关于Android图片资源瘦身的奇思妙想

版权声明:本文由张绍文原创文章,转载请注明出处: 
文章原文连接:https://www.qcloud.com/community/article/77android

来源:腾云阁 https://www.qcloud.com/community算法

分析大部分apk,能够发如今android中图片应用较多的主要包括jpg和png两种资源类型。对于颜色不少尺寸大的图片通常用jpg,主要适用场景是用于作背景展现,这类图片除了调整压缩参数作有损压缩外,无损压缩可优化的空间则通常不会太大。相对而言,png图片的应用场景更多,一方面是因为其拥有透明值,另外一方面也由于其能够方便缩放(九宫格)。png这部分资源通常在apk中占用了比较大的体积,不少时候能够经过tinypng有损压缩减小颜色表来减小体积,但容易被像素眼的设计师挑战;另外一种方案是无损压缩,常规方法包括转换为索引图片、改变编码方式、提高压缩级别等,相较而言体积小了但效果同样,本文也将就这一方面结合源码对其在Android的实践和问题进行阐述。工具

一.选择压缩工具

首先是选择压缩工具的问题,在这以前先看下系统是如何作的。android的aapt在编译阶段实际上是会对png图片进行压缩的,用的则是libpng和zlib,这个能够用aapt的源码佐证:优化

  • 用libpng对图片进行预处理
  • 用zlib对预处理后的图片进行压缩生成新图片

能够看到aapt对图片的压缩等级使用了最高等级9,期间系统也会作颜色表转换,这样能够减小很大一部分图片的体积,但系统的压缩方案是否是天衣无缝呢?目前经常使用的无损压缩大概有Pngrewrite、pngcrush、optipng、advancecom、pngout,参考了不少文章,得出的结果是pngout仍然是王者,毕竟是Ken神童(听说Doom and Quake的做者John都尊敬他,作游戏的确定都知道John )写的。另外因为pngout能够很好的支持命令行,方便放到编译脚本中自动化,因此暂时选它好了。google

二.实践案例

压缩工具选好了,第二步即是实验了。拿手Q为例,直接对手Q中的全部png压一遍,Pngout的速度确实通常,对4千张图片所有处理一遍大概须要13分钟,不过这个过程只须要在本地作一遍,因此能够忍受,但处理完的结果不理想,由于没什么效果,减少量为十几KB~~ 仔细分析得知这里面犯浑做怪的居然是aapt,因为先调pngout再调aapt会致使压缩效果覆盖。那么可不能够关闭aapt呢? 查看aapt的参数,关于压缩相关的只有下面这两个参数:编码

其中crunch即是预处理资源了,可是没有关闭crunch的参数。。。。有点技穷了对不对。只能去源码中找灵感了,看aapt的源码:spa

google把它隐藏了,没有打印出来给用户~打开这个参数,在手Q中资源打包脚本处分别加入--no-crunch参数,即可以把系统压缩给屏蔽掉了,样式以下:命令行

至于为何设置了这个参数就能够屏蔽呢,其实源码调用过程以下:设计

第1步 (Main.cpp)code

第2步 (Command.cpp)

第3步 (Resource.cpp)

终结: (Resource.cpp)

但是实验尚未结束,由于这样屏蔽掉会出现奇葩的景象,获得的手Q画面效果以下:

为何呢?仔细分析发现九宫格图片被压出问题了,aapt在处理png图片时会判断是否是九宫格图片,若是是则作特殊预处理:

do_9patch其实主要的是九宫格信息弄出来,写入到info9Patch字段,并最终写入nptc的chunk中:

到这里又回到第一步为何我说Ken是神童了,由于Pngout能够选择chunk进行压缩,因此解决方案即是:对于九宫格图片,咱们单独拎出来,先用aapt的aapt crunch进行预处理获得npTc字段,再用pngout在压缩时调用"knptc"参数保护一下npTc块,这样便获得了正确的九宫格图片,安装包的效果图也就正常了。

三.总结

上面大概就是png无损压缩在android中应用的基本思路和遇到的问题,概括为一句话即是:替换掉系统的压缩算法。若是你不嫌麻烦和喜欢折腾的话能够在你的apk使用一下,效果仍是很是显著的。不改变安装包内图片像素内容,轻轻松松减小几百K体积,何乐而不为呢?

相关文章
相关标签/搜索