美文网首页
[Point] Android Bitmap 压缩

[Point] Android Bitmap 压缩

作者: simplehych | 来源:发表于2018-12-17 11:31 被阅读0次

Android Bitmap

Android 中的图片是以 Bitmap 方式存在的,绘制的时候也是 Bitmap,直接影响到 app 运行时的内存。

在 Android 中 Bitmap 所占用内存的计算公式是:

图片长度 * 图片宽度 * 像素点的字节数

Bitmap.getByteCount()、Bitmap.getAllocationByteCount()和Bitmap.compress(...)

public int getByteCount()
返回可用于存储该位图像素的最小字节。
从 Build.VERSION_CODES.KITKAT开始,该方法结果不再用于确定 bitmap 所使用的内存。可以使用 getAllocationByteCount()

public int getAllocationByteCount()
返回用于存储该位图像素已经分配的内存大小。
如果重用位图以解码其他更小尺寸的位图或者手动重新配置,该方法的结果可能大于 getByteCount() 的结果。例如 reconfigure(int, int, Config), setWidth(int), setHeight(int), setConfig(Bitmap.Config), 和 BitmapFactory.Options.inBitmap。如果没有以这种方式修改 bitmap,那么它将和 getByteCount() 的值相同。

public boolean compress(Bitmap.CompressFormat format, int quality, OutputStream stream)
将压缩的位图放到指定的输出流,如果返回 true,通过将相应的输入流传递给 BitmapFactory.decodeStream() 可以重建位图。注意,并非所有的 Formats 都支持位图的直接配置,所以从 BitmapFactory 返回的位图可能是不同的位深。或者丢失每个像素的 Alpha。例如:jpeg 仅支持不透明像素
这个方法可能需要几秒才能完成,所以应该再工作线程调用它。

图片格式

类型 描述 eg
ALPHA_8 每个像素都存储一个半透明通道 0000 0000 8bits 1B
ARGB_4444 此字段已在 API 13中弃用。此配置质量较差,建议使用ARGB_8888 0000 0000 0000 0000 16bits 2B
ARGB_8888 每个像素存储4个字节 0000 0000 0000 0000 0000 0000 0000 0000 32bits 4B
RGB_565 每个像素存储在2个字节中,只有 RGB 通道被编码:红色以5位精度存储(32个可能值),绿色以6位精度存储(64个可能值),蓝色存储为5位精度 0000 0000 0000 0000 16bits 2B

压缩方法

  1. 质量压缩
private Bitmap compressQuality(Bitmap bitmap){
    Bitmap bm = BitmapFactory.decodeResource(getResource(), R.drawable.tes)
    int beforeBmCount = bitmap.getByteCount();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
    int compressedLen = baos.toByteArray().length;
    Bitmap compressBm = BitmapFactory.decodeByteArray(out.toByteArray(), 0,         compressedLen);
    int afterBmCount = compressBm.getByteCount();
    return compressBm;
}

结果:
1. beforeBmCountafterBmCount 是相等的。
2. 输出流的长度 compressedLen 是变小了

经过 BitmapFactory.decodeByteArray() 对压缩后的 byte[] 进行解码后得到的 bitmap 和未压缩的是一样的。

Bitmap.compress()压缩的是存储大小,即保存在本地 disk 的大小(通过流的方式,流确实变小了)。

质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位神及透明度,来达到压缩图片的目的,图片的长、宽、像素都不会改变,那么 bitmap 所占内存大小是不会变的。

第二个参数 quality,可以调节你压缩的比例,但值得注意的是,质量压缩对 png 这种无损压缩是没有作用的。

  1. 采样率压缩
private Bitmap compressSampling(){
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 2;
    Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test. options);
    return bm;
}

采样率压缩的原理是缩放 bitmap 的尺寸,通过调节 inSampleSize 参数,比如调节为2,宽高就会为原来的1/2,内存变回原来的 1/4

  1. 放缩法压缩
private Bitmap compressMatrix(Bitmap bm){
    Matrix matrix = new Matrix();
    matrix.setScale(0.5f, 0.5f);
    Bitmap.createBitmap(bitmap, 0, 0, bm.getWidth, bm.getHeigh, matrix, true);
}

