携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情
介绍
对于图片的压缩,最常见的分有损、无损压缩。
无损压缩譬如去除 exif 信息,重新排列像素存储方式等;有损压缩疲软合并相似像素,减少可见像素点等。
一、png图片的特点
- 无损压缩:
PNG采取的是LZ77无损数据压缩算法,使其压缩比更高,生成的文件体积更小,并且不损失数据LZ77算法简单来讲就是通过使用编码器或解码器中已经出现过的相应匹配数据信息,替换当前数据从而实现压缩功能。- 因此对图片的颜色没有影响,也不会丢失数据导致颜色的损失(无损压缩)
- 透明度:
PNG为原图形定义了256个透明层次,使得图像边缘能够与任何背景平滑的融合,消除锯齿边缘。此功能是GIF和JPEG没有的。
二、二进制数据内容
我这里使用 vscode 的插件,来观察一下 png 的 hex 格式内容。
- 头信息(
89 50 4e 47 0D 0A 1A 0A):随便打开一张PNG图,都可以看到前8位都是一样的,这是PNG的头,其他的软件会通过这个头来判断此文件是否为PNG格式; - 数据块长度(
00 00 00 0D):IHDR数据块的长度 - 数据块类型(
49 48 44 52):可以从右侧绿色的字体看到,类型是IHDR - 图片的宽度(
00 00 03 53) - 图片的高度(
00 00 00 EC) - 等等
三、压缩
PNG 图片的压缩分为两个阶段:过滤和压缩
3.1、过滤
PNG 图片用差分编码(Delta encoding) 对图片进行预处理,处理每一个像素点中每条通道的值,PNG允许5种不同的算法(每一行像素可能采取不同的过滤算法):
- 不过滤
- X-A
- X-B
- X-(A+B)/2 :平均值
- Paeth推断
算法示意图:
假设一张 PNG 图如下
这张图片是一个红色逐渐增强的渐变图,如果从左往右映射成数组的话就是:[1,2,3,4,5,6,7,8,9],使用 X-A 的差分编码就是:
[2-1=1, 3-2=1, 4-3=1, 5-4=1, 6-5=1, 7-6=1, 8-7=1, 9-8=1]
也就是
[1, 1, 1, 1, 1, 1, 1, 1, 1]
最终的结果数组出现了大量的重复数字,就非常适合压缩。
这就是渐变色图片、颜色单一的图片更容易压缩的原理。
差分编码处理的是每一个像素点中,每条颜色通道的值:R(红)、G(绿)、B(蓝)、A() 四个颜色通道的值分别进行处理。
3.2、压缩
在一行像素被过滤后,就会执行 Deflate 压缩,这是 LZ77 延伸出来的一种算法。该算法结合了 LZ77 编码和哈夫曼编码,它跟 GZIP 差不多相同。这种实现方式虽然是现成的,但用在压缩图片数据上,还是有一些需要注意的点:
Deflate算法只能匹配 3 ~ 258 个之间符号,所以最大压缩比只能到 1035 :1- 如果匹配到的符号小于3,那么将产生一些额外的开销来表示这些符号