PNG文件的结构

PNG文件的结构

一. 概述

PNG(Portable Network Graphics,便携式网络图形)是一种非常常见的图像存储格式,诞生于20世纪90年代,其设计目的是试图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。除了多数人所熟知的PNG支持透明背景这一特性,PNG格式更为重要的一点是其能在保证无损压缩的前提下,将文件体积减小到最小,此外对灰度图像和彩色图像分别提供了16 bit和48 bit深度,并且还可存储多达16 bit的α通道数据。

二. PNG文件结构

PNG文件由文件署名域(8字节)和最少3个数据块(Chunk)按照特定的顺序排列而成。

数据块分为两类:

关键数据块(Critical Chunk):必须包含的数据块。一个有效的PNG文件必须包含一个IHDR块、至少一个IDAT块和一个IEND块;以及辅助数据块(Ancillary Chunk):可选的数据块。也就是说,编码器并不必须写入辅助数据块,解码器也可以选择忽略它们,但鼓励编码器在有相关数据时写入标准的辅助数据块、解码器在可行的条件下对这些内容进行解码。

每个数据块都包含4部分:

名称长度说明Length4字节无符号整数,注意只表示Chunk Code部分的长度,允许为0,其值不超过

(

2

31

1

)

(2^{31}-1)

(231-1)字节Chunk type code4字节标识该数据块的类型,由ASCII码的A-Z和a-z组成Chunk data可变(应与Length值相等)存储指定数据,长度可为0CRC4字节循环冗余检测

三. PNG文件具体构成

1. PNG文件签名(PNG file signature)

文件的前8字节为PNG文件签名,便于计算机识别文件类型。PNG文件对应的标识为89 50 4E 47 0D 0A 1A 0A。以一张带有透明背景的微信表情为例,使用Synalize it! Pro以二进制方式打开。其文件署名域可参见图2(紫色部分)。

图1 示例图像1:微信表情[机智]

图1-1 PNG文件签名

下面将依次介绍各个数据块的结构。

2. 关键数据块

(1) IHDR chunk(Image Header chunk,文件头数据块)

IHDR必须为PNG文件的第一个数据块,它包含了一个PNG文件的基本信息。一个PNG数据流中只能有一个IHDR数据块。

IHDR由13字节组成:

名称字节数说明Width4字节图像宽度(像素)Height4字节图像高度(像素)Bit depth1字节图像深度:表示每个采样点占用的bit数索引(indexed)彩色图像:1,2,4或8;灰度图像:1,2,4,8或16;真彩色图像:8或16Colour type1字节颜色类型:0:灰度图像, 深度为1,2,4,8或16 bit;2:真彩色(truecolor)图像,深度为8或16 bit;3:索引彩色图像,深度为1,2,4或8 bit;4:带α通道数据的灰度图像,深度为8或16 bit;6:带α通道数据的真彩色(truecolor with alpha)图像,深度为8或16 bitCompression method1字节压缩方法:0:LZ77派生算法(目前仅定义了0)其他值:无效;为未来扩展的压缩方法预留Filter method1字节滤波器方法:0(目前仅定义了0)其他值:无效Interlace method1字节隔行扫描方法:0:非隔行扫描;1: Adam7隔行扫描方法

同样以图1为例,其IHDR字段如下:

图1-2 IHDR块

由数据可知,该图像:

Length:0x00 00 00 0D(13),表示IHDR块的Chunk data部分长度为13字节Chunk type code:0x49 48 44 52(ASCII码“IHDR”),标识该块类型Chunk data:

Width:0x00 00 00 40(64)Height:0x00 00 00 40(64)Bit depth:8,表示8 bit深度Colour type:3,表示索引彩色图像Compression method:0Filter method:0Interlace method:0,非隔行扫描 CRC:0x9D B7 81 EC

(2) PLTE chunk(Palette chunk,调色板数据块)

若PLTE块存在,必须要放在IDAT块之前,且只能有1个此块。

