PNG文件结构分析
一、概述
PNG(Portable Network Graphics,便携式网络图形)是一种常见的图像存储格式。PNG可以支持透明背景,也可以保证在无损压缩前提下,将文件体积减到最小。PNG格式还为灰度图像和彩色图像分别16bit和48bit像素深度,还可以存储16位的α通道。
还具有以下特点:
流式读/写性
逐次逼近显示(先用低分辨率显示图像,然后逐步提高其分辨率)
真彩色数据流,但是可以有调色板数据块(PLTE)
二、文件结构
文件署名域
8字节;用于识别该文件是否为PNG文件;值如下:
数据块
每个数据块都由下表所示的四个域组成
名称 | 字节数 | 说明 |
---|---|---|
Length(长度) | 4 | 指定数据块中数据域的长度,其长度不超过(231−1)(231−1)字节 |
Chunk Type Code(数据块类型码) | 4 | 数据块类型码由ASCII字母(A-Z和a-z)组成 |
Chunk Data(数据块实际内容) | 可变长 | 存储按照Chunk Type Code指定的数据 |
CRC(循环冗余检测) | 4 | 存储用来检测是否有错误的循环冗余码 |
关键数据块(critical chunk)
文件头数据块IHDR(header chunk)
包含PNG文件中存储的图像数据的基本信息,是PNG数据流中的第一个数据块,一个PNG数据流中只能有一个IHDR
域的名称 | 字节数 | 说明 |
---|---|---|
Width | 4 bytes | 图像宽度,以像素为单位 |
Height | 4 bytes | 图像高度,以像素为单位 |
Bit depth | 1 byte | 图像深度:索引彩色图像:1,2,4或8 ;灰度图像:1,2,4,8或16 ;真彩色图像:8或16 |
ColorType | 1 byte | 颜色类型:0:灰度图像, 1,2,4,8或16;2:真彩色图像,8或16;3:索引彩色图像,1,2,4或84:带α通道数据的灰度图像,8或16;6:带α通道数据的真彩色图像,8或16 |
Compression method | 1 byte | 压缩方法(LZ77派生算法) |
Filter method | 1 byte | 滤波器方法 |
Interlace method | 1 byte | 隔行扫描方法:0:非隔行扫描;1: Adam7(由Adam M. Costello开发的7遍隔行扫描方法) |
以下为一个本地8*8像素的png文件:
00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0a | 0b | 0c | 0d | 0e | 0f |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
89 | 50 | 4e | 47 | 0d | 0a | 1a | 0a | 00 | 00 | 00 | 0d | 49 | 48 | 44 | 52 |
00 | 00 | 00 | 08 | 00 | 00 | 00 | 08 | 08 | 06 | 00 | 00 | 00 | c4 | 0f | be |
8b | 00 | 00 | 00 | 01 | 73 | 52 | 47 | 42 | 00 | ae | ce | 1c | e9 | 00 | 00 |
00 | 04 | 67 | 41 | 4d | 41 | 00 | 00 | b1 | 8f | 0b | fc | 61 | 05 | 00 | 00 |
00 | 09 | 70 | 48 | 59 | 73 | 00 | 00 | 16 | 25 | 00 | 00 | 16 | 25 | 01 | 49 |
52 | 24 | f0 | 00 | 00 | 00 | 11 | 49 | 44 | 41 | 54 | 28 | 53 | 63 | f8 | 4f |
00 | 8c | 08 | 05 | ff | ff | 03 | 00 | 84 | b5 | ff | 01 | 98 | b2 | ba | 5c |
00 | 00 | 00 | 00 | 49 | 45 | 4e | 44 | ae | 42 | 60 | 82 |
调色板数据块PLTE(palette chunk)
包含与索引彩色图像相关的彩色变换数据,置于图像数据块(image data chunk)之前。
PLTE可以包含1~256个调色板信息,每一个调色板信息由3个字节组成,因此调色板数据块所包含的最大字节数为768,调色板的长度应该是3的倍数,否则,这将是一个非法的调色板。调色板的颜色数不能超过图像色深中规定的颜色数,否则会非法。
便于非真彩色显示程序用它来量化图像数据。结构如下:
颜色 | 长度 | 含义 |
---|---|---|
Red | 1字节 | 0 = 黑,255 = 红 |
Green | 1字节 | 0 = 黑,255 = 绿 |
Blue | 1字节 | 0 = 黑,255 = 蓝 |
图像数据块IDAT(image data chunk)
包含实际的图像数据,允许编码器根据需要将压缩的数据流分为多个IDAT块,但它们必须连续出现,大小不限,但是过短时浪费空间。
可以出现在PNG数据流中的任何位置。
它是压缩算法的输出流。
图像结束数据IEND(image trailer chunk)
用于标记PNG文件(数据流已经结束),必须放在文件的尾部。
IEND均为:
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。
举个例子
以下为一个本地8*8像素的png文件:
00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0a | 0b | 0c | 0d | 0e | 0f |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
89 | 50 | 4e | 47 | 0d | 0a | 1a | 0a | 00 | 00 | 00 | 0d | 49 | 48 | 44 | 52 |
00 | 00 | 00 | 08 | 00 | 00 | 00 | 08 | 08 | 06 | 00 | 00 | 00 | c4 | 0f | be |
8b | 00 | 00 | 00 | 01 | 73 | 52 | 47 | 42 | 00 | ae | ce | 1c | e9 | 00 | 00 |
00 | 04 | 67 | 41 | 4d | 41 | 00 | 00 | b1 | 8f | 0b | fc | 61 | 05 | 00 | 00 |
00 | 09 | 70 | 48 | 59 | 73 | 00 | 00 | 16 | 25 | 00 | 00 | 16 | 25 | 01 | 49 |
52 | 24 | f0 | 00 | 00 | 00 | 11 | 49 | 44 | 41 | 54 | 28 | 53 | 63 | f8 | 4f |
00 | 8c | 08 | 05 | ff | ff | 03 | 00 | 84 | b5 | ff | 01 | 98 | b2 | ba | 5c |
00 | 00 | 00 | 00 | 49 | 45 | 4e | 44 | ae | 42 | 60 | 82 |
首先是八个字节的文件头标志,标识着png文件:
89 50 4e 47 0d 0a 1a 0a
IHDR数据块:
00 00 00 0d 说明IHDR头块长为13
49 48 44 52 IHDR标识(ascii码为IHDR)
PLTE和IDATA:
00 00 00 08 图像的宽 8像素
00 00 00 08 图像的高 8像素
08 表示色深,这里是2^8=256,即这是一个256色的图像
06 颜色类型,查表可知这是带α通道数据的真彩色图像
00 PNG Spec规定此处总为0(非0值为将来使用更好的压缩方法预留),表示使压缩方法(LZ77派生算法)
00 PNG Spec规定此处总为0(非0值为将来使用更好的压缩方法预留),表示使压缩方法(LZ77派生算法)
00 非隔行扫描
c4 0f be 8b CRC校验字段
IEND:
00 00 00 00 49 45 4E 44 AE 42 60 82
辅助数据块
分为4大类,描述一些细节信息,下文介绍。
数据块总览
数据块符号 | 数据块名称 | 多数据块 | 可选否 | 位置限制 |
---|---|---|---|---|
IHDR | 文件头数据块 | 否 | 否 | 第一块 |
cHRM | 基色和白色点数据块 | 否 | 是 | 在PLTE和IDAT之前 |
gAMA | 图像γ数据块 | 否 | 是 | 在PLTE和IDAT之前 |
sBIT | 样本有效位数据块 | 否 | 是 | 在PLTE和IDAT之前 |
PLTE | 调色板数据块 | 否 | 是 | 在IDAT之前 |
bKGD | 背景颜色数据块 | 否 | 是 | 在PLTE之后IDAT之前 |
hIST | 图像直方图数据块 | 否 | 是 | 在PLTE之后IDAT之前 |
tRNS | 图像透明数据块 | 否 | 是 | 在PLTE之后IDAT之前 |
oFFs | (专用公共数据块) | 否 | 是 | 在IDAT之前 |
pHYs | 物理像素尺寸数据块 | 否 | 是 | 在IDAT之前 |
sCAL | (专用公共数据块) | 否 | 是 | 在IDAT之前 |
IDAT | 图像数据块 | 是 | 否 | 与其他IDAT连续 |
tIME | 图像最后修改时间数据块 | 否 | 是 | 无限制 |
tEXt | 文本信息数据块 | 是 | 是 | 无限制 |
zTXt | 压缩文本数据块 | 是 | 是 | 无限制 |
fRAc | (专用公共数据块) | 是 | 是 | 无限制 |
gIFg | (专用公共数据块) | 是 | 是 | 无限制 |
gIFt | (专用公共数据块) | 是 | 是 | 无限制 |
gIFx | (专用公共数据块) | 是 | 是 | 无限制 |
IEND | 图像结束数据 | 否 | 否 | 最后一个数据块 |
几种辅助数据块
tRNS
透明度
Colour type为0、2或3的PNG图像(索引彩色图像)通过且tRNS块来显示透明信息,而Colour type为4或6的PNG图像(带α通道数据的灰度/真彩色图像)不需要此数据块就可以显示透明信息(直接从IDAT块的数据中提取α分量)。
如果存在tRNS块,则必须位于第一个IDAT块之前、PLTE块之后。
sRGB色彩空间
如果存在
sRGB
块,则图像样本符合 sRGB 颜色空间[
IEC 61966-2-1]
,并且应使用国际颜色联盟[
ICC-1]
和[
ICC-1A]
定义的指定渲染意图进行显示。
sRGB块的Chunk data部分只有1个字节:
名称 | 长度 | 说明 |
---|---|---|
Rendering intent | 1字节 |
0:Perceptual,用于牺牲色度精度以更好地适应输出设备的图像,例如照片; 1:Relative colorimetric,用于需要颜色外观匹配(相对于输出设备白点)的图像,例如标志; 2:Saturation,用于牺牲亮度和色相以保持合适的饱和度的图像,例如图表和图形; 3:Absolute colorimetric,用于需要保留绝对色度的图像,例如用于其他输出设备的图像预览(校样)。 |
建议写入
sRGB
块的 PNG 编码器也写入
gAMA
块(以及可选的
cHRM
块)以与不使用
sRGB
块的解码器兼容。仅应使用以下值。
数据块 | Chunk data的取值(十进制) |
---|---|
gAMA | 45455 |
cHRM |
White point x:31270 White point y:32900 Red x:64000 Red y:33000 Green x:30000 Green y:60000 Blue x:15000 Blue y:6000 |
当存在
sRGB
块时,建议识别它并能够进行颜色管理[
ICC]
的解码器忽略
gAMA
和
cHRM
块,而改用
sRGB
块。
物理分辨率pHYs
pHYs块指定用于显示图像的预期像素大小或纵横比。它包含了:
每单位像素数,X 轴 | 4字节(PNG无符号整数) |
---|---|
每单位像素数,Y轴 | 4字节(PNG无符号整数) |
单位说明符 |
1字节(0:单位是米 1:单位未知) |
当单位说明符为 0 时,
pHYs
块仅定义像素纵横比;像素的实际大小仍未指定。
如果不存在
pHYs
块,则假定像素为正方形,并且未指定每个像素的物理尺寸。
压缩文本数据zTXt
推荐使用
zTXt
块来存储大块文本。一个zTXT块包含:
关键词 | 1-79字节(字符串) |
---|---|
空分隔符 | 1字节 |
压缩方式 | 1个字节 |
压缩文本数据流 | n字节 |
660221)]
压缩文本数据zTXt
推荐使用
zTXt
块来存储大块文本。一个zTXT块包含:
关键词 | 1-79字节(字符串) |
---|---|
空分隔符 | 1字节 |
压缩方式 | 1个字节 |
压缩文本数据流 | n字节 |