摘要:
质量压缩主要借助Bitmap中的compress方法实现
public boolean compress(CompressFormat format, int quality, OutputStream stream) {}
这个方法用来将位图的压缩变体写入指定的输出流(OutputStream)中,如果返回true,则可以通过将相应的输入流传递给BitmapFactory.decodestream()来重建位图,注意,并非所有图片格式都直接支持所有位图配置,因此BitmapFactory返回的位图可能位于不同的位深度,可能丢失了每个像素的透明度(例如,jpeg仅支持不透明像素)
原理:保持像素的前提下改变图片的位深及透明度,(即:通过算法抠掉(同化)了图片中的一些某个些点附近相近的像素),达到降低质量压缩文件大小的目的
注意:它其实只能实现对file的影响,对加载这个图片出来的bitmap内存是无法节省的,还是那么大。因为bitmap在内存中的大小是按照像素计算的,也就是width*height,对于质量压缩,并不会改变图片的真实的像素(像素大小不会变)
Bitmap 内存大小(粗略计算) = weight * height*字节数(单位像素占的字节数)
Bitmap常见有2种编码方式:ARGB_8888和RGB_565,ARGB_8888每个像素点4个byte,RGB_565是2个byte,一般都采用ARGB_8888这种。那么常见的1080*1920的图片内存占用就是:
1920 x 1080 x 4 = 7.9M
Android性能优化之图片压缩优化
Android图片编码机制深度解析
android仿微信高效压缩图片(libjpeg)
Android性能优化:Bitmap详解&你的Bitmap占多大内存
/**
* 质量压缩
* */
public static boolean isCompressBitmapToFile(Bitmap image,File file,int maxSize) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中,这里从90开始
int quality = 90;
image.compress(Bitmap.CompressFormat.JPEG, quality, baos);
Log.d("Bitmap","before=="+baos.toByteArray().length);
// 循环判断如果压缩后图片是否大于maxSize(例如:100kb),大于继续压缩
while (baos.toByteArray().length / 1024 > maxSize) {
baos.reset(); // 重置baos即清空baos
quality -= 10;// 每次都减少10
// 这里压缩options,把压缩后的数据存放到baos中
image.compress(Bitmap.CompressFormat.JPEG, quality, baos);
}
Log.d("Bitmap","after=="+baos.toByteArray().length);
try{
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
return true;
}catch (Exception e){
e.printStackTrace();
}
return false;
}
当压缩和保存分开写的时候遇到了保存的图片变大的情况:
相关代码:
public static boolean saveBitmapToJPG(Bitmap bitmap, File file) {
if (bitmap == null)
return false;
FileOutputStream fos = null;
if (file.exists()){
file.delete();
}
try {
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
fos.close();
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 质量压缩方法
*
* @param image
* @return
*/
public static Bitmap compressImage(Bitmap image,int maxSize) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int quality = 100;
image.compress(Bitmap.CompressFormat.JPEG, quality, baos);
Log.d("Bitmap","before"+baos.toByteArray().length);
// 100 循环判断如果压缩后图片是否大于100kb,大于继续压缩
while (baos.toByteArray().length / 1024 > maxSize) {
baos.reset(); // 重置baos即清空baos
quality -= 10;// 每次都减少10
// 这里压缩options,把压缩后的数据存放到baos中
image.compress(Bitmap.CompressFormat.JPEG, quality, baos);
}
Log.d("Bitmap","After"+baos.toByteArray().length);
// 把压缩后的数据baos存放到ByteArrayInputStream中
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
// 把ByteArrayInputStream数据生成图片
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
return bitmap;
}
原因是中间压缩后生成的Bitmap进行了一次编码,导致保存后的Bitmap变大