package cc.util.android.image;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.util.Log; /**
* A class for helping deal the bitmap,
* like: get the orientation of the bitmap, compress bitmap etc.
* @author wangcccong
* @version 1.140122
* crated at: 2014-03-22
* update at: 2014-06-26
*/
public class BitmapHelper { /**
* get the orientation of the bitmap {@link android.media.ExifInterface}
* @param path
* @return
*/
public final static int getDegress(String path) {
int degree = 0;
try {
ExifInterface exifInterface = new ExifInterface(path);
int orientation = exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
} /**
* rotate the bitmap
* @param bitmap
* @param degress
* @return
*/
public static Bitmap rotateBitmap(Bitmap bitmap, int degress) {
if (bitmap != null) {
Matrix m = new Matrix();
m.postRotate(degress);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
return bitmap;
}
return bitmap;
} /**
* caculate the bitmap sampleSize
* @param path
* @return
*/
public final static int caculateInSampleSize(BitmapFactory.Options options, int rqsW, int rqsH) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (rqsW == 0 || rqsH == 0) return 1;
if (height > rqsH || width > rqsW) {
final int heightRatio = Math.round((float) height/ (float) rqsH);
final int widthRatio = Math.round((float) width / (float) rqsW);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
} /**
* 压缩指定路径的图片,并得到图片对象
* @param context
* @param path bitmap source path
* @return Bitmap {@link android.graphics.Bitmap}
*/
public final static Bitmap compressBitmap(String path, int rqsW, int rqsH) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
options.inSampleSize = caculateInSampleSize(options, rqsW, rqsH);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
} /**
* 压缩指定路径图片,并将其保存在缓存目录中,通过isDelSrc判定是否删除源文件,并获取到缓存后的图片路径
* @param context
* @param srcPath
* @param rqsW
* @param rqsH
* @param isDelSrc
* @return
*/
public final static String compressBitmap(Context context, String srcPath, int rqsW, int rqsH, boolean isDelSrc) {
Bitmap bitmap = compressBitmap(srcPath, rqsW, rqsH);
File srcFile = new File(srcPath);
String desPath = getImageCacheDir(context) + srcFile.getName();
int degree = getDegress(srcPath);
try {
if (degree != 0) bitmap = rotateBitmap(bitmap, degree);
File file = new File(desPath);
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 70, fos);
fos.close();
if (isDelSrc) srcFile.deleteOnExit();
} catch (Exception e) {
// TODO: handle exception
Log.e("BitmapHelper-->compressBitmap", e.getMessage()+"");
}
return desPath;
} /**
* 此方法过期,该方法可能造成OutOfMemoryError,使用不含isAdjust参数的方法
* @param is
* @param reqsW
* @param reqsH
* @param isAdjust
* @return
*/
@Deprecated
public final static Bitmap compressBitmap(InputStream is, int reqsW, int reqsH, boolean isAdjust) {
Bitmap bitmap = BitmapFactory.decodeStream(is);
return compressBitmap(bitmap, reqsW, reqsH, isAdjust);
} /**
* 压缩某个输入流中的图片,可以解决网络输入流压缩问题,并得到图片对象
* @param context
* @param path bitmap source path
* @return Bitmap {@link android.graphics.Bitmap}
*/
public final static Bitmap compressBitmap(InputStream is, int reqsW, int reqsH) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ReadableByteChannel channel = Channels.newChannel(is);
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (channel.read(buffer) != -1) {
buffer.flip();
while (buffer.hasRemaining()) baos.write(buffer.get());
buffer.clear();
}
byte[] bts = baos.toByteArray();
Bitmap bitmap = compressBitmap(bts, reqsW, reqsH);
is.close();
channel.close();
baos.close();
return bitmap;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return null;
}
} /**
* 压缩指定byte[]图片,并得到压缩后的图像
* @param bts
* @param reqsW
* @param reqsH
* @return
*/
public final static Bitmap compressBitmap(byte[] bts, int reqsW, int reqsH) {
final Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bts, 0, bts.length, options);
options.inSampleSize = caculateInSampleSize(options, reqsW, reqsH);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(bts, 0, bts.length, options);
} /**
* 此方法已过期,该方法可能造成OutOfMemoryError,使用不含isAdjust参数的方法
* @param bitmap
* @param reqsW
* @param reqsH
* @return
*/
@Deprecated
public final static Bitmap compressBitmap(Bitmap bitmap, int reqsW, int reqsH, boolean isAdjust) {
if (bitmap == null || reqsW == 0 || reqsH == 0) return bitmap;
if (bitmap.getWidth() > reqsW || bitmap.getHeight() > reqsH) {
float scaleX = new BigDecimal(reqsW).divide(new BigDecimal(bitmap.getWidth()), 4, RoundingMode.DOWN).floatValue();
float scaleY = new BigDecimal(reqsH).divide(new BigDecimal(bitmap.getHeight()), 4, RoundingMode.DOWN).floatValue();
if (isAdjust) {
scaleX = scaleX < scaleY ? scaleX : scaleY;
scaleY = scaleX;
}
Matrix matrix = new Matrix();
matrix.postScale(scaleX, scaleY);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
return bitmap;
} /**
* 压缩已存在的图片对象,并返回压缩后的图片
* @param bitmap
* @param reqsW
* @param reqsH
* @return
*/
public final static Bitmap compressBitmap(Bitmap bitmap, int reqsW, int reqsH) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 100, baos);
byte[] bts = baos.toByteArray();
Bitmap res = compressBitmap(bts, reqsW, reqsH);
baos.close();
return res;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return bitmap;
}
} /**
* 此方法过期,该方法可能造成OutOfMemoryError,使用不含isAdjust参数的方法
* get bitmap form resource dictory, and then compress bitmap according to reqsW and reqsH
* @param res {@link android.content.res.Resources}
* @param resID
* @param reqsW
* @param reqsH
* @return
*/
@Deprecated
public final static Bitmap compressBitmap(Resources res, int resID, int reqsW, int reqsH, boolean isAdjust) {
Bitmap bitmap = BitmapFactory.decodeResource(res, resID);
return compressBitmap(bitmap, reqsW, reqsH, isAdjust);
} /**
* 压缩资源图片,并返回图片对象
* @param res {@link android.content.res.Resources}
* @param resID
* @param reqsW
* @param reqsH
* @return
*/
public final static Bitmap compressBitmap(Resources res, int resID, int reqsW, int reqsH) {
final Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resID, options);
options.inSampleSize = caculateInSampleSize(options, reqsW, reqsH);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resID, options);
} /**
* 基于质量的压缩算法, 此方法未 解决压缩后图像失真问题
* <br> 可先调用比例压缩适当压缩图片后,再调用此方法可解决上述问题
* @param bts
* @param maxBytes 压缩后的图像最大大小 单位为byte
* @return
*/
public final static Bitmap compressBitmap(Bitmap bitmap, long maxBytes) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 100, baos);
int options = 90;
while (baos.toByteArray().length > maxBytes) {
baos.reset();
bitmap.compress(CompressFormat.PNG, options, baos);
options -= 10;
}
byte[] bts = baos.toByteArray();
Bitmap bmp = BitmapFactory.decodeByteArray(bts, 0, bts.length);
baos.close();
return bmp;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
} // public final static Bitmap compressBitmap(InputStream is, long maxBytes) {
// try {
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// byte[] bts = new byte[1024];
// while (is.read(bts) != -1) baos.write(bts, 0, bts.length);
// is.close();
// int options = 100;
// while (baos.toByteArray().length > maxBytes) {
//
// }
// } catch (Exception e) {
// // TODO: handle exception
// }
// } /**
* 得到指定路径图片的options
* @param srcPath
* @return Options {@link android.graphics.BitmapFactory.Options}
*/
public final static Options getBitmapOptions(String srcPath) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(srcPath, options);
return options;
} /**
* 获取图片缓存路径
* @param context
* @return
*/
private static String getImageCacheDir(Context context) {
String dir = FileHelper.getCacheDir(context) + "Image" + File.separator;
File file = new File(dir);
if (!file.exists()) file.mkdirs();
return dir;
}
}

