块的基本理论
众所周知,所有的信息在计算机中以位的形式存在(0|1)8位是一个字节,可以表示成两个16进制数,例如0xFC因为4位对应一个16进制数嘛。PNG这种图片也不例外,它也是由位组成的,不过我们提供了更好的抽象,文件块(chunks)每个文件块符合下面的格式
- 长度字段 (4字节): 表示数据字段的长度。
- 类型字段 (4字节): 表示块的类型。
- 数据字段 (N字节): 实际的数据内容。
- CRC字段 (4字节): 数据字段类型字段的 CRC 校验码。
PNG中,文件块有以下的类型
- IHDR :表明了图像的格式
- ICCP:表明了图像的色彩类型
- IDAT:存储像素信息的块
- IEND:标明PNG结束的块
使用010editor来解析PNG
将这张240*240的PNG图像拖入解析工具中,我们可以看到如下的界面
位…
每一行的每一个元素是两个16进制数,也就是说,每一个元素,就是一个字节,而0000h指的是16进制的偏移量,010中,每一行是16个元素(字节),所以过一行,0000h变为0010h
总头
签名为:89 50 4E 47 0D 0A 1A 0A
这是PNG文件的文件头(Signature): PNG文件以8字节的签名开头,表示这是一个PNG文件。
- 89: 这个字节是为了确保PNG文件不会被误解为其他类型的文件。它的值在ASCII中不是可打印字符,可以防止某些早期的文本编辑器或文件查看器误解PNG文件。
- 50 4E 47: 这三个字节对应于ASCII字符“PNG”。它明确标识了文件格式为PNG(在十六进制中是
50
(P)、4E
(N)、47
(G))。 - 0D 0A: 这是回车换行(CRLF),通常在文本文件中作为行结束符,在PNG中作为文件的一部分。
- 1A: 这是一个ASCII控制字符(Substitute),它标识文件的结束,防止文件被截断或损坏。在一些老旧系统中,它被用作文件结束标志。
- 0A: 这是换行符(LF),在PNG文件的最后用来分隔文件签名和后续数据。
在ASCII解析的部分容易看出。同样,这是我们识别PNG的快速路径
这也说明,你把一个JPG文件,仅改变后缀,是改不了存储方式的,真类型在内部用位记着
IHDR部分
- 长度字段 (4字节): 00 00 00 0D 标识IHDR数据段有13字节
- 类型字段 (4字节): 49 48 44 52即为ASCII码中的IHDR,标明这个文件使用PNG的IHDR格式存储
- 数据字段 (N字节): 实际的数据内容
- 00 00 00 F0 前四个字节表示宽度,这里是240像素
- 00 00 00 F0 这4个字节表示高度,这是240像素
- 08 06 00 00 这4个字节
08
:位深度(8位)。06
:颜色类型(真彩色加 Alpha)。00
:压缩方法(无压缩)。(PNG中仅支持0)00
:滤波方法(无滤波)。(PNG中仅支持0)00
:交错方式(无交错)。如果后面跟着6个0,表示这个PNG是无损的格式,每个像素都存在里面
- CRC字段 (4字节): 数据字段类型字段的 CRC 校验码。
3E 55 E9 92
:这是IHDR
块的 CRC 校验码,用于验证IHDR
块的类型字段。
ICCP部分
ICCP主要是用于标识颜色空间的,我们不能像读IHDR那样从ICCP中读出类似宽高的有用信息
- 长度字段 (4字节): 00 00 01 22标识数据有290字节
- 类型字段 (4字节): 69 43 43 50标识ICCP的ASCII码
- 数据字段 (N字节): 实际的数据内容。
- CRC字段 (4字节): 78 FA 2F D7验证数据的字段
IDAT部分
和上面的内容差不多,不过你会发现,IDAT每个的长度都是200ch(长度字段为00 00 20 00)8192字节
IEND部分
00 00 00 00
//IEND的长度为0
49 45 4E 44
//IEND
AE 42 60 82
//CRC码