图片优化(图片压缩)

公司的Android应用第一版比较简单,几乎没什么资源文件。第二版进行了大改版之后增加了更多功能使用了更多切图。因为没有设计师切图,大部分图片素材都是我从网上找到切得尺寸并没有考虑过图片大小和压缩的问题,直到上线打包时发现整个包已经超过10M了,于是怒而瘦身,将所有用到的切图资源压缩了一遍减少到6M左右,基本满足需要了。

在这里压缩使用的是腾讯爸爸的 智图 图片优化平台。可以使用网页版也可以使用客户端,默认设置完全能够满足需求。

之后就一发不可收拾,一直有想法想要了解图片是怎么压缩的,一是确实想要将技术掌握到自己手中,二是因为当前智图平台是免费的万一以后收费了怎么办,还是自己搞一套放心。期间一直比较忙,趁这个国庆开撸。

PNG图片

在平时开发过程中,因为支持透明,png成为最常用于切图格式。从其命名可以看出,Png(Portable Networks Graphics)格式是是为了在网络间传输用的。因此,png图片肯定不是简单的像素点存储,否则不能进行压缩也就不适合在网络间传输了。

在网上找了找,这篇文章中的介绍可能最符合我想要了解的内容。 如下示意图为png图片生成过程。

2017100615072235022070.png

图中标注的1 2 即为影响png文件关键处理步骤。

PNG图片生成

我们知道电脑上表示一张图片要描述图中每一个素点信息,如果将这些像素点不加处理直接存储起来就是bmp图片,常见格式如tga图。png作为适合网络传输的格式当然不能直接存储这是很浪费空间的,于是需要将其压缩,如果像素点序列直接压缩的话压缩效率并不高,需要做一次中间变换,将原始像素序列转换为可压缩序列。这个转换被称为Delta Filtering或者坚持Filtering。
Deflate压缩指的是通过哪种方法将中间变换的字节流压缩存储,当前方法有lz77,7-zip。

影响文件大小的因素

20171006150728062124975.png

1 图片类型
一个像素点可以使用8bit表示也可使用24bit,24位存储的图片能够表示更多颜色,比如红色从,使用24位表示从纯红色到0红色可以分割的数量比8bit更多,因此颜色也更加细腻。

png使用调色板,在文件部分会有一部分用于存放颜色区域的地方,这样每个像素点就可以用调色板上的点而不是颜色值,更方便压缩。

png支持灰度和透明,灰度和透明通道也会影响图片大小;

2 过滤器

png压缩需要将像素点信息通过过滤器转换,过滤器的策略也是影响图片大小的因数。

3 压缩策略 、4霍夫曼数缓存大小
压缩算法不是一层不变的,不同压缩参数会影响压缩效率,继而影响图片大小。

无损变换

同一张图片按照不同参数进行压缩后文件并非完全一致,这样生成的两张图片互相被叫做另一张图片的变换。

上述影响因素中 2 3 4中进行优化进行的变换被称为无损变换。

常见工具有 pngrewrite, pngcrush, optipng, advpngpngout

有损变换

如果在图片类型处做文章,将初始24位深度的图片转换为8位深度图片,这样图片像素点数据大幅度减少,导致png图片文件减小,不过这种变换是有损的,损失的像素信息是找不回来的。

使用这种压缩的工具主要有 pngnq, pngquant

两个工具都可以将png图片转换为png8图片,大幅度减小图片大小。

有损变换可以吗?

使用TinyPng 会将图片压缩直接压缩成png8。智图的默认设置会将颜色比较复杂的图片保留而不是直接转换为png8。

从上述设置可以看出,并不是所有图片都适合有损压缩的。不过对于应用图片和应哟app内部切图来说,直接转png8是能满足需求的。对于技术博客中示意图来讲,png8也足够满是需求了。

参考链接

pngquant vs pngcrush vs optipng vs pngnq

Difference Between PNG8 and PNG24

几种主流贴图压缩算法的实现原理详解

JPEG 图片的压缩

JPEG/JPG格式是有损图片压缩,图片生成过程中会根据量化和无损压缩编码相结合来去掉视角冗余信息和数据本身冗余信息。整个压缩过程大致分为三个步骤:

  1. 使用正向离散余弦变换(Forward Discrete Cosine Transform,FDCT)把空间域表示的图变换成频率域表示的图。
  2. 使用加权函数对DCT系数进行量化,这个加权函数对于人的视觉系统是最佳的。
  3. 使用霍夫曼可变字长编码器对量化系数进行编码。
  4. 译码或者叫做解压缩的过程与压缩编码过程正好相反。

20171006150729661187891.jpg

图片时有损的,根据不同的压缩比例生成不同清晰度的图片。

常用的JPEG图片压缩工具有 mozjpegjpegoptimjpegtran(谷歌推荐)

jpegoptim 和 jpegtran 在Ubuntu上可以直接方便的安装,使用方法如下:

jpegtran -copy none -optimize -progressive -outfile out.jpg in.jpg

jpegoptim -–strip-com –-strip-exif –-strip-iptc -m 85 in.jpg

  • mozjpeg

不像jpegoptim 和jpegtran, mozjpeg 不直接提供可执行文件,需要按照BUILDING.txt中的步骤完成编译,根据编译参数不同会生成不同平台和目的链接文件或可执行目标文件,可执行文件为 cjpeg ,cjpeg 可以处理tga,bmp ppm等多种格式,也支持jpg文件优化,使用方法如下:

cjpeg -quality 80 foo.bmp > bar.jpg

参考:

JPEG有损压缩过程介绍

使用mozjpeg打造更高效的JPEG

其他

通过前四个字节判断文件是否png/jpeg
png: 0x474e5089
jpeg/jpg: 0xe0ffd8ff