IDG PNG文件格式块

时间:2014-10-01 21:16:14

标签: c png deflate

我目前正在开发基于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

enter image description here

1 个答案:

答案 0 :(得分:6)

两项更正可能会帮助您顺利开始:

  1. 标志中zlib个字节的数量是2,而不是1 - 请参阅RFC 1950。第一个是CMF,下一个是FLG
  2. 在您的数据中:

    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,尤其是博士。阿德勒的回答。

    1. LENNLEN仅针对未压缩的块设置;这就是为什么你找不到它们的原因。 (另外,部分原因是因为你正在查看错误的字节。)
    2. 流中的下一个字节EC;按位,这是1110 1100 ,但记得从低到高读取位。所以下一位读取是0,意味着 FINAL,接下来的2位读取是10(按此顺序!),表示常规动态霍夫曼编码数据块