PNG图片原理二三事

5,242 阅读8分钟

Questions

  • PNG图片结构是什么样的?

  • PNG规范中定义PNG是无损压缩(Lossless Compression)的图片格式,那么PNG支持有损压缩吗?

一、PNG概述

1、PNG简介
  • PNG(Portable Network Graphics,便携式网络图型)是一种无损压缩的图片格式,支持索引、灰度、RGB三种颜色方案以及Alpha通道等特性(iOS的绝大部分切图都是PNG格式)。
  • PNG图片主要有三个类型,分别为 PNG 8、 PNG 24 和 PNG 32;其中 PNG 8支持两种不同的透明形式,索引透明和Alpha透明、 PNG 24不支持透明和 PNG 3224位基础上增加了8bits透明通道。
  • PNG规范可见: Portable Network Graphics (PNG) Specification (Second Edition)
2、PNG结构
  • PNG结构如下: header,chunk,chunk,chunk….chunk; 其中,header代表png图片的头,由固定的8个字节组成,内容是:89 50 4E 47 OD 0A 1A 0A;而chunk代表png图片的数据块。

PNG编码结构

二进制查看PNG图片

3、PNG的数据块
  • PNG的数据块由四个数据域组成:长度、数据块类型码、数据块数据和循环冗余校验;而数据块分成两种:关键数据块可选数据块,关键数据块包括:文件头数据块调色板数据块图像数据块图像结束数据块
  • 真正和图片展示有关是图像数据块中的数据块区域
  • IHDR数据块(文件头数据块):一个PNG图片中只能有一个IHDR数据块,它是PNG图片中第一个数据块,共13个字节(0000 000d),具体信息如下:
域名称 字节数(bytes) 说明
width 4 图像宽度,以像素为单位
height 4 图像高度,以像素为单位
bit depth 1 表示一个通道的总位数
color type 1 颜色类型. [0]:灰度图像, 1,2,4,8或16 [2]:真彩色图像,8或16 [3]:索引彩色图像,1,2,4或8 [4]:带α通道数据的灰度图像,8或16 [6]:带α通道数据的真彩色图像,8或16
compression method 1 压缩方法(LZ77派生算法)
filter method 1 滤波器方法
Interlace method 1 隔行扫描方法. 0:非隔行扫描 1: Adam7(7遍隔行扫描方法)
  • 0000 000d是iHDR数据块的长度,为13,4948 4452是数据块的type,为IHDR,之后紧跟着是data, 0000 02bc是图片的宽度,0000 03a5是高度,08是bit depth,也就是一个通道是8位,06是color type,这里表示图片是真彩色,00是压缩方法,png中目前只有一种,也就是LZ77派生的算法,00是滤波器方法,表示不使用,00是隔行扫描方法,代表不扫描。8f 1434 a4是四个字节的CRC校验码。
  • IDAT数据块(图像数据块):存放的就是图像的一个个像素,一张图像中可以存在多个IDAT数据块,这里的数据会被隔行扫描方法(Interlace method)滤波器(filtering)压缩算法(compression)处理。
  • IEND数据块(图像结束数据块)、PLTE数据块(调色板数据块,在IDAT数据块之前),介绍略。
4、总结
  • 通过了解PNG的结构可以知道,减少PNG图片大小可以通过去除PNG文件中不需要的信息,或 选择正确的PNG格式(如,如果图片中没有Alpha通道,那么就应当使用PNG 24,而不是使用PNG 32。类似,如果是灰度的图片,那么应当使用PNG 8)

二、PNG的压缩原理

1、无损压缩 VS 有损压缩
  • 无损压缩(Lossless Compression):数据压缩格式方法之一,指数据经过压缩后,信息不受损失,还能完全恢复到压缩前的原样。
  • 有损压缩(Lossy compression):数据压缩格式方法之一,指数据经过压缩、解压的数据会与原始数据不同但是非常接近。
  • 无损压缩和有损压缩是相对的,有损压缩将次要的信息数据舍弃,牺牲一些质量来减少数据量、提高压缩比。
  • PNG压缩过程分为两个阶段:Prediction(预解析) 和 Compression(压缩)

