Encoding 试图理解PNG文件中的zlib/deflate 我目前正在为学习目的编写一个小的PNG图像I/O库。我的问题如下:

Encoding 试图理解PNG文件中的zlib/deflate 我目前正在为学习目的编写一个小的PNG图像I/O库。我的问题如下:,encoding,png,implementation,deflate,Encoding,Png,Implementation,Deflate,我创建了一个尺寸只有2×2像素的小PNG,并在十六进制编辑器中打开它来研究它的内容。这是我使用GIMP创建的图像,并以“9”压缩存储 (请注意,这是原始2×2像素图像的放大图像;) 所以我猜在未压缩的情况下,这在内存中看起来是这样的: 00 00 00 FF 00 00 00 00 FF 00 FF 00 当存储时没有alpha通道 (我在这里只是为了清楚起见,我知道压缩,没想到会在文件中看到这个字节模式) 我提取了IDAT块,去掉了块ID(“IDAT”)和尾部CRC值,得到了这个字节序列:

我创建了一个尺寸只有2×2像素的小PNG,并在十六进制编辑器中打开它来研究它的内容。这是我使用GIMP创建的图像,并以“9”压缩存储

(请注意,这是原始2×2像素图像的放大图像;)

所以我猜在未压缩的情况下,这在内存中看起来是这样的:

00 00 00 FF 00 00 00 00 FF 00 FF 00
当存储时没有alpha通道

(我在这里只是为了清楚起见,我知道压缩,没想到会在文件中看到这个字节模式)

我提取了IDAT块,去掉了块ID(“IDAT”)和尾部CRC值,得到了这个字节序列:

08 D7 05 C1 01 01 00 00 00 80 10 FF 4F 17 10 48 06 0F FE 02 FE
现在,前两个字节
08 D7
包含编码块的信息。 FE 02 FE的最后四个字节必须是ADLER32校验和

这最终留给我以下字节:

05 C1 01 01 00 00 00 80 10 FF 4F 17 10 48 06
以二进制表示形式写入这些字节:

0000 0101  1100 0001  0000 0001  0000 0001
0000 0000  0000 0000  0000 0000  1000 0000
0001 0000  1111 1111  0100 1111  0001 0111
0001 0000  0100 1000  0000 0110
为了更好地理解DEFLATE,我尝试用手“解包”这个序列,至少在我完全理解它并编写一个小工具之前。但我很快就被卡住了

RFC1951()声明每个编码块都以一个三位头开始。一个位指示这是否是最后一个块,另外两个块指示压缩方法。因为我假设编码器在这里只使用了一个块(意味着第一个块自动是最后一个),并且使用了非静态哈夫曼树,所以我正在寻找位序列“101”,但我找不到它(我也找不到其他可能的头“100”或“110”)

RFC还指出,必须有两个双字节值LEN和NLEN来存储块的长度,其中NLEN是LEN的一个补码,但我同样无法找到满足此条件的四个这样的字节。我甚至不会开始寻找任何能阻止两棵哈夫曼树的东西

我阅读了1951年和1950年的RFCs(以及维基百科关于zlib、DEFLATE、LZ77和Huffman编码的文章,以及网上几篇小而无用的文章和一些关于堆栈溢出的答案,但没有一篇能帮助我解决我的理解不足


如果您能提供任何帮助或提示,我将不胜感激。

我想您可能不知道字节中的位是如何打包的(例如,请参阅的第3.1.1节)

因此,如果第一个字节为05=0000 0101,则第一位为1

(顺便说一句,看这么多细节肯定很有启发性,但如果你的目的是理解PNG,我想知道你是否走得太远了。)


此外,当您找到未压缩的IDAT流时,请记住,像素是用每行五个中的一个进行编码的,并且在每行的开头有一个额外的字节来表示过滤器类型。因此,您不会真正找到原始的12字节
00 00 00 00 00 00 FF 00
,而是12+2=14字节相反。

如果这有帮助,下面是IDAT块内容的分解:

! infgen 2.2 output
!
zlib
!
last
dynamic
count 257 2 18
code 1 1
code 2 2
code 18 2
lens 1
zeros 138
zeros 116
lens 2 2 1 1
! litlen 0 1
! litlen 255 2
! litlen 256 2
! dist 0 1
! dist 1 1
literal 0 0 0 0 255 0 0 0 0 0 255 0 255 0
end
!
adler

您可以获得
infgen
源代码。

谢谢您的回答。您是对的,我没有想到字节内的位顺序。我知道过滤器,只包含了这个小示例,以显示在解压缩和删除过滤器后我最终的期望;-)。。也可以省略这个片段。现在我们有了标题。下面的零是第一棵哈夫曼树的表示,对吗?(顺便说一句,是的,这是一个非常低的级别,我当然不会在另一个图像格式上再次这样做,但我想至少了解一次这个级别上发生了什么;-)。如果你想要详细的解释,我建议我不确定,我不是deflate方面的专家,也许你应该问一个新问题(记住:这不是聊天论坛)。在这里,你可以从真正的专家那里得到答案,就像阿德勒先生自己一样:-)那是阿德勒博士对你说的。底部是亲笔签名,还是确认最后两个单词编码正确?这不是确认,只是声明阿德勒-32应该在四个字节的位置
infgen
不计算未压缩数据的检查值以查看其是否正确。
! infgen 2.2 output
!
zlib
!
last
dynamic
count 257 2 18
code 1 1
code 2 2
code 18 2
lens 1
zeros 138
zeros 116
lens 2 2 1 1
! litlen 0 1
! litlen 255 2
! litlen 256 2
! dist 0 1
! dist 1 1
literal 0 0 0 0 255 0 0 0 0 0 255 0 255 0
end
!
adler