什么是PNG文件?
PNG(便携式网络图形)文件是一种使用无损压缩的光栅图像文件格式。此文件格式是作为图形交换格式 (GIF) 的替代品而创建的,没有版权限制。但是,PNG 文件格式不支持动画。 PNG文件格式支持无损图像压缩,使其在用户中很受欢迎。随着时间的推移,PNG 已发展成为广泛使用的图像文件格式之一。
PNG文件格式简史
创建 PNG 文件格式的主要原因是用于 GIF 文件格式的专利压缩算法 Lempel-Ziv-Welch。这与其他 GIF 限制一起需要替换 GIF 文件格式。 PNG 文件格式的第一个提案和名称出现在 1995 年 1 月。有关 PNG 文件格式的关键事件如下所列:
- 1996 年 10 月:PNG 规范版本 1.0 发布,后来作为 RFC 2083 出现。同样在 1996 年 10 月成为 W3C 推荐标准。
- 1998 年 12 月:发布了 1.1 版,其中有一些小的改动并添加了三个新块。
- 1999 年 8 月:发布了 1.2 版,增加了一个额外的块。
- 2003 年 11 月:PNG 成为国际标准 (ISO/IEC 15948:2003)。此版本的 PNG 与 1.2 版略有不同,并且没有添加新的块。
- 2004 年 3 月:ISO/IEC 15948:2004
GIF和PNG的功能比较
PNG文件格式被设计为简单便携、法律上不受阻碍、可互换、灵活和健壮。下表列出了除新功能外,PNG 文件格式继承的 GIF 功能。
特征 | GIF | PNG |
---|---|---|
多达 256 种颜色的索引色图像 | 是 | 是 |
支持流媒体 | 是 | 是 |
透明度 | 是 | 是 |
辅助信息 | 是 | 是 |
硬件和平台独立性 | 是 | 是 |
有效 | 是 | 是 |
高达每像素 48 位的真彩色图像 | 否 | 是 |
高达每像素 16 位的灰度图像 | 否 | 是 |
全 alpha 通道(一般透明蒙版) | 否 | 是 |
图像伽玛信息 | 否 | 是 |
可靠性 | 否 | 是 |
更快的初始演示 | 否 | 是 |
PNG文件结构
几乎所有操作系统都支持打开 PNG 文件。例如,Microsoft Windows 查看器能够打开 PNG 文件,因为操作系统默认支持作为安装的一部分。 PNG 文件由一个 PNG signature
后跟一系列 //chunks// 组成。
PNG 文件头
PNG 文件的前 8 个字节始终包含以下(十进制)值:
{{{137 80 78 71 13 10 26 10 }}}
此签名表明文件的其余部分包含单个 PNG 图像,由一系列以 IHDR 块开始并以 IEND 块结尾的块组成。
块###
每个块由四个部分组成:
长度: 一个 4 字节无符号整数,给出块数据字段中的字节数。长度只计算数据字段,不计算本身、块类型代码或 CRC。零是有效长度。尽管编码器和解码器应将长度视为无符号,但其值不得超过 231 个字节。
块类型: 4 字节的块类型代码。为了便于描述和检查 PNG 文件,类型代码被限制为由大写和小写 ASCII 字母(AZ 和 az,或 65-90 和 97-122 十进制)组成。但是,编码器和解码器必须将代码视为固定的二进制值,而不是字符串。例如,用这些字母的 EBCDIC 等效项来表示类型代码 IDAT 是不正确的。下一节将讨论块类型的其他命名约定。
块数据: 适用于块类型的数据字节(如果有)。该字段的长度可以为零。
CRC: 一个 4 字节的 CRC(循环冗余校验),根据 chunk 中前面的字节计算,包括 chunk type code 和 chunk data 字段,但不包括 length 字段。 CRC 始终存在,即使对于不包含数据的块也是如此。
块数据长度可以是最大字节数;因此,实现者不能假设块在大于字节的任何边界上对齐。
块可以以任何顺序出现,受每个块类型的限制。 (一个值得注意的限制是 IHDR 必须首先出现,IEND 必须最后出现;因此 IEND 块用作文件结束标记。)可以出现多个相同类型的块,但前提是该类型特别允许。
块类型
根据分配给块类型的 4 字节区分大小写的 ASCII 值,块类型分为 Critical 和 Ancillary 块。所有实现都必须理解并成功呈现标准关键块。一个有效的 PNG 图像必须包含一个 IHDR 块、一个或多个 IDAT 块和一个 IEND 块。
### 压缩
PNG 压缩方法 0(目前为 PNG 定义的唯一压缩方法)指定使用最多 32768 字节的滑动窗口的 deflate/inflate 压缩。 Deflate 压缩是 LZ77 的衍生产品,用于 zip、gzip、pkzip 和相关程序。已经进行了广泛的研究来支持其无专利状态。 zlib 数据流中的压缩数据存储为一系列块,每个块可以表示原始(未压缩)数据、使用固定 Huffman 码编码的 LZ77 压缩数据或使用自定义 Huffman 码编码的 LZ77 压缩数据。最后一个块中的标记位将其标识为最后一个块,从而允许解码器识别压缩数据流的结尾。
预压缩过滤
应用预压缩过滤器来准备图像数据以进行最佳压缩。 PNG过滤器方法定义了以下五种基本过滤器类型:
过滤器类型 | 名称 | 预测值 |
---|---|---|
0 | 无 | 扫描线未经修改传输 |
1 | Sub | 传输每个字节与前一个像素对应字节的值之间的差值。 |
2 | Up | Up() 过滤器与 Sub() 过滤器类似,只是将当前像素正上方的像素用作预测器,而不是其左侧。 |
3 | Average | Average() 过滤器使用两个相邻像素(左侧和上方)的平均值来预测一个像素的值。 |
4 | Paeth | Paeth() 过滤器计算三个相邻像素(左、上、左上)的简单线性函数,然后选择最接近计算值的相邻像素作为预测器。 |
过滤算法适用于“字节",而不是像素,无论图像的位深度或颜色类型如何。过滤算法对扫描线形成的字节序列起作用。如果图像包含 Alpha 通道,则 Alpha 数据会以与图像数据相同的方式进行过滤。
当图像被隔行扫描时,隔行扫描图案的每一次通过都被视为一个独立的图像用于过滤目的。过滤器对在一次传递中实际传输的像素形成的字节序列进行处理,“前一个扫描线"是在同一次传递中先前传输的扫描线,而不是整个图像中相邻的扫描线。请注意,在任何一次传递中传输的子图像始终是矩形的,但宽度和/或高度小于完整图像。当此子图像为空时,不应用过滤。