PLTE块包含有与索引彩色图像 (indexed-colour image) 相关的彩色变换数据,包含1—256个调色板信息,其中每条信息由8 bit表示:

颜色长度含义Red1字节0 = 黑,255 = 红Green1字节0 = 黑,255 = 绿Blue1字节0 = 黑,255 = 蓝

调色板的作用在于,使得图像深度较小的图像,可以使用索引号来正确表示颜色。

PLTE块还必需满足以下限制条件,否则会被判定为不合法:

调色板的长度应为3的倍数,即PLTE块最大字节数为256 × 3 = 768 B;

调色板信息的数量不能超过图像深度可以表示的范围(如对于4 bit深度的图像,最多有16条调色板信息,但允许少于16条);

对于Colour type 3的PNG图像(索引图像),PLTE块是必需的,此时调色板的颜色索引从0开始编号,然后是1,2……; 对于Colour type为2和6的图像,PLTE块是可选的,此时调色板将提供一个1—256的建议颜色集,以便软件或屏幕不支持显示真彩色时量化真彩色图像; Colour type为0和4的图像中不能出现PLTE块。

仍以图1为例,其PLTE块为:

图1-3 PLTE块

其中:

Length:0x00 00 02 04(516),表示PLTE块的数据部分有516字节(是3的倍数)

Chunk type code:0x50 4C 54 45(ASCII码“PLTE”)

Chunk data:例如,

第0种颜色,0x 00 00 00,即

(

R

.

G

,

B

)

=

(

0

,

0

,

0

)

(R.G,B) = (0,0,0)

(R.G,B)=(0,0,0);

第1种颜色,0x B9 81 3F,即

(

R

.

G

,

B

)

=

(

185

,

129

,

63

)

(R.G,B) = (185,129,63)

(R.G,B)=(185,129,63);

第100中颜色,0xFF FF DD,即

(

R

.

G

,

B

)

=

(

255

,

255

,

238

)

(R.G,B) = (255,255,238)

(R.G,B)=(255,255,238)(一种接近于白色的颜色)。现在将其修改为0x00 00 00(纯黑色),结果为:

图1-4 修改了调色板之后的[机智]表情

这与预想的结果一致;

CRC:0x5A 89 F7 7C

(3) IDAT chunk(Image data chunk,图像数据块)

IDAT块包含实际的图像数据。此外:

允许编码器根据需要将压缩的数据流分为多个IDAT块,但它们必须连续出现;并不限定IDAT块的大小,但过短的IDAT块会浪费更多空间;IDAT块可以出现在压缩数据流的任何位置。

(4) IEND chunk(Image trailer chunk,图像结束数据块)

IEND块必需出现在文件的末尾,用来标志PNG数据流的结束。该数据块的数据字段是空的。例如图1的IEND块为:

图1-5 IEND块

可以看出,其只包含Length(0)、Chunk Type Code(IEND)和CRC(0xAE 42 60 82)。

3. 辅助数据块

辅助数据块主要包含以下4类、14种:

表示透明信息(Transparency information)的数据块:tRNS chunk(Transparency chunk,透明信息数据块)

表示色彩空间信息(Colour space information)的数据块:

gAMA chunk(Image gamma chunk,图像γ数据块)cHRM chunk(Primary chromaticities chunk,基色和白色度数据块)sRGB chunk(Standard RGB colour space chunk,标准RGB色彩空间数据块)iCCP chunk(Embedded ICC profile chunk) 表示文本信息(Textual information)的数据块:

tEXt chunk(Textual data chunk,文本信息数据块)zTXt chunk(Compressed textual data chunk,压缩文本数据块)iTXt chunk(International textual data chunk) 表示其他信息(Miscellaneous information)的数据块:

bKGD chunk(Background colour chunk,背景颜色数据块)

pHYs chunk(Physical pixel dimensions chunk,物理像素尺寸数据块)

sBIT chunk(Significant bits chunk,样本有效位数据块)