Android 图片压缩,基于比例和质量压缩的更多相关文章

  1. Android中图片压缩(质量压缩和尺寸压缩)

    关于Android 图片压缩的学习: 自己总结分为质量压缩和像素压缩.质量压缩即:将Bitmap对象保存到对应路径下是所占用的内存减小,但是当你重新读取压缩后的file为Bitmap时,它所占用的内存 ...

  2. Golang 编写的图片压缩程序,质量、尺寸压缩,批量、单张压缩

    目录: 前序 效果图 简介 全部代码 前序: 接触 golang 不久,一直是边学边做,边总结,深深感到这门语言的魅力,等下要跟大家分享是最近项目 服务端 用到的图片压缩程序,我单独分离了出来,做成了 ...

  3. Android图片压缩方法总结

    本文总结Android应用开发中三种常见的图片压缩方法,分别是:质量压缩法.比例压缩法(根据路径获取图片并压缩)和比例压缩法(根据Bitmap图片压缩).   第一:质量压缩方法:   ? 1 2 3 ...

  4. android图片压缩方法

    android 图片压缩方法: 第一:质量压缩法: private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = ...

  5. android图片压缩的3种方法实例

    android 图片压缩方法: 第一:质量压缩法: private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = ...

  6. 性能优化——Android图片压缩与优化的几种方式

    图片优化压缩方式大概可以分为以下几类:更换图片格式,质量压缩,采样率压缩,缩放压缩,调用jpeg压缩等1.设置图片格式Android目前常用的图片格式有png,jpeg和webp,png:无损压缩图片 ...

  7. android图片压缩总结

    一.bitmap 图片格式介绍 android中图片是以bitmap形式存在的,那么bitmap所占内存,直接影响到了应用所占内存大小,首先要知道bitmap所占内存大小计算方式: bitmap内存大 ...

  8. Android 图片压缩各种方式

       前言:由于公司项目当中需要用到压缩这块的相应技术,之前也做过的图片压缩都不是特别的理想, 所以这次花了很多心思,仔细研究和在网上找到了很多相对应的资料.为了就是 以后再做的时候直接拿来用就可以了 ...

  9. 利用反射快速给Model实体赋值 使用 Task 简化异步编程 Guid ToString 格式知多少?(GUID 格式) Parallel Programming-实现并行操作的流水线(生产者、消费者) c# 无损高质量压缩图片代码 8种主要排序算法的C#实现 (一) 8种主要排序算法的C#实现 (二)

    试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...

