IDG PNG文件格式块

我目前正在开发基于png文件格式的专有文件格式。 到目前为止我完成了,除了它不起作用:-p我实现的deflate解压缩器就像魅力一样,但是png解码器不想很好地执行所以我看了一下原来的png文件。

标准说,在IDAT标题之后,压缩数据立即跟随。 因此,当数据是deflate流时,IDAT之后的第一个字符是0x78 == 01111000,这意味着,模式一个块(未压缩)而不是最后一个。

奇怪的是 – 我很难想象PNG编码器不使用动态霍夫曼编码来压缩滤波后的原始图像数据。 deflate标准表示在模式1中跳过当前字节的其余部分。

因此接下来的四个字节表示未压缩块的大小及其一个补码。 但是0x59FD不是0xECDA的一个补码。 即使我搞砸了字节顺序:0xFD59也不是0xDAEC的一个补码。

好吧,淘汰赛字节紧随其后。 0x97被认为是未压缩但仍过滤的原始png图像数据的第一个字节,因此必须是filtertype。 但是0x97 == 10010111不是有效的filter类型。 事件,如果我搞砸了位打包顺序11101001 == 0xe9仍然没有有效的filter类型。

我不再那么关注RFC 1951,因为到目前为止我能够使用我的deflate解压缩程序实现所有类型的文件,所以我怀疑在我的部分中有一些误解,我认为PNG标准。

我一遍又一遍地阅读RFC 2083但是我在这里看到的数据与RFC不匹配,对我来说没有意义,必须有一个缺失的部分!

当我查看以下字节时,实际上我无法在任何地方看到有效的filter类型字节,这使得我认为过滤后的png数据流毕竟是压缩的。

如果将0x78(IDAT之后的第一个字节)从MSB读取到LSB,但RFC 1951则另有说明,这是有意义的。 另一个想法(对我来说更可能)是IDAT字符串和压缩的deflate流的开始之间存在一些数据,但RFC 2083则另有说明。 布局很清楚

4Bytes大小4Bytes ChunkName(IDAT)[大小]字节(压缩放气流)4Bytes CRC校验和

因此,IDAT之后的第一个字节必须是压缩的deflate流的第一个字节 – 这表示模式1未压缩的数据块。 这意味着0x97必须是未压缩但已过滤的png图像数据的第一个字节 – 这意味着0x97是第一行的过滤类型 – 这是无效的…

我只是不明白,我是愚蠢还是什么?

总结:可能性1:在IDAT和压缩的deflate流的有效启动之间还有一些其他的数据,如果这些数据呈现为真,则在RFC2083和我读过的任何关于图像压缩的书中都没有提及。

可能性2:数字0x78被解释为MSB – > LSB,这表示模式3块(动态霍夫曼编码),但这与RF1951相矛盾,RF1951对比特打包非常清楚:(LSB – > MSB)

我已经知道了,丢失的部分必须是非常愚蠢的东西,如果Stack Overflow中只有一个删除按钮,我会觉得急需出售我的灵魂:-p

在此处输入图像描述

两个更正可以帮助您帮助您:

  1. 标志中的zlib字节数为2,而不是1 – 请参阅RFC 1950 。 第一个是CMF ,即下一个FLG

在您的数据中:

 78 DA ---CMF--- ---FLG--- 0111.1000 1101.0101 CINF -CM- +-|| | |+- FCHECK | +-- FDICT +---- FLEVEL 

CINF为7,表示标准的32Kb压缩窗口。
CM为8,表明压缩算法确实是DEFLATE。
FCHECK只是一个校验和; 我没有检查它是否正确(但我敢打赌)。
FDICT很清楚,这意味着没有存储预设字典。
FLEVEL为3,表示最大压缩。

另请参阅尝试理解PNG文件中的zlib / deflate ,尤其是 博士。 阿德勒的回答。

  1. LENNLEN仅针对未压缩块设置; 这就是你没找到它们的原因。 (另外,部分原因是因为你正在查看错误的字节。)

流中的下一个字节EC ; 按位,这是1110 1100 记得从低到高读取位。 因此,下一位读取为0 ,意味着不是 FINAL,接下来的2位读取是10 (按此顺序!),表示常规动态霍夫曼编码数据块。