我目前正在开发基于png文件格式的专有文件格式。到目前为止,我已经完成了,除了它不起作用:-p我实现的deflate解压缩器就像魅力一样,但是png解码器并不想要很好地执行,所以我看了一下原来的png文件。
标准说在IDAT标题之后,压缩数据立即跟随。因此,当数据是一个deflate流时,IDAT之后的第一个字符是0x78 == 01111000,这意味着,模式一个块(未压缩)而不是最后一个。
虽然很奇怪 - 我很难想象PNG编码器不会使用动态霍夫曼编码来压缩滤波的原始图像数据。 deflate标准表示在模式1中跳过当前字节的其余部分。
因此接下来的四个字节表示未压缩块的大小及其一个补码。 但是0x59FD不是0xECDA的一个补码。即使我搞砸了字节顺序:0xFD59也不是0xDAEC的一个补码。
嗯,淘汰赛字节紧随其后。 0x97被认为是未压缩但仍过滤的原始png图像数据的第一个字节,因此必须是filtertype。但是0x97 == 10010111不是有效的过滤器类型。事件,如果我搞砸了位打包顺序11101001 == 0xe9仍然没有有效的过滤器类型。
我不再那么关注RFC 1951,因为到目前为止我可以使用我的deflate解压缩程序实现所有类型的文件,所以我怀疑在我这方面有一些误解,认为PNG标准。
我一遍又一遍地阅读RFC 2083,但是我在这里看到的数据与RFC不匹配,对我来说没有意义,必须有一个缺失的部分!
当我查看以下字节时,实际上我无法在任何地方看到有效的过滤器类型字节,这让我认为过滤后的png数据流毕竟是压缩的。
如果将0x78(IDAT之后的第一个字节)从MSB读取到LSB,但RFC 1951另有说明,那将是有意义的。另一个想法(我更可能)是IDAT字符串和压缩的deflate流的开始之间有一些数据,但RFC 2083则另有说法。布局清晰
4Bytes大小 4Bytes ChunkName(IDAT) [大小]字节(压缩放气流) 4Bytes CRC Checksum
因此IDAT之后的第一个字节必须是压缩的deflate流的第一个字节 - 表示模式1未压缩的数据块。这意味着0x97必须是未压缩但已过滤的png图像数据的第一个字节 - 这意味着0x97是第一行的过滤类型 - 这是无效的......
我只是没有得到它,我是愚蠢还是什么?
要点: 可能性1: 在IDAT和压缩的deflate流的有效启动之间还有一些其他数据,如果这些数据呈现为真,则在RFC2083和我阅读的有关图像压缩的任何书籍中均未提及。
可能性2: 数字0x78被解释为MSB - > LSB表示模式3块(动态霍夫曼编码),但这与RF1951相矛盾,RF1951对位填充非常清楚:(LSB - > MSB)
我已经知道,缺少的部分必须是非常愚蠢的东西,如果Stack Overflow中只有一个删除按钮,我会觉得急需出售我的灵魂:-p
答案 0 :(得分:6)
两项更正可能会帮助您顺利开始:
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,表示最大压缩。
另见Trying to understand zlib/deflate in PNG files,尤其是博士。阿德勒的回答。
LEN
和NLEN
仅针对未压缩的块设置;这就是为什么你找不到它们的原因。 (另外,部分原因是因为你正在查看错误的字节。)流中的下一个字节是EC
;按位,这是1110 1100
,但记得从低到高读取位。所以下一位读取是0
,意味着不 FINAL,接下来的2位读取是10
(按此顺序!),表示常规动态霍夫曼编码数据块