Bitmap 质量压缩 以及bitmap保存变大的原因

Bitmap的质量压缩

摘要:

文章目录

  • Bitmap的质量压缩
    • 质量压缩描述
    • 质量压缩原理
    • 质量压缩实现
    • 所遇问题

质量压缩描述

​ 质量压缩主要借助Bitmap中的compress方法实现

public boolean compress(CompressFormat format, int quality, OutputStream stream) {}
    

这个方法用来将位图的压缩变体写入指定的输出流(OutputStream)中,如果返回true,则可以通过将相应的输入流传递给BitmapFactory.decodestream()来重建位图,注意,并非所有图片格式都直接支持所有位图配置,因此BitmapFactory返回的位图可能位于不同的位深度,可能丢失了每个像素的透明度(例如,jpeg仅支持不透明像素)

  • format是压缩后的图片的格式,可取值:Bitmap.CompressFormat .JPEG、.PNG、.WEBP。
  • quality的取值范围为[0,100],值越小,经过压缩后图片失真越严重,图片文件也会越小,100表示不压缩(PNG格式的图片会忽略quality值的设定,quality值无效)
  • stream指定压缩的图片输出的地方,比如某文件

质量压缩原理

原理:保持像素的前提下改变图片的位深及透明度,(即:通过算法抠掉(同化)了图片中的一些某个些点附近相近的像素),达到降低质量压缩文件大小的目的

注意:它其实只能实现对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变大

你可能感兴趣的:(Android,Bitmap)