上一篇介绍了PNG图像的基本情况,有兴趣的可以翻阅查看,本文进行编码过程的几个重要阶段说明,以期更好理解PNG图像格式。
PNG图像的编码过程是先将原始图像转换为RGB或灰度颜色模式,然后对每个像素进行滤波和压缩,最后将压缩后的二进制代码存储为PNG文件。
通道提取
通道提取:将一个PNG图像分解成一系列缩小的图像,其中第一张图像定义了一个粗略的视图,随后的图像增强了这个粗略的视图,直到最后一张图像完成了PNG图像。
扫描
PNG图像是一个矩形像素阵列,每个扫描线内的像素从左到右出现,扫描线从上到下出现。每个像素的大小由每像素比特数确定。
扫描线内的像素总是被打包成一系列字节,像素之间没有浪费的数据位。扫描线总是从字节边界开始。允许的比特深度和颜色类型受到限制,以使在所有情况下打包变得简单高效。
在颜色类型为0(灰度)的PNG图像中,每个像素是单个样本,其精度可能小于一个字节(1、2或4位)。这些样本被打包成字节,其中最左边的样本位于字节的高位,然后是扫描线中的其他样本。
在颜色类型为3(索引颜色)的PNG图像中,每个像素是单个调色板索引。这些索引与颜色类型0的样本以相同的方式打包为字节。
非索引颜色图像的PNG图像可能具有16位比特深度的样本值。这些样本按网络字节顺序(MSB在前,LSB在后)排列。PNG仅允许8位和16位样本的多样本像素,因此单个像素的多个样本永远不会打包成一个字节。
过滤
过滤方法是应用于扫描线数组的一种转换,旨在提高它们的可压缩性。在解释过滤方法之前,先说明一下字节相关位置,如下表格和图所示:
PNG图像定义了5种过滤器类型:0表示没有过滤器,1表示使用左边像素过滤器,2表示使用上一个像素过滤器,3表示使用平均像素过滤器,4表示使用Paeth过滤器。这5种类型的主要特点,优缺点进行直观汇总,方便进行统一对比,如下表格:
压缩
本国际标准只定义了PNG压缩方法0。其他压缩方法的值保留用于未来标准化。PNG压缩方法0是采用滑动窗口(其上限是在deflate流中出现的距离)不超过32768字节的压缩方法。Deflate压缩是从LZ77衍生出来的,并结合了Huffman编码算法。具体Deflate可以参考以下几篇文档理解。
https://datatracker.ietf.org/doc/html/rfc1951
https://luyuhuang.tech/2020/04/28/gzip-and-deflate.html
https://www.euccas.me/zlib/
分块
分块提供了将压缩数据流方便地分解为可管理的块,每个块都有自己的冗余检查。主要有两种类型:键块和辅助块:
关键块是为了从 PNG 数据流中成功解码 PNG 图像而绝对需要的那些块。
有效的 PNG 数据流应以 PNG 签名开头,紧随其后的是IHDR块,然后是一个或多个IDAT块,最后应以IEND 块结束。一个 PNG 数据流中只允许一个IHDR块和一个IEND块。
辅助块有些会有规定顺序,但没有强制在 PNG 数据流中出现的顺序。解码器可能会忽略辅助块。对于每个辅助块,所描述的操作都是在解码器没有忽略该块的假设下进行的。
图像类型
基于调色板的图像,也称为颜色映射或索引颜色图像,使用 PLTE 块并支持四种像素深度:1、2、4 和 8 位,对应于最大 2、4、16 或 256调色板条目
PNG 规范禁止对基于调色板的图像使用完整的 alpha 通道,但它允许通过透明度块 tRNS 使用“简易版alpha”
PNG 灰度图像支持任何图像类型中最广泛的像素深度范围。支持 1、2、4、8 和 16 位深度,涵盖从简单的黑白扫描到全深度医学和原始天文图像的所有内容
PNG 支持灰度和 RGB 图像两种透明度。第一种是调色板风格的“简易透明”,其中单一颜色或灰度值被标记为完全透明。第二种是alpha通道的透明。
具体分类如下图,详细信息可以参看:《 PNG The Definitive Guide》一书。
编码阶段的几个过程简单做个介绍,下一篇文档进行源码解读,主要是针对FFMPEG中encode过程进行详细拆解,也会针对前两篇的内容进行代码比对,更好地理解PNG图像。敬请期待。
我是一枚爱跑步的程序猿,维护公众号和知乎专栏《MediaStack》,有兴趣可以关注,一起学习音视频知识,时不时分享实战经验。
继续阅读
阅读原文