Android手机和iPhone有很多相比较的地方。我们无法做出哪个更好的结论,但是我们都知道Android手机图片的质量是比iPhone差的。无论你是用Facebook、Twitter甚至是Instagram,拍完照片,加个滤镜,然后分享到社交平台,Android手机产生的图片总是很粗糙。为什么呢?
从去年开始,我们的团队就这一点已经工作了一年。经过深入的研究,这是由于Google的一个“很小的”错误导致的。虽然是个很小的错误,但它的影响却是非常大的(所有的Android应用都涉及到图片),并且一直延续到了今天。
问题就是:libjpeg
我们都知道libjpeg是被广泛地应用到各种开源的图片库中。Android也使用libjpeg去压缩图片。在深入挖掘了Android的源码之后,我们可以发现相比于直接使用libjpeg库,Android是基于一个叫Skia的开源图片引擎。Skia是一个由谷歌维护的很棒的引擎,它涉及到了所有的图片功能。它被广泛地使用到谷歌和其他公司的产品中,比如Chrome、Firefox、Android等。Sika具有良好的封装性,在它的基础上,你可以很容易地开发图片工具。
当我们使用libjpeg去压缩图片时,optimize_coding 是一个非常重要的参数。在libjpeg的文档中,我们可以发现该参数的介绍如下:
boolean optimize_coding
TRUE causes the compressor to compute optimal Huffman coding tables
for the image. This requires an extra pass over the data and
therefore costs a good deal of space and time. The default is
FALSE, which tells the compressor to use the supplied or default
Huffman tables. In most cases optimal tables save only a few percent
of file size compared to the default tables. Note that when this is
TRUE, you need not supply Huffman tables at all, and any you do
supply will be overwritten.
来源: <https://github.com/bither/bither-android-lib/blob/master/REASON.md>
正如libjpeg的文档所示,我们不知道因为optimize_coding设置成了TRUE可能会花费很大的时间和空间,而optimize_coding 的默认值为FALSE。
文档中的所有内容看起来都是没问题的,而且libjpeg库也是非常稳定的。但是很多人忽视了一点,这个文档已经超过了10年。在那个时期,空间和计算能力都是非常有限的。在今天现代化的计算机甚至是手机上,这些都不是问题。相反,我们应该把更多的注意力放到图片的质量(Reitna 屏)和图片的大小(云服务)上来。
谷歌Skia项目的工程师并没有设置这个参数,所以Skia中的optimize_coding参数是保留FALSE作为默认值,并且Skia隐藏了该设置,你无法在Sika项目的外部去改变这个设置。所以这个就变成了很大的问题,我们也不得不去忍受糟糕的画质和更大的文件体积。
我们的团队已经测试了很多不同的图片。如果你想要同样质量的图片压缩,将optimize_coding设置为FALSE会比设置成TRUE的文件体积大5到10倍。这个差距是非常大的。
我们也比较了Android和iOS之间的图片压缩(他们都隐藏了optimize_coding参数)。在相同的原始图片下,如果你想获得相同的质量级别,在Android上你需要5到10倍的文件大小。
结论很清楚,Apple确实的知道optimize_coding和Huffman表的重要性,而Google不知道。(Apple使用它们自己的Huffman表算法,并不是像libjpeg或者libjpeg-turbo,看起来Apple在压缩图片上做了更多的工作)
最后,我们决定不使用Android提供的JPEG压缩算法,并且我们编译了基于libjpeg-turbo(libjpeg-turbo在表现上也有提高)的原生库。现在我们可以节省5到10倍的空间并且享受同样甚至更好的图片画质。这个工作是完全值得我们去做的。
感谢你的阅读。