PNG图片压缩

2、PNG压缩之Prediction
  • 简单理解:在这个阶段,对图片做一些预处理,方便后续的压缩处理;

  • 每次会处理图片中一行的数据,首先通过Filter处理这一行当中每一个的像素点中每条通道的值,然后交由差分处理器来重新计算该通道的值。

  • 差分处理器会根据这个像素点上通道和之前或者之上像素点对应通道值之间的差异,进行差分编码,也就是说,如果原本相邻像素点之间通道的值之间很接近,那么我们就会获得很多的1,0,-1这种很小的值。(差分编码器比较的是像素点之间对应通道的值,而并不是整个像素点)

  • 整个Prediction阶段的目的,也就是选择合适的差分处理器,让最终的编码结果出现尽可能多的零值和重复值,这一结果将会影响到Compression阶段的压缩率。

3、PNG压缩之Compression
  • Prediction处理完毕之后,再将这一转换的结果输出给DeflateDeflate执行真正的压缩操作,它会通过LZ77Huffman对图像进行编码,最后将处理之后的结果保存。在Compression阶段,它最终的压缩率会受到两方面的影响:

    • Prediction 的处理结果:对于颜色相近的区域,也就是有很多零值的区域,那么压缩率将会更高,而如果颜色之间差异很大,那么压缩效果就差很多。

    • Deflate 每一行的匹配情况:整个处理过程是按行来处理的。而在处理每一行的数据时,Deflate把处理的符号数限制为3 ~ 258,也就是说,最大的压缩率为1032:1,当出现符号数小于3个时,那么就有可能出现无法匹配的情况,因此,对于图片宽度的改变将有可能影响最终压缩的效果。

4、总结
  • 从上述内容可以知道,减少PNG的图片大小,可以通过PNG压缩优化,压缩优化有两个方向:
    • 优化差分编码器,使得经过差分编码后的图像有尽可能多的零值和相同的值
    • 优化Deflate的算法,获得更高的压缩率

三、PNG的有损压缩方案

1、概述
  • 目前大部分PNG的压缩采用基于LZ77派生算法,使得它压缩比率更高,生成的文件体积更小,并且不损失数据【无损压缩】。
  • 但是有些大神不能接受无损压缩的压缩率,设计并实现了有损压缩算法,并在工程中得到了应用。
2、TinyPNG
  • 这是一个提供PNG有损压缩的平台,地址:tinypng.com/

  • 从官网公开的信息来看,TinyPNG主要是使用Quantization的技术,通过合并图片中相似的颜色,通过将 24 位的 PNG 图片压缩成小得多的 8 位色值的图片,并且去掉了图片中不必要的 metadata(元数据,从 Photoshop 等工具中导出的图片都会带有此类信息),这种方式几乎能完美支持原图片的透明度。

  • TinyPNG没有公开他们使用的PNG有损压缩算法。

3、pngquant算法及其应用
  • 著名的PNG有损压缩算法,详细介绍地址在:pngquant.org/

mgod3T.jpg

  • ImageAlpha和PNGyu等软件都采用了pngquant算法;甚至有猜测,TinyPNG可能综合利用了pngquant、optipng、advpng,才获得很好的压缩效果。

mgoX28.jpg

  • pngquant算法的核心:通过Vector Quantization (矢量量化)减少图片中颜色的种类

    • 如果图像中的颜色种类小于256,那么我们可以把它转换为索引PNG格式,而如果图片原本的颜色大于256种,那么可以通过矢量量化的方法来创建一个索引PNG格式。
    • 在矢量量化的过程中,会把所有的像素基于它们之间颜色的相似程度进行分组,一个组内像素的颜色会比较接近。之后根据组内的所有颜色,计算出一个中心点颜色,组内的所有颜色会被替换成为该中心点的颜色。
    • 矢量量化会通过将相近颜色替换成同一种颜色的方法,来减少图片中颜色的种类,因此有可能会使得图片失真。
  • 使用有损压缩方案,需要在图片质量和大小之间取一个平衡点。

参考