PNG格式是一种采用无损压缩算法的位图格式,支持索引、灰度、RGB三种颜色方案以及alpha通道等特性。
PNG能够支持256色调色板技术,产生文件的体积小,最高支持24位真彩色图像以及8位灰度图像,支持存在附加文本信息,以保留图像名称、作者、著作权、创作时间、注释等,支持无损压缩,适合在网络传输中快速显示预览效果后再显示全貌。
本文借助所选PNG图片的二进制表示来加深对PNG图像文件的理解,所选图片为:
在vs2019中使用二进制格式打开上面的图片,就可以看到用十六进制显示的PNG文件的信息了
ps:推荐“格式工厂”,可以将视频、音频、图像、文档等转换成需要的格式
PNG二进制文件读取的时候是高位在前低位在后。
PNG图像格式的文件由一个8字节的PNG文件表示域和3个以上的后续数据块(IHDR、IDAT、IEND)组成。数据块又分为关键数据块,也是一个PNG文件必须要包含的数据块,还有可选数据块。
一个标准PNG文件的格式为:
| PNG文件标志 | PNG数据块 | …… | PNG数据块 |
可以通过头文件的方式来看是否是一个PNG文件。
PNG文件头共8个字节,用来识别该文件是否是PNG文件,这一部分的值为
十进制数 | 137 | 80 | 78 | 71 | 13 | 10 | 26 | 10 |
---|---|---|---|---|---|---|---|---|
十六进制数 | 89 | 50 | 4e | 47 | 0d | 0a | 1a | 0a |
其中第一个字节0x89超出量ASCII字符的范围,这样可以避免某些软件将PNG文件当作文本文件来处理。
观察”小猪佩奇“的图片:
其头部信息与PNG文件的头部信息一样,可以确定是PNG格式的图片
PNG定义了两种类型的数据块,一种是关键数据块,也就是标准数据块,定义了4个标准数据块,每个PNG文件都必须包含它们;另一种是可选数据块。
常见的PNG格式数据块有
数据块符号 | 数据块名称 | 多数据块 | 可选否 | 位置限制 |
---|---|---|---|---|
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 | 图像结束数据 | 否 | 否 | 最后一个数据块 |
还可能会有iCPCP数据块,是PNG解码时进行特殊的颜色处理信息。
无论是关键数据块还是可选数据块,它们大致都由以下几部分构成:
名称 | 字节数 | 说明 |
---|---|---|
Length(长度) | 4字节 | 指定数据块中数据(Chunk Data)部分的长度,其长度最大为 ( 2 31 − 1 ) (2^{31}-1) (231−1)字节 |
Chunk Type Code(数据块类型码) | 4字节 | 数据块类型码由ASCII字母( A ∼ Z A\sim Z A∼Z和 a ∼ z a\sim z a∼z)组成 |
Chunk Data(数据块数据) | 可变长度 | 存储按照Chunk Type Code指定的数据 |
CRC(循环冗余检测) | 4字节 | 存储用来检测是否有错误的循环冗余码(针对Chunk Type Code和Chunk Data部分数据计算得到) |
只展示Chunk Data部分的结构
文件头数据块,包含PNG文件中存储的图像数据的基本信息,是数据部分的第一个数据块,并且一个PNG文件中只能有一个文件头数据块,其具体组成如下
域的名称 | 字节数 | 说明 |
---|---|---|
Width | 4字节 | 图像宽度,以像素为单位 |
Height | 4字节 | 图像高度,以像素为单位 |
Bit depth | 1字节 | 图像深度:(数字代表位深) 索引彩色图像:1,2,4或8 灰度图像:1,2,4,8或16 真彩色图像:8或16 |
Color Type | 1字节 | 颜色类型:(数字代表位深) 0:灰度图像, 1,2,4,8或16 2:真彩色图像,8或16 3:索引彩色图像,1,2,4或8 4:带 α \alpha α通道数据的灰度图像,8或16 6:带 α \alpha α通道数据的真彩色图像,8或16 |
Compression method | 1字节 | 压缩方法(LZ77派生算法),仅支持压缩方式0(deflate压缩方式) |
Filter method | 1字节 | 滤波器方法,在PNG的白皮书中仅定义了方法0,然而所有的5种方法都被支持 |
Interlace method | 1字节 | 隔行扫描方法: 0:非隔行扫描 1:Adam7(由Adam M.Costello开发的7遍隔行扫描方法) |
α \alpha α通道表示一张图片的透明和半透明度
观察“小猪佩奇”图片:
调色板数据块包含有与索引彩色图像相关的彩色变换数据,它仅与索引彩色图像有关,要放在图像数据块IDAT之前。
真彩色的PNG数据(颜色类型为2/6)也可以有调色板数据块,可以便于非真彩色显示程序用它来量化图像数据从而显示图像。
调色板实际是一个彩色索引查找表,它的值可以是1~256中的任一个数,每个值的信息用3个字节表示。彩色查找表其实是指表示彩色图像本身的像素值和彩色查找表入口地址(可以用索引来类比理解)有一个变换关系,通过彩色图像本身的像素值得到查找表的索引(入口地址),找到对应查找表中用来显示的像素值,这些颜色是真实的,但是不是图像本身的颜色。
调色板的数据块数据表示为
颜色 | 字节 | 说明 |
---|---|---|
Red | 1字节 | 0=黑色,255=红色 |
Green | 1字节 | 0=黑色,255=绿色 |
Blue | 1字节 | 0=黑色,255=蓝色 |
调色板的长度应该是3的倍数,否则就是一个非法的调色板。
调色板的条目数不应超过图像位深所能表示的范围(如位深为4,则调色板条目数不能超过 2 4 = 16 2^4=16 24=16),否则会导致图像不合法。
如果调色板条目数少于允许的条目数,那么此时图像数据中任何超出范围的像素值都会被认为是错误的。
另外,对于每个样本颜色,调色板都用8位来表示。
在本张图中没有找到与调色板有关的信息
存储实际数据,在数据流中可包含多个连续顺序的图像数据块。
观察“小猪佩奇”:
其下一个数据块为
用来标记PNG文件或者数据流已经结束了,要放在文件的尾部
观察“小猪佩奇”:
辅助数据块主要包含以下4类、14种:
表示透明信息(Transparency information)的数据块:
表示色彩空间信息(Colour space information)的数据块:
表示文本信息(Textual information)的数据块:
表示其他信息(Miscellaneous information)的数据块:
物理像素尺寸数据块,表示了图片的像素尺寸或者宽高比,其定义如下
字节数 | 说明 |
---|---|
4字节 | x轴上每米像素的数量,单位:像素 |
4字节 | y轴上每米像素的数量,单位:像素 |
1字节 | 单位,1表示以米为单位,0表示未知单位 |
α \alpha α通道是指一张图片的透明和半透明度。
对于颜色类型为4或6的图片来讲,其 α \alpha α通道的值就跟在对应的灰度值或 R 、 G 、 B R、G、B R、G、B值的后面,因此不需要有tRNS数据块;对于颜色类型为0或2的图片来说,用2个字节来代表采样值,只有被采样的灰度值或 R 、 G 、 B R、G、B R、G、B的值被视为透明,其余的值都为完全不透明;对于颜色类型为3的图片来说,每个样点是调色板的索引,大小为1个字节,它是指调色板索引对应像素的 α \alpha α值,同样的,0是全透明,255是全不透明, 无论图像位深如何,tRNS块包含的alpha值不能超过调色板数目,但tRNS块包含的alpha值可以少于调色板数目,此时所有剩下的条目的alpha值被设为255。
查看图片:
除了上面分析的数据块以外,该图片还具有sRGB和gAMA数据块。
如果存在sRGB块,图像样本符合sRGB颜色空间[IEC 61966-2-1],并应使用由国际颜色联盟[ICC-1]和[ICC-1A]定义的指定渲染意图来显示。
其数据块部分只有1个字节:
名称 | 长度 | 说明 |
---|---|---|
Rendering intent | 1字节 | 0:Perceptual,用于牺牲色度精度以更好地适应输出设备的图像,例如照片; 1:Relative colorimetric,用于需要颜色外观匹配(相对于输出设备白点)的图像,例如标志; 2:Saturation,用于牺牲亮度和色调以保持合适的饱和度的图像,例如图表和图形; 3:Absolute colorimetric,用于需要保留绝对色度的图像,例如用于不同输出设备的图像预览(校样)。 |
为了与不使用sRGB块的解码器兼容,通常也会跟一个gAMA块以及可选的cHRM块。
当sRGB块存在时,能够识别它并能够进行颜色管理的解码器忽略gAMA和cHRM块,而使用sRGB块。建议sRGB和iCCP块不要同时出现在PNG数据流中。
gAMA和cHRM只能取下面的值:
名称 | 数据块取值 |
---|---|
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 |
观察该图片: