PNG文件格式
PNG文件结构
PNG图像格式文件(或者称为数据流)由一个8字节的PNG文件署名(PNG file signature)域和按照特定结构组织的3个以上的数据块(chunk)组成。
PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是必需的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块,如 bKGD cHRM gAMA hIST iCCP sBIT sPLT sRGB tEXt tIME tRNS zTXt。关键数据块定义了4个标准数据块,每个PNG文件都必须包含它们,PNG读写软件也都必须要支持这些数据块。虽然PNG文件规范没有要求PNG编译码器对可选数据块进行编码和译码,但规范提倡支持可选数据块。
以下PNG文件都以VS2019中的二进制编辑器方式打开,示例文件为:
PNG文件标识
PNG文件头位置总是由固定的8个字节来描述的:
| 00000000 | 89 50 4E 47 0D 0A 1A 0A |
|---|---|
| 对应ASCII码 | ё P N G CR LF SUB LF |
其中第一个字节0x89是为了避免某些软件将PNG文件当做文本文件来处理,后四个字节是控制字符。ASCII码对照表
JPEG,PNG,GIF,BMP等图片都具有不同的图像标识符号,判读一个文件的正确mimeType类型,更应该通过标识符,而不是通过后缀名判断。
PNG数据块
数据块结构
PNG文件从0×08开始,每个数据块由四部分组成:
- 数据块长度
一个4字节的无符号整数,仅指数据块的数据字段的长度(以字节计)。 长度只计算数据域,为了兼容一些不支持无符号的语言,所以长度限制在(2³¹-1)字节,不能达到(2³²-1)字节。 - 数据块类型
一个4字节的块类型代码。 为了便于描述和检查PNG文件,类型代码仅限于大写和小写的ASCII字母(A - Z和a - z,使用十进制ASCII代码表示为65-90和97-122)。 然而,编码器和解码器必须把代码作为固定的二进制值而非字符串来处理。 - 数据块数据
数据块的数据域,存储按照数据块类型码指定的数据(如果有的话)。 该字段可以是长度为零。 - 循环冗余检测(校验信息)
一个4字节的CRC(循环冗余校验)计算,使用的是CRC32标准算法。在所述块的前面的字节,包括该块类型的代码和数据块的数据字段,但是不包括长度字段。 CRC始终存在,即使不包含数据块。CRC码生成多项式:x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
但经测试,删除示例文件的校验信息后,仍能打开图像
关键数据块
IHDR(header chunk)
文件头数据块,包含PNG文件中存储的图像数据的基本信息,并要作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。
文件头数据块由13字节组成,它的格式如图所示。
00 00 00 0D 说明数据块长为13
49 48 44 52 IHDR标识
00 00 02 38 图像的宽,568像素
00 00 01 77 图像的高,375像素
08 色深,2⁸=256,即这是一个256色的图像(也有可能颜色数不超过16)
06 颜色类型,带α通道数据的真彩色图像
00 PNG Spec规定此处总为0(非0值为将来使用更好的压缩方法预留),表示使压缩方法(LZ77派生算法)
00 同上
00 非隔行扫描
A8 93 31 D2 CRC校验
PLTE(palette chunk)
调色板数据块,包含有与索引彩色图像(indexed-color image)相关的彩色变换数据。PLTE可以包含1~256个调色板信息,每一个调色板信息由3个字节组成,因此,调色板的长度应该是3的倍数,否则,这将是一个非法的调色板。对于索引图像,调色板信息是必须的,调色板的颜色索引从0开始编号,然后是1、2……,调色板的颜色数不能超过色深中规定的颜色数,否则,这也将导致PNG图像不合法。真彩色图像和带alpha通道数据的真彩色图像也可以有调色板数据块,目的是便于非真彩色显示程序用它来量化图像数据,从而显示该图像。
经查找,示例一没有调色板,在此仅对示例二分析。
00 00 00 27 调色板数据长为39字节,有13个颜色数
50 4C 54 45 PLTE标识
B7 00 34 颜色0
FF 99 00 颜色1
…… ……
FF FF 00 颜色12
48 29 75 2C CRC校验
IDAT(image data chunk)
图像数据块,存放着图像真正的数据信息,在数据流中可包含多个连续顺序的图像数据块。(如图,示例一图像数据块有4+4+2048+4=2060字节)
IEND(image trailer chunk)
图像结束数据,用来标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。通常是: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。
参考文献:
https://baike.baidu.com/item/png/174154?fr=aladdin
https://www.jianshu.com/p/e4a7eb127d53
https://blog.csdn.net/qq_21950929/article/details/79198814