一、概述
对于PNG
这种图像存储格式,它有两个特点:无损压缩和支持透明效果。
- 由于
PNG
文件采用LZ77
算法的派生算法进行压缩,其结果是获得高的压缩比,不损失数据。它利用特殊的编码方法标记重复出现的数据,因而对图像的颜色没有影响,也不可能产生颜色的损失,这样就可以重复保存而不降低图像质量。 -
PNG
可以为原图像定义256
个透明层次,使得彩色图像的边缘能与任何背景平滑地融合,从而彻底地消除锯齿边缘。这种功能是GIF
和JPEG
没有的。
今天,我们就来介绍一下PNG
的相关知识。
二、PNG 原理
2.1 PNG 文件结构
PNG
由一个8
字节的PNG
文件署名域和按照特定结构组织的3
个以上的数据块组成,其中数据块分成两种,关键数据块和可选数据块,关键数块为如下四种:
- 文件头数据块
- 调色板数据块
- 图像数据块
- 图像结束数据块
而每个数据块由以下四个数据域组成:
- 长度
- 数据块类型码
- 数据块数据
- 循环冗余校验
从上面的构成中,我们可以看到,对于用户可见的部分,真正和展现有关就是图像数据块中的数据块区域,因此,我们就需要注意有没有在别的数据块中引入了不必要的数据,例如下面的右图,在从Photoshop
中导出的时候,选择了export to web
,因此它的大小就比左图要小很多。
2.2 PNG 格式
PNG
的格式有8/24/32
三种,称为PNG 8/ PNG 24 / PNG 32
,其中后面的数字表示最多可以索引和存储的颜色值。
-
PNG 8
支持两种不同的透明形式,索引透明和Alpha
透明 -
PNG 24
不支持透明 -
PNG 32
在24
位基础上增加了8
位透明通道,因此可展现256
级透明程度
我们应当根据图片来选择正确的格式,在能表示图片中颜色的前提下,尽量选择位数较少的PNG
格式。
2.3 PNG
压缩原理
PNG
压缩过程分为两个阶段:Prediction 和 Compression。
2.3.1 Prediction
在这一阶段,我们每次会处理图片中一行的数据,首先通过Filter
阶段处理这一行当中每一个的像素点中每条通道的值,也就是我们常说的ARBG
。它交由差分处理器来重新计算该通道的值。差分处理会根据这个像素点上通道和之前或者之上像素点对应通道值之间的差异,进行差分编码,也就是说,如果原本相邻像素点之间通道的值之间很接近,那么我们就会获得很多的1,0,-1
这种很小的值。这里有两点需要注意:
- 整个
Prediction
阶段的目的,也就是选择合适的差分处理器,让最终的编码结果出现尽可能多的零值和重复值,这一结果将会影响到Compression
阶段的压缩率。 - 差分编码器比较的是像素点之间对应通道的值,而并不是整个像素点。
2.3.2 Compression
在Prediction
处理完毕之后,再将这一转换的结果输出给Deflate
,Deflate
执行真正的压缩操作,它会通过LZ77
和Huffman
对图像进行编码,最后将处理之后的结果保存。在Compression
阶段,它最终的压缩率会受到两方面的影响:
- Prediction 的处理结果:对于颜色相近的区域,也就是有很多零值的区域,那么压缩率将会更高,而如果颜色之间差异很大,那么压缩效果将不尽人意。
-
Deflate 每一行的匹配情况:前面我们分析过,整个处理过程是按行来处理的。而在处理每一行的数据时,
Deflate
把处理的符号数限制为3 ~ 258
,也就是说,最大的压缩率为1032:1
,当出现符号数小于3
个时,那么就有可能出现无法匹配的情况,因此,对于图片宽度的改变将有可能影响最终压缩的效果。
下面,我们对于上面描述的第二点举一个例子,对于下面两幅图,右图虽然之比左图宽了两个像素,但是它的大小整整大了一倍:
我们通过下面这个工具可以观察每个像素点的压缩率:
在分析的结果中,深蓝色表示该像素点具有较高的压缩率,而黄色/红色则表示压缩率较低,可以发现正是由于改变了图片的大小,导致某些像素点没有匹配到,从而产生了一个较大的文件。
2.3.3 代码表示
对于 Prediction 和 Compression 这两个过程,可以通过下面这个代码来理解:
三、总结
PNG
有很多优点,并且应用广泛,但是还是需要根据具体的场景来选用:
- 如果原始的图片为高清的,但是不要求进行无损的压缩,那么可以选择类似于
JPG
这样的有损压缩 - 但是从反方面来说,如果原始图片较为简单,并且需要支持透明形式,那么
PNG
要由于JPG
。
这一篇文章,介绍了PNG
相关的一些知识,目的还是让大家对这种图片格式有一个大概的理解,这也是我们后面分析优化的基础。