放缩法通过矩阵对图片进行裁剪,也是通过缩放图片尺寸,来达到压缩图片的效果,和采样率原理一样。

  1. RGB_565压缩
private Bitmap compressRGB565(){
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    return BitmapFactory.decodeResource(getResource(), R.drawable.test, options);
}

这里通过压缩像素占用的内存来达到压缩的效果,一般不建议使用 ARGB_4444,画质很低,如果对透明度没有要求,建议改成 RGB_565,相比 ARGB_8888将节省一般的内存开销。

  1. createScaledBitmap
private Bitmap compressScaleBitmap(Bitmap bm){
     Bitmap bitmap = Bitmap.createScaleBitmap(bm, 600, 900, true);
     return bitmap;
}

将图片的大小压缩成用户期望的大小,来减少内存。

case

description
创建桌面快捷方式时失败,甚至部分机型崩溃。

analyse
1. 版本适配问题,26以上方式不一样
2. Bitmap 太大,发生异常

项目中已经进行了适配,对 bitmap 进行了分析,最终锁定 bitmap 太大,导致问题。

solve

使用createScaledBitmap的方式更为简单,下面使用压缩方式为例编写:

ByteArrayOutputStream baos = new ByteArrayOutStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] bytes = baos.toByteArray();

BitmapFactory.Options options = new BitmapFactory.Options();
// 只获取图片的大小信息,而不是将整张图片载入在内存中,避免内存溢出
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
int height = options.outHeight;
int width = options.outWidth;
int inSampleSize = 2;
int minLen = Math.min(height, width);
if(minLen > 100) {
    float ratio = (float) minLen / 100.0f;
    inSampleSize = (int) ratio;
}
// 计算好压缩比例,设置加载原图
options.inJustDecodeBounds = false;
// 设置计算好的压缩比例
options.inSampleSize = inSampleSize;
Bitmap bm = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
...

// 内存优化
// 1. 内存泄漏
// 2. 内存占用 bitmap 压缩
bitmap.recycle()

参考学习:
https://developer.android.com/reference/android/graphics/Bitmap.html
https://blog.csdn.net/adam_ling/article/details/52346741
https://www.jb51.net/article/132775.htm
https://blog.csdn.net/u010652002/article/details/72676723

相关文章

  • [Point] Android Bitmap 压缩

    Android Bitmap Android 中的图片是以 Bitmap 方式存在的,绘制的时候也是 Bitmap...

  • 2019-11-05

    Bitmap Bitmap 细说Bitmap bitmap的六种压缩方式,Android图片压缩 1.先讲讲屏幕密...

  • 收集_Android源码文章

    一、Bitmap: Android bitmap压缩优化方案Android性能优化系列之Bitmap图片优化 二、...

  • Bitmap图片压缩

    Android中图片是以bitmap形式存在的,这篇文章主要介绍了Android实现图片压缩(bitmap的六种压...

  • Android

    Android常用图片压缩方式 质量压缩 尺寸压缩 1. 质量压缩 质量压缩通过相应算法进行优化Bitmap的位深...

  • Android NDK编译libjpeg-turbo压缩图片

    Android开发中,我们经常要面对图片压缩,大部分人使用Android Bitmap进行压缩,还有一些使用lib...

  • 关于android 图片压缩你需要知道的事

    关键词: Bitmap,质量压缩,比例压缩,采样率压缩,微信分享 前言 android 系统的图片压缩大体上有三种...

  • android图片压缩

    先生成一个长宽被缩放的bitmap 再压缩到100k以下 关于Bitmap的compress方法,android ...

  • libjpeg-turbo 图片压缩

    android7.0之前,Bitmap.compress不支持哈夫曼压缩算法,压缩效率不高,因此引入libTurb...

  • bitmap的六种压缩方式,Android图片压缩

    此处分享一个图片的压缩处理方式 : bitmap的六种压缩方式,Android图片压缩 转载链接,点击查看详情 !

网友评论

      本文标题:[Point] Android Bitmap 压缩

      本文链接:https://www.haomeiwen.com/subject/imyghqtx.html