sPLT chunk(Suggested palette chunk)

hIST chunk(Palette histogram chunk,图像直方图数据块)

tIME chunk(Image last-modification time chunk,图像最后修改时间数据块)

下面就几个问题,简要介绍其中几个辅助数据块。

(1) 如何将PNG部分呈现为“透明”?——tRNS chunk

Colour type为0、2或3的PNG图像(索引彩色图像)通过且tRNS块来显示透明信息,而Colour type为4或6的PNG图像(带α通道数据的灰度/真彩色图像)不需要此数据块就可以显示透明信息(直接从IDAT块的数据中提取α分量)。

如果存在tRNS块,则必须位于第一个IDAT块之前、PLTE块之后(若存在)。

对于Colour type 3的索引彩色图像(如下图),tRNS块包含了一系列对应于PLTE块信息的单字节α值(通常在这种情况下,图像中不包含完整的α通道)。α值与8 bit全α通道具有相同的含义: 0表示完全透明,255表示完全不透明,且与图像位深度无关。tRNS块所包含的α值不能超过调色板信息条数,但可以少于,在这种情况下,其余调色板条目的α值为255。

图1-6 tRNS块

(2) 辅助颜色管理——sRGB chunk、gAMA chunk、cHRM chunk

除了使用PLTE块,PNG文件还可以使用sRGB进行颜色识别和颜色管理。

如果存在sRGB块,则图像样本符合sRGB色彩空间[IEC 61966-2-1]。

sRGB块的Chunk data部分只有1个字节:

名称长度说明Rendering intent1字节0:Perceptual,用于牺牲色度精度以更好地适应输出设备的图像,例如照片;1:Relative colorimetric,用于需要颜色外观匹配(相对于输出设备白点)的图像,例如标志;2:Saturation,用于牺牲亮度和色相以保持合适的饱和度的图像,例如图表和图形;3:Absolute colorimetric,用于需要保留绝对色度的图像,例如用于其他输出设备的图像预览(校样)。

例如对于下面的照片(图2),其sRGB块如图2-1所示:

图2 示例图像2

图2-1 sRGB块

其Chunk data部分为0x00(照片)。

标准中还建议,编码器除了写入sRGB块外,还写入gAMA块(以及可选的cHRM块),以便与不使用sRGB块的PNG解码器兼容。当sRGB块存在时,标准建议能对其识别并进行颜色管理的解码器忽略gAMA和cHRM块,而改用sRGB块。

gAMA块和cHRM块的Chunk data部分只能取以下值:

数据块Chunk data的取值(十进制)gAMA45455cHRMWhite point x:31270White point y:32900Red x:64000Red y:33000Green x:30000Green y:60000Blue x:15000Blue y:6000

(3) 如何表示物理分辨率?——pHYs chunk

pHYs块的Chunk data由三部分构成:

名称长度说明Pixels per unit, X axis4字节Pixels per unit, Y axis4字节Unit specifier1字节0:单位未知1:单位为米

例如,图2的pHYs块如下图所示:

图2-2 pHYs块

从中可知,该图像水平、垂直方向上的物理分辨率(像素密度)均为2835(0x00 00 0B 13)像素/米。

(4) 如何在PNG中存储EXIF信息?——eXIf chunk

EXIF,可交换图像文件格式,是专门为数码相机拍摄的照片所设定的,用于记录照片属性信息和拍摄参数的数据。

但eXIf块并不在[前面所列出的14种辅助数据块的范围](#3. 辅助数据块)中。实际上,辅助数据块允许编码器自定义,例如图2的该数据块为:

图2-3 eXIf块

从中我们可以看出一些图像元数据,例如:

拍摄设备:Apple iPhone XR镜头:Apple iPhone XR back camera 4.25 mm ƒ/1.8拍摄时间:2019.12.16 10:07:12

四. 参考文献

Portable Network Graphics (PNG) Specification (Second Edition)