IDAT__1">IDAT 结构
在PNG文件中,每个块(包括IDAT块)的结构是固定的,CRC校验码总是位于每个块的末尾。具体来说,每个块的结构如下:
长度(4字节):表示数据部分的长度。
类型(4字节):表示块的类型,如IHDR、IDAT、IEND等。
数据(可变长度):块的具体内容。
CRC(4字节):用于校验数据的完整性。
IDAT 的结尾标识是 IEND
IDAT 块数据表示含义
样例数据如下: 最开始 00 00 00 00
不需要关注,是其他的信息
00 00 FF F4
是第一个 IDAT 的长度。这个长度的计算不包含本身、IDAT、CRC 校验值,仅代表数据的长度。
49 44 41 54
表示 IDAT 字符。
从 第一行的 35 7A C6 5C
到第 10 行的 A2 BF 1E 94
是数据本身, 长度就是计算的这个。
第 11 行 的 第二个块 IDAT 的长度 00 00 FF F4
之前的四个字节 87 6E FA 22
表示第一个 IDAT 的 CRC 校验。
最前面的 1:0000h 表示 如下:
1: 第 1 个 IDAT 块
0000h: 表示开始的长度。
0 1 2 3 4 5 6 7 8 9 A B C D E F
1:0000h: 00 00 00 00 00 00 FF F4 49 44 41 54 35 7A C6 5C ......ÿôIDAT5zÆ\
1:0010h: 49 A3 06 56 A7 2D 44 F9 C6 F9 4F 95 A1 60 24 A7 I£.V§-DùÆùO•¡`$§
1:0020h: 84 4D E0 EB 76 A0 49 A7 06 6A 67 05 5E CF 83 FE „Màëv I§.jg.^σþ
1:0030h: 5E F6 29 1D 4B FA 99 22 20 C6 8E A3 72 86 FD EA ^ö).Kú™" ÆŽ£r†ýê
1:0040h: F0 36 F8 06 F5 3C 5F C9 64 12 C4 CF F3 34 E5 57 ð6ø.õ<_Éd.ÄÏó4åW
1:0050h: 41 EE 4A 65 83 07 D2 8D BC 89 25 AD 68 DC AE F0 AîJeƒ.Ò
........................................................ ................
1:FFE0h: EE C4 85 87 38 76 75 21 16 A9 86 80 46 CE 3A C3 îÄ…‡8vu!.©†€FÎ:Ã
1:FFF0h: 25 22 5E CA BF 87 46 C7 93 18 D8 4C A2 BF 1E 94 %"^Ê¿‡FÇ“.ØL¢¿.”
2:0000h: 87 6E FA 22 00 00 FF F4 49 44 41 54 57 62 4F B6 ‡nú"..ÿôIDATWbO¶
2:0010h: D0 5B 8B 8C 97 FE 63 3E 73 FE 63 CC F1 FD 1A 20 Ð[‹Œ—þc>sþcÌñý.
2:0020h: 1B B3 7A 3B 02 E4 60 62 C8 F1 BB 72 DB C7 31 79 .³z;.ä`bÈñ»rÛÇ1y
当 IDAT 的长度错误时,就会导致图片无法正常显示,IDAT 的长度最长是 231 - 1字节, 转化为 16 进制是
-1 字节的原因是,索引为 0 开始.
计算 IDAT 长度
还是上面的数据,拿过来计算,
我们只需要将数据的最后地址 - 最开始的地址即可。
很明显第 10 行的 A2 BF 1E 94
是第一个 IDAT 块的结束。而其中 94
的地址,通过左侧和最上方的地址能够看出来是 0xFFFF
而第一行数据的开始是 35 7A C6 5C
,其中 35
的地址是 0x0C
0xFFFF
- 0x0C
= 0xFFF3
10 进制是 65523
,因为索引从 0 开始,所以最后长度还要 +1
,得到第一个 IDAT 的长度为 65524
,16 进制是 0xFFF4
,因为长度为 4 个字节一组,所以不够的补 0, 最终得到 00 00 FF F4
0 1 2 3 4 5 6 7 8 9 A B C D E F
1:0000h: 00 00 00 00 00 00 FF F4 49 44 41 54 35 7A C6 5C ......ÿôIDAT5zÆ\
1:0010h: 49 A3 06 56 A7 2D 44 F9 C6 F9 4F 95 A1 60 24 A7 I£.V§-DùÆùO•¡`$§
1:0020h: 84 4D E0 EB 76 A0 49 A7 06 6A 67 05 5E CF 83 FE „Màëv I§.jg.^σþ
1:0030h: 5E F6 29 1D 4B FA 99 22 20 C6 8E A3 72 86 FD EA ^ö).Kú™" ÆŽ£r†ýê
1:0040h: F0 36 F8 06 F5 3C 5F C9 64 12 C4 CF F3 34 E5 57 ð6ø.õ<_Éd.ÄÏó4åW
1:0050h: 41 EE 4A 65 83 07 D2 8D BC 89 25 AD 68 DC AE F0 AîJeƒ.Ò
........................................................ ................
1:FFE0h: EE C4 85 87 38 76 75 21 16 A9 86 80 46 CE 3A C3 îÄ…‡8vu!.©†€FÎ:Ã
1:FFF0h: 25 22 5E CA BF 87 46 C7 93 18 D8 4C A2 BF 1E 94 %"^Ê¿‡FÇ“.ØL¢¿.”
2:0000h: 87 6E FA 22 00 00 FF F4 49 44 41 54 57 62 4F B6 ‡nú"..ÿôIDATWbO¶
2:0010h: D0 5B 8B 8C 97 FE 63 3E 73 FE 63 CC F1 FD 1A 20 Ð[‹Œ—þc>sþcÌñý.
2:0020h: 1B B3 7A 3B 02 E4 60 62 C8 F1 BB 72 DB C7 31 79 .³z;.ä`bÈñ»rÛÇ1y
最后一个 IDAT 块
通过 16 进制编辑工具的搜索功能,能够快速定位到最后一个 IDAT 块的所在位置
先找到倒数第二个 IDAT 块的结尾,也就是最后一个 IDAT 块的开始,这里根据之前讲的格式,可以得到
D1 B6 DB 87
是倒数第二个 IDAT 的 CRC 值, 00 00 9E D0
是 最后一个 IDAT 的长度(不确定是否正确,需要计算)
49 44 41 54
表示最后一个 IDAT 标识,59 E5 27 BE
是数据的开始。
长度是不包含 CRC 和标识的,肯定也不包含上一个 IDAT 的内容,所以最后得到的值,我们需要** 减去 12 **。
IDAT 的结尾标识是 IEND
IEND块的结构如下:
长度:00 00 00 00(4字节),表示数据部分的长度为0。
类型:49 45 4E 44(4字节),表示这是一个IEND块。
数据:空(0字节)。
CRC:AE 42 60 82(4字节),IEND块的标准CRC值。
也就是说这里最后一个 IDAT 块的 CRC 值为 CE 10 F1 2B
那么它的长度就应该是 0x9EE4
- 0x0C
+ 0x01
= 0x9ED9
最后得到结果
‘
IDAT 块 CRC 检查
这里需要注意的一点是,当我们确定长度之后,最好验证下 CRC 校验的值,这里可以通过 010Editor 的脚本判断
也可以通过工具 pngcheck 确定
最后修复之后,图片完全显示正常,而且通过 pngcheck 检查,无问题