如何解码没有压缩的PNG文件中的IDAT块

10

我用 Photoshop 制作了一些 4x4 像素、16 位灰度的图像,并将它们保存为无压缩、无隔行,PNG 文件。我正在尝试编写一个程序来从这些文件中提取图像数据,但我对 IDAT 块有些困惑。这是为了自我学习而做的,所以我不使用库。

下面是其中一张图像的 IDAT 块的十六进制代码,其中每个像素都是白色。

hex code

我已经用颜色标记了我目前理解的部分:

红色 = 忽略此部分,因为它属于 IEND 块,与 IDAT 无关。
黄色 = 块信息。前 4 个黄色字节是数据长度。接下来的 4 个黄色字节是块标识符。图像末尾的最后 4 个黄色字节是循环冗余校验码。
蓝色 = zlib 压缩格式信息。第一个蓝色字节是压缩方法和压缩信息。第二个蓝色字节是标志信息。图像底部附近的最后 4 个蓝色字节是 ADLER-32 校验和。我假设在这种情况下没有 DICTID。
灰色 = Deflate 压缩算法的信息。第一个灰色字节中,第一位表示最后一个块标记,第二和第三位表示编码方法。忽略掉第一个灰色字节的其余部分。由于这种方法是非压缩方法,第二个和第三个灰色字节是块中数据字节的长度,第四和第五个灰色字节是第二个和第三个灰色字节的取反值。
无框 = 使用 LZ77 算法压缩的图像数据(由于是非压缩方法,没有哈夫曼编码),算法使用 8 位来表示潜在重复长度,15 位用于搜索距离。

我可能对某些事情的理解有误,或者没有正确理解如何使用LZ77算法解码没有边框的图像中的字节。如果有人能够纠正我或者展示我不理解的内容,我将不胜感激。谢谢。


添加了一些标签...看起来你已经正确解码了IDAT黄色起始/结束块(大小+12字节),至少在我测试的png上是一样的。 - Spektre
1个回答

10

顶部行: 01 ff fd 00 00 00 00 00 00 ("sub" 过滤器,第一个像素是fffd, 接下来的像素都与其左边的像素相同(差异= 0)

其余3行: 02 00 00 00 00 00 00 00 00 ("up"过滤器,所有像上面一行的像素相同)

最后一个块: 01 00 00 ff ff (最后一个字节标记01,长度0000,~长度ffff)

因此,图像为4x4,所有像素都是16位fffd,几乎是白色的。

如果您对所有字节使用了filter-type 0,可能更容易理解;每行的像素将都是00 ff fd ff fd ff fd ff fd

顺便说一句,IEND块应该有4个字节的CRC; 或者您的编码器出了问题,或者您已从十六进制转储图片中删除了它们。


我已经编辑了IEND块之后的所有块,包括IDAT块之前的所有块。我的理由是重点在于IDAT块。我还提供了证明IEND块是下一个块,以便人们不会质疑是否还有另一个IDAT块跟随或者那是否真的是IDAT块的结尾。感谢您的回复。 - Kevin Baker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接