随机推荐

  1. 牛客网剑指offer刷题总结

    二维数组中的查找: 题目描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 两 ...

  2. SDNU 1206.蚂蚁感冒 【代码如此简单,思维练习】【7月29】

    蚂蚁感冒 Description 长100厘米的细长直杆子上有n仅仅蚂蚁. 它们的头有的朝左,有的朝右. 每仅仅蚂蚁都仅仅能沿着杆子向前爬,速度是1厘米/秒. 当两仅仅蚂蚁碰面时.它们会同一时候掉头往 ...

  3. python RESTful API框架:Eve 高速入门

    Eve是一款Python的REST API框架.用于公布高可定制的.全功能的RESTful的Web服务.帮你轻松创建和部署API,本文翻译自Eve官方站点: http://python-eve.org ...

  4. RingtoneManager-获得系统当前的铃声

    我们直接看代码 bt1 = (Button) findViewById(R.id.bt1); bt2 = (Button) findViewById(R.id.bt2); bt3 = (Button) ...

  5. 深入理解Linux启动过程

    深入理解Linux启动过程       本文详细分析了Linux桌面操作系统的启动过程,涉及到BIOS系统.LILO 和GRUB引导装载程序,以及bootsect.setup.vmlinux等映像文件 ...

  6. 非常有用的sql脚本

    /*sql 语法学习*/ /*函数的学习---------------------------------------*/ 获取当前时间(时/分/秒):select convert(varchar(1 ...

  7. Google Web Toolkit(GWT) 在windows下环境搭建

    1.什么是GWT? Google Web Toolkit(简称GWT,读作/ˈɡwɪt/),是一个前端使用JavaScript,后端使用Java的AJAX framework,以Apache许可证2. ...

  8. android 闹钟提醒并且在锁屏下弹出Dialog对话框并播放铃声和震动

    android 闹钟提醒并且在锁屏下弹出Dialog对话框并播放铃声和震动            1.先简单设置一个闹钟提醒事件: //设置闹钟 mSetting.setOnClickListener ...

  9. java set转list,数组与list的转换

    读zookeeper的源码(zookeeper.java)时发现的,平时没有怎么注意: private final ZKWatchManager watchManager; List<Strin ...

  10. 作为一个新人,怎样学习嵌入式Linux?(韦东山)

    这篇文章是引用韦老师的部分关于新人怎么学习嵌入式Linux的经验,引用如下: 1.电脑一开机,那些界面是谁显示的?是BIOS,它做什么?一些自检,然后从硬盘上读入windows,并启动它. 类似的, ...