C PNG文件格式的IDAT块

C PNG文件格式的IDAT块,c,png,deflate,C,Png,Deflate,我目前正在开发一种基于png文件格式的专有文件格式。到目前为止,我已经完成了,除了它不工作:-p我实现的deflate解压器工作得很好,但是png解码器不想表现得很好,所以我查看了原始png文件 该标准规定,在IDAT头之后,压缩数据立即跟随。因此,由于数据是一个deflate流,IDAT之后的第一个字符是0x78==01111000,这意味着是一个模式一块(未压缩),而不是最后一个 奇怪的是,我很难想象PNG编码器不使用动态哈夫曼编码来压缩过滤后的原始图像数据。deflate标准表示在模式1中

我目前正在开发一种基于png文件格式的专有文件格式。到目前为止,我已经完成了,除了它不工作:-p我实现的deflate解压器工作得很好,但是png解码器不想表现得很好,所以我查看了原始png文件

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

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

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

好吧,接下来就是淘汰字节。0x97被认为是未压缩但仍经过过滤的原始png图像数据的第一个字节,因此必须是filtertype。但是0x97==10010111不是有效的筛选器类型。如果我拧紧了位打包顺序11101001==0xe9,则事件仍然没有有效的过滤器类型

我不再关注RFC1951,因为到目前为止,我能够使用我的deflate解压器实现对所有类型的文件进行膨胀,所以我怀疑我对PNG标准有一些误解

我读了一遍又一遍的RFC2083,但是我在这里看到的数据与RFC不匹配,这对我来说没有意义,一定是缺少了一块

当我看下面的字节时,我实际上在任何地方都看不到有效的过滤器类型字节,这使我认为过滤后的png数据流毕竟是压缩的

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

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

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

我就是不明白,我是愚蠢还是什么

总结: 可能性1: 在IDAT和压缩的deflate流的有效开始之间还有一些其他数据,如果呈现为真,在RFC2083或我读过的任何关于图像压缩的书中都没有意义

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

我已经知道,丢失的部分一定是非常愚蠢的东西,如果堆栈溢出中只有一个删除按钮,我会觉得urgend需要出卖我的灵魂:-p


两个可能帮助您上路的更正:

  • 标志中的
    zlib
    字节数是2,而不是1——请参阅。第一个是
    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,表示最大压缩

    另请参见,特别是阿德勒博士的回答

  • LEN
    NLEN
    仅为未压缩块设置;这就是为什么你没有找到他们。(另外,部分原因是您查看的字节错误。)

  • 流中的下一个字节是
    EC
    ;按位,这是
    1110 1100
    ,但请记住从低到高读取位。因此,下一个读取的位是
    0
    ,表示不是最终的,下两个读取的位是
    10
    (按顺序!),表示一个常规的动态哈夫曼编码数据块。

    我没有意识到deflate流被包装在zlib容器中。我认为这是一条纯粹的泄气流。所以我现在跳过了两个字节,瞧,png导入器工作了!:-)谢谢!