android bitmap优化

参考文章: 最详细的Android图片压缩攻略,让你一次过足瘾

bitmap内存计算方式:

bitmap内存大小 = (图片长度 x 图片宽度)(分辨率压缩) x 单位像素占用的字节数 (改变编码格式);

  • 不过,这样的说法并不准确,我们常说的 图片长* 图片宽,这里最终需要换成px作为单位去计算图片大小。在 Android 原生的 Bitmap 操作中,某些场景下,图片被加载进内存时的分辨率会经过一层转换,所以,虽然最终图片大小的计算公式仍旧是分辨率像素点大小,但此时的分辨率已不是图片本身的分辨率了;
  • 而且当图片放在 res 内的不同目录中,最终图片加载进内存所占据的大小会不一样,因为系统在加载 res 目录下的资源图片时,会根据图片存放的不同目录做一次分辨率的转换,而转换的规则是

  • 新图的高度 = 原图高度 * (设备的 dpi / 目录对应的 dpi )
    新图的宽度 = 原图宽度 * (设备的 dpi / 目录对应的 dpi )

  • 因此同一个 app,但跑在不同 dpi 设备上,同样的界面,但所耗的内存有可能是不一样的

两种bitmap内存优化方式:

1.质量压缩(不会减少图片本身大小,但是会减少file文件大小)

在Android中,对图片进行质量压缩,通常我们的实现方式如下所示:

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//quality 为0~100,0表示最小体积,100表示最高质量,对应体积也是最大
bitmap.compress(Bitmap.CompressFormat.JPEG, quality , outputStream);

在上述代码中,我们选择的压缩格式是CompressFormat.JPEG,除此之外还有两个选择:

其一,CompressFormat.PNG,PNG格式是无损的,它无法再进行质量压缩quality这个参数就没有作用了,会被忽略,所以最后图片保存成的文件大小不会有变化;

其二,CompressFormat.WEBP,这个格式是google推出的图片格式,它会比JPEG更加省空间,经过实测大概可以优化30%左右。

Bitmap的compress这个API 最后调用了函数encoder->encodeStream(…)编码保存本地。该函数是调用skia引擎来对图片进行编码压缩;Skia 是一个 Google 自己维护的 c++ 实现的图像引擎,实现了各种图像处理功能,并且广泛地应用于谷歌自己和其它公司的产品中(如:Chrome、Firefox、 Android等)

 Skia 在 Android 中提供了基本的画图和简单的编解码功能,实际会调用 libjpeg.so 动态库进行编码压缩,Android编码保存图片的逻辑是Java层函数→Native函数→Skia函数→对应第三库函数(例如libjpeg)。 libjpeg是一个C语音编写的高效JPEG图像处理库,Android系统在7.0版本之前内部使用的是libjpeg非turbo版,并且为了性能关闭了Huffman编码(optimize_coding 设为 false),使用的是默认的哈夫曼表。在7.0之后的系统内部启用了Huffman进行编码,根据实际图片去计算相对应的哈夫曼表

        去获取每一个元素,对于图片就是每一个像素中 argb 的权重,去循环整个图片的像素信息,这无疑是非常消耗性能的,所以早期 android 就使用了默认的哈夫曼表进行图片压缩。

哈夫曼算法(还有定长算术编码)举例: Android 中图片压缩分析(上) - 腾讯云开发者社区-腾讯云

所以想要提升图片压缩率的可以从libjpeg库着手,网上资料也不少,后续有机会可以测试一下其他可替代的so库。

2.尺寸压缩(包含采样率压缩 + 长宽缩放)

inJustDecodeBounds为true会禁止为bitmap分配内存,获取到bitmap的长宽值,计算出insampelsize采样率;

 为什么要比较实际宽高和目标宽高比呢?

假设有张原图宽高3840x2400,要压缩成1920x1080,实际不可能100%压缩到这个值,因为要图片压缩保持宽高比,所以采用优先保证以最短边进行比例缩放

计算较短边举例:   3840/1920 = 2,   2400/1080 = 2.2,因此看出高缩放程度更大,优先保证高的缩放,scale = 2400/1080=2.22,因此宽width = 2840/2.2 = 1728,最终结果1728x1080;

鲁班库和微信是会设置长宽边不同的缩放阶层,根据不同的长宽比例,设置不同压缩率;

而Driver app项目中会设定一个最短边标准960, 如果长和宽中的最短值大于960,将会一直压缩,直到这个最短边小于等于960;

鲁班框架的缺点:

  • 不支持多文件合理并行压缩

  • 质量压缩写死 60不能自己选

  • 没有提供图片输出格式选择

  • 可能出现内存泄漏,需要自己合理处理生命周期

总流程如下:

3.改变编码格式:

Bitmap裁剪方法(createBitmap):

public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)

matrix:来实现旋转等多种效果的截图;

Bitmap source:需要截图的原始图

int x:起始x坐标

int y:起始y坐标

int width:要截的图的宽度

int height:要截的图的宽度

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值