三分钟讲清楚---- 图片压缩的原理

1,183 阅读4分钟

  在我们日常工作中,天天都在用,并且在网路传输和图片展示中,是一个很主流的格式,今天这片文章,就用PNG,来作为主角,来探究一下,图片压缩中的一些知识;

PNG

  • 体积小:传输同样的图片,png就比别人要小
  • 支持透明:这个是 gif 和 jpeg 没有的功能

PNG的数据结构

  是不是和HTTP请求的结构很像,一个Head,然后一堆Chunk,这个就是PNG的数据结构;

如果你用 vim 打开一张 png

## step1.打开一个png
vi -b xxx.png
## step2.使用十六进制显示
:%!xxd

666.png

8950 4e47 0d0a 1a0a:这个是PNG图片的头,所有的PNG图片的头都是这一串编码。
0000 000d:是iHDR数据块的长度,为134948 4452:是数据块的type,为IHDR,之后紧跟着是data。
0000 00c8:是图片的宽度,转换一下是2000000 00c8:是图片的高度,转换一下是200

png 是如何做压缩的?

压缩分为两个阶段:解析 + 压缩PNG都有自己特殊的处理;

解析阶段(特殊的编码方式)

  在压缩之前,有一个步骤,叫做解析(Prediction),处理之后,更加方便后面的压缩,类似化妆前,先打粉底、涂乳液、摸精华先上去;
  PNG差分编码(Delta encoding)对图片进行一个预先处理,处理每一个像素点中的每一条通道的值,R(红)、G(绿)、B(蓝)、A(透明);

  查分编码主要有几种:

  • 不过滤
  • X-A
  • X-B
  • X-(A+B)/2(又称平均值)
  • Paeth 推断

1582964330303-ed775632-1e90-4b5d-bf54-8c6553ec2482.png

  这张图片是一个红色逐渐增强的渐变色图,它的红色从左到右逐渐加强,映射成数组的值为[1,2,3,4,5,6,7,8]

使用X-A的差分编码的话,那就是: [2-1=1, 3-2=1, 4-3=1, 5-4=1, 6-5=1, 7-6=1, 8-7=1],得到的结果为[1,1,1,1,1,1,1],这个结果出现了大量的重复数字,这样就非常适合进行压缩。

 差分编码的目的,就是尽可能的将png数据值转换成一组重复的、低的值,这样的值更容易被压缩。最后还要注意的是,差分编码处理的是每一个的像素点中每条颜色通道的值,R(红)、G(绿)、B(蓝)、A(透明)四个颜色通道的值分别进行处理。

压缩阶段(删除图片信息)

  压缩阶段会将预处理阶段得到的结果进行Deflate压缩, 这种压缩算法,会标记图片所有的重复数据,并记录数据特征和结构,会得到一个压缩比最大的png图片编码数据。

  前面我们知道了PNG数据结构,一个 NG图片是由很多的数据块构成的,但是并不是所有的都是必须的,一些设备信息,光圈信息,拍摄日期,定位信息都是可以直接丢掉的;

  说一个最实际的场景,用 Photoshop 保存了一张PNG都会很大,因为 Adobe 会在 PNG 里面存储很多信息,设计师的需要这些信息,前端是不需要的,如果用Photoshop 的导出web格式” 就能去掉这些无用信息。所以体积一下就小了,可以自己试试;

什么样的图片压缩效果好?

  颜色越单一颜色值越少颜色差异越小的PNG,压缩率就越大,体积就越小,压缩率就越高,这就是为什么渐变色图片、颜色值变化不大、颜色单一的图片更容易压缩呢?

image.png

它仅仅由红色绿色构成,如果用0代表红色,用1代表绿色,那用数字表示这张图就是下面这个样子:

00000000000000000
00000000000000000
00000000000000000
1111111111111111111111111
1111111111111111111111111
1111111111111111111111111

  这张图片是用了大量重复的数字,我们可以将重复的数字去掉,直接用数组形式的[0, 1]就可以直接表示出这张图片了,仅仅用两个数字,就能表示出一张很大的图片,这样就极大的压缩了一张 PNG