PNG编解码算法详解
1.PNG介绍
PNG是便携式网络图型( Portable Network Graphics)的缩写,由于PNG带有透明通道,无损压缩,可提升设计元素的呈现效果,因此设计上对PNG情有独钟,广泛的运用在设计、游戏、网页、app开发里,实际使用上由于存在很多误区,导致被滥用,这里对之前学习png的心得做个整理。
首先,PNG和诞生跟GIF格式有较大关系,这中间有很多趣事,可自行查阅。PNG的压缩过程是完全无损的,压缩过的文件可以准确的还原出原图,可封装多种pixfmt格式的数据,并且是一种可扩展的封装格式,
PNG文件格式里面包含不同的区块(chunks),各个区块带有不同类型的数据。典型的PNG数据包括四部分,而在此基础上,增加acTL(动画控制块)、fcTL(帧控制块)、fdAT(帧数据块)即为APNG动图格式。
- PNG Signature(PNG签名块,包含PNG类型的标识)
- IHDR(图像头部块,包含图片的宽度、高度、位的深度和颜色类型)
- IDAT(图像数据块,像素压缩后的数据)
- IEND(图像结束块,PNG结束标识)
2.PNG文件解析
PNG图像格式文件由一个8字节的PNG文件署名(PNG signature:0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)和按照特定结构组织的3个以上的数据(chunk)组成。PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。关键数据块定义了4个标准数据块,每个PNG文件都必须包含它们,PNG读写软件也都必须要支持这些数据块,虽然PNG文件规范没有要求PNG编解码器对可选数据块进行编码和解码,但规范提倡支持可选数据块。
1.PNG介绍
PNG是便携式网络图型( Portable Network Graphics)的缩写,由于PNG带有透明通道,无损压缩,可提升设计元素的呈现效果,因此设计上对PNG情有独钟,广泛的运用在设计、游戏、网页、app开发里,实际使用上由于存在很多误区,导致被滥用,这里对之前学习png的心得做个整理。
首先,PNG和诞生跟GIF格式有较大关系,这中间有很多趣事,可自行查阅。PNG的压缩过程是完全无损的,压缩过的文件可以准确的还原出原图,可封装多种pixfmt格式的数据,并且是一种可扩展的封装格式,
PNG文件格式里面包含不同的区块(chunks),各个区块带有不同类型的数据。典型的PNG数据包括四部分,而在此基础上,增加acTL(动画控制块)、fcTL(帧控制块)、fdAT(帧数据块)即为 APNG动图格式 。
- PNG Signature(PNG签名块,包含PNG类型的标识)
- IHDR(图像头部块,包含图片的宽度、高度、位的深度和颜色类型)
- IDAT(图像数据块,像素压缩后的数据)
- IEND(图像结束块,PNG结束标识)
2.PNG文件解析
PNG图像格式文件由一个8字节的PNG文件署名(PNG signature:0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)和按照特定结构组织的3个以上的数据(chunk)组成。PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。关键数据块定义了4个标准数据块,每个PNG文件都必须包含它们,PNG读写软件也都必须要支持这些数据块,虽然PNG文件规范没有要求PNG编解码器对可选数据块进行编码和解码,但规范提倡支持可选数据块。
每个数据块按如下方式排列 ,包括数据块 内 数据长度、块类型、块数据和CRC校验码。
一个典型的PNG文件的十六进制如下
(1)PNG signature
PNG signature为固定的8个字节0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A
(2)IHDR
文件头数据块 IHDR(header chunk,13个字节) 包含PNG文件中存储的图像数据的基本信息,包括 分辨率、比特深度、色彩模式、压缩方法 ,是非常重要的数据块,必须作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。
(3)IDAT
图像数据块IDAT(image data chunk)存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。IDAT存放着图像真正的数据信息,因此,如果能够了解IDAT的结构,我们就可以很方便的生成PNG图像。
生成IDAT需要先经过Filter(具体算法由IHDR指定),再经过Deflate(具体算法由IHDR指定)
(4)IEND
图像结束数据IEND(image trailer chunk)用来标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。如果我们仔细观察PNG文件,我们会发现,文件的结尾12个字符看起来总应该是这样的:00 00 00 00 49 45 4E 44 AE 42 60 82
由于IEND数据块的长度是0(00 00 00 00,除非人为加入信息),数据标识总是IEND(49 45 4E 44),因此,CRC码也总是AE 42 60 82。
3.Filter
IDAT的压缩过程主要包括Filter和deflate两部分,Filter即对像素做过滤,PNG编码使用差分对原始像素数据进行Filter,该过程无任何压缩损失,并且完全可逆。对图像来说,存储残差所需的比特远远小于实际图像所需,这也是差分编码的收益来源。
差分编码原理如下,对于 每一行 像素点X,使用左、左上、上的三个像素来进行约束,对于不同的内容,须使用不同的Filter类型来提升压缩收益。
PNG在压缩时,对每行的图像 以byte为单位 进行filter,如图像为真彩色RGBA图像,则先对R分量进行filter,再依次对G、B、A进行Filter[5]。
4.deflate
PNG中的Deflate与gzip、zlib中的deflate原理一样,结合了LZ77和Hoffman算法。
Ziv和Lempel于1977年发表《A Universal Algorithm for Sequential Data Compression 》进行像素数据的压缩,定义了一种编码标准而没定义具体实现,后来称为LZ77算法,LZ77压缩算法采用字典的方式进行压缩,是一个简单但十分高效的数据压缩算法。其方式就是把数据中一些可以组织成短语(最长字符)的字符加入字典,然后再有相同字符出现采用标记来代替字典中的短语,如此通过标记代替多数重复出现的方式以进行压缩。Hoffman是一种变长编码,即用少的bit数表示出现概率大的数据。
deflate算法用在压缩图片数据上,有以下特点:
- Deflate算法只能匹配3到258个之间符号,所以最大的压缩比只能到1035:1;
- 如果匹配到的符号小于3,那么你会产生一些额外的开销来表示这些符号;
上面的这两点意味着实际图片大小会受到每一行像素的匹配程度影响。
5.png格式怎么用
对于PNG格式数据,实际项目应用上,选择很多,可以用opencv,也可以用libpng这种原生开源库。
后面再来介绍libpng编解码的实现及调用。
参考
[1] http://www. libpng.org/pub/png/spec /1.2/PNG-Chunks.html
[2] http://www. libpng.org/pub/png/spec /1.2/PNG-Filters.html
[4] https:// blog.csdn.net/john_cdy/ article/details/46936667
[5] http://www. libpng.org/pub/png/spec /1.2/PNG-DataRep.html#DR.Image-layout