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

来源:腾云阁 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可以很好的支持命令行,方便放到编译脚本中自动化,所以暂时选它好了。

二.实践案例

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

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

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

至于为什么设置了这个参数就可以屏蔽呢,其实源码调用过程如下:

第1步 (Main.cpp)

第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体积,何乐而不为呢?

关于Android图片资源瘦身的奇思妙想的更多相关文章

  1. 包建强的培训课程(6):Android App瘦身优化

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  2. Android APK 瘦身 - JOOX Music项目实战

    导语 JOOX Music是腾讯海外布局的一个音乐产品,2014年发布以来已经成为5个国家和地区排名第一的音乐App.东南亚是JOOX Music的主要发行地区,由于JOOX Music所面对的市场存 ...

  3. Android应用瘦身

    转:https://zhuanlan.zhihu.com/p/25465537 瘦身的目的 从目的导向来看,我们是不会无缘无故去做一件事情的,那我们对应用瘦身的目的是为了什么?答案是:提高下载转化率. ...

  4. Android APK瘦身之Android Studio Lint (代码审查)

    ******** ******** 第一部分: 瘦身内容介绍 ******** ******** 项目新版本的迭代接近尾声, 因为历史累积问题, 导致有很多无效的资源让已经臃肿的APK变得更肿, 因此 ...

  5. 利用 Android Gradle 瘦身 apk

    http://devyang.me/blog/2014/11/11/li-yong-android-gradleshou-shen-apk/ apk瘦身一般有两条线, 去除无用的代码,例如引用一个比较 ...

  6. 再谈Android应用瘦身

    Android应用apk安装包的大小,虽然对于现在WiFi普及情况而言消耗流量已经微乎其微,但是,对于一款好的应用,对于一款负责任的应用,当然是越小越好了. 引言: .应用越小,下载越快,也就意味着新 ...

  7. Android Apk 瘦身大法

    原文地址: https://mp.weixin.qq.com/s/XS0tuLgTfyp4rW4h69wyQQ 一, 我们在多人开发项目 或者 遗留项目中开发时,会有些自己没用到的资源文件,但是自己也 ...

  8. android apk瘦身之 图片压缩 tinypng

    参考地址: http://blog.csdn.net/jy692405180/article/details/52409369 http://www.tuicool.com/articles/BraI ...

  9. Android APK瘦身方法小结

    众所周知,APP包体的大小,会影响推广的难度,用户不太喜欢下载太大的APP,同类型同等功能的APP中往往是包体小的更受用户的青睐,所以降低包体是一项非常必要的事情,也是最近公司的APP需要降低包体,所 ...

随机推荐

  1. __attribute__((weak, alias())))

    参考gcc的reference: 弱符号: 若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误.链接器会忽略弱符号,去 ...

  2. iOS边练边学--触摸事件以及能够拖拽的UIView的练习

    一.用户在使用APP的过程中,会产生各种各样的事件.iOS中的事件可以分为3大类型: 二.响应者对象 在iOS中只有继承了了UIResponder的对象才能接受并处理事件,这样的对象称之为“响应者对象 ...

  3. C#NetRemoting双向通信

    闲来无事想玩玩双向通信,实现类似QQ的互发消息的功能.于是乎开始学习.Net Remoting. .Net Remoting 是由客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为 ...

  4. activiti小结

    前提:业务流程复杂且流程频繁变更的,建议使用工作流:其他情况不建议使用. activiti(v5.14),工作流引擎,基于jbpm.使用建模语言BPMN2.0进行定义. 工作流数据需要写入数据库,ac ...

  5. mpeg压缩输入格式---打包模式和平面模式

    版本 v1.0,存在内存问题在 void v4l2_process_image(struct buffer buf)中对 v4l2 采集来的一帧进行处理,存在 struct buffer buf 中b ...

  6. 配置 -- PHPstorm+Xdebug断点调试PHP

    运行环境: PHPSTORM版本 : 8.0.1 PHP版本 : 5.6.2 xdebug版本:php_xdebug-2.2.5-5.6-vc11-x86_64.dll ps : php版本和xdeb ...

  7. struct iphdr中的__LITTLE_ENDIAN_BITFIELD和__BIG_ENDIAN_BITFIELD

    __LITTLE_ENDIAN_BITFIELD表示小端序,__BIG_ENDIAN_BITFIELD表示大端序. /usr/include/linux/ip.h中有一段代码定义了ip首部的结构体,例 ...

  8. UVa 10633 - Rare Easy Problem

    题目:给定一个数N.去掉末尾的数变成M.如今已知N-M,确定N. 分析:数论.简单题. 设N = 10*a + b { 当中0 ≤ b ≤ 9 }.则M = a: N - M = N - a = 9* ...

  9. 解决 Comparison method violates its general contract!

    问题:Comparison method violates its general contract!报错 Collections.sort(list, new Comparator<Integ ...

  10. Asp.Net实现FORM认证的一些使用技巧(必看篇)

    最近因为项目代码重构需要重新整理用户登录和权限控制的部分,现有的代码大体是参照了.NET的FORM认证,并结合了PORTAL KITS的登录控制,代码比较啰嗦,可维护性比较差.于是有了以下的几个需求( ...