挥舞着指尖,谱写指尖的艺术
两种压缩图片的方式
-
Bitmap.Factory
-
bitmap.compress
阅读完本文你的收获
- Bitmap.Factory是怎样进行图片缩小的;
- 为什么bitmap.compress压缩图片了,还是造成了OOM;
- 怎样去正确的选择一个适合自己的压缩方式;
进入正题
1. ComPress图片质量压缩
我们在实际开发中,经常会用后台返回的url地址,进行图片的下载,或者说是调用相机拍摄照片时,图片都会异常的大,一张图片3M,4M,大量如此,OOM是在所难免的。
先上代码
public static Bitmap simaplePic(Bitmap bitmap) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG,70,stream);
stream.close();
return bitmap;
}
我们传入一个bitmap类型,通过
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG,70,stream);
两行代码去执行图片的缩小,创建一个字节输出流,调用compress方法,三个参数分别对应:
- 图片后缀格式;
- 保留原始图片的70%质量;
- 字节输出流;
后缀格式不用说,第二个参数保 留原始图片的70%质量 ,意思是压缩了30%的质量。
- 这种压缩方法之所以称之为质量压缩,是因为它不会减少图片的像素。
- 它是在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的。
- 进过它压缩的图片文件大小会有改变,但是导入成bitmap后占得内存是不变的。
- 因为要保持像素不变,所以它就无法无限压缩,到达一个值之后就不会继续变小了。
- 显然这个方法并不适用于缩略图,其实也不适用于想通过压缩图片减少内存,仅仅适用于想在保证图片质量的同时减少文件大小的情况而已。
2. Bitmap.Factory像素/采样率图片压缩
这种方式就会适用于缩略图,减少占用内存。我这里用的是后台给的url地址,下载图片。
铁汁 ~ 上代码
public class CompressPic {
/**
* 图片缩小工具类
* @param stream 图片的字节
* @param reqWidth 自定义想要缩小的宽
* @param reqHeight 自定义想要缩小的高
* @return
*/
public static Bitmap decodeBitmap(byte[] stream, int reqWidth, int reqHeight){
//获取当前图片的高
int inPictureHeight;
//获取当前图片的宽
int inPictureWidth;
//默认宽高都压缩一倍
int inSample = 1;
BitmapFactory.Options options = new BitmapFactory.Options();
// 设置为true时,bitmap = null,不加载进内存,但可以得到图片的宽高
//只获取图片的大小信息,而不是将整张图片载入在内存中,避免内存溢出
options.inJustDecodeBounds = true;
//byte, byte.length, options
BitmapFactory.decodeByteArray(stream, 0,stream.length, options);
//获取图片资源的宽高
inPictureHeight = options.outHeight;
inPictureWidth = options.outWidth;
//图片缩小算法
BitmapFactory.Options resultOption = calculationWidthAndHeight(options,inPictureHeight,inPictureWidth,reqWidth,reqHeight,inSample);
return BitmapFactory.decodeByteArray(stream,0,stream.length,resultOption);
}
private static BitmapFactory.Options calculationWidthAndHeight(BitmapFactory.Options options, int inPictureHeight, int inPictureWidth,
int reqWidth, int reqHeight, int inSample) {
//更改原始像素为reqWidth,reqHeight比例,如果原始像素比自定义像素要小,则跳过此步骤,都比自定义像素要小了,还压缩个啥
if (inPictureWidth > reqWidth || inPictureHeight >reqHeight){
while (inPictureWidth / inSample > reqWidth || inPictureHeight / inSample >reqHeight){
//要求取值为n的2次冥,不是二次幂则四舍五入到最近的二次幂
inSample = inSample *2;
}
Log.e("TAG",inSample+"");
}
//得到的最终值
options.inSampleSize = inSample;
//设置编码为RGB_565,默认为ARGB_8888
options.inPreferredConfig = Bitmap.Config.RGB_565;
//设置为false,得到实际的bitmap,不然只会得到宽高等信息
options.inJustDecodeBounds = false;
//设置图片可以复用
options.inMutable = true;
return options;
}
}
调用工具类
bitmap = CompressPic.decodeBitmap(response.body().bytes(),100,100);
主要用到的几个参数:
-
options.inJustDecodeBounds;
该参数设置为true时,不加载图片资源进内存,意思是bitmap返回的是null,但是可以拿到图片的一些信息,比如它的宽高。 -
options.isSampleSize;
设置要缩放的倍数,以n * 2开始扩展,n * 0.6这样的,默认四舍五入倍数,800 x 600像素,该值设置为2时,宽高默认都缩小两倍,即总体缩了4倍。 -
options.inPreferrConfig;
设置图片编码格式,默认ARGB_888
每个像素4字节,例如800 x 600,则字节位 800 x 600 x 4。
RGB_565,每个像素2个字节,800 x 600 x2。 -
options.inMutable;
图片复用, 不多做赘述。
总结
质量压缩:实质上没减少bitmap内存开销,只是图片文件大小变小了;
像素压缩:达到了内存压缩方式;