如何在不压缩的情况下解码 PNG 文件的 IDAT 块
How to decode the IDAT chunk of a PNG file with no compression
我在 Photoshop 中创建了一些 4x4 像素、16 位灰度图像,并将它们保存为 non-compressed、无隔行扫描、PNG 文件。我正在尝试编写一个程序来从这些文件中提取图像数据,但我对 IDAT 块有点困惑。这是为了 self-education 目的,所以我没有使用库。
这是其中一个图像的 IDAT 块的十六进制代码,其中每个像素都是白色的。

我已经用颜色标记了我现在理解的内容。
红色 = 忽略,因为它是 IEND 块的一部分,与 IDAT 无关。
黄色 = 区块信息。前 4 个黄色字节是数据长度。第二个 4 黄色字节是块标识符。图像末尾的最后 4 个黄色字节是循环冗余校验。
Blue = zlib 压缩格式信息。其中第一个蓝色字节是压缩方式和压缩信息。第二个蓝色字节是Flag信息。图像底部附近的最后四个蓝色字节是 ADLER-32 校验和。我假设在这种情况下没有 DICTID。
灰色 = Deflate 压缩算法的信息。在第一个灰色字节中,第一位是最后一个块标记,第二位和第三位是编码方法。第一个灰色字节的其余部分将被忽略。由于这种方法是non-compressed方法,所以第二个和第三个灰色字节是块中数据字节的长度,第四个和第五个灰色字节是第二个和第三个灰色字节的补码。
No Box = 使用 LZ77 算法压缩的图像数据(由于未压缩方法,没有 Huffman 代码),该算法使用 8 位潜在重复长度和 15 位搜索反向距离。
要么我理解有误,要么我不理解如何使用 LZ77 算法正确解码无框图像中的字节。如果有人可以纠正我或展示我不理解的地方,我将不胜感激。谢谢。
顶行: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,len 0000,~len ffff)
所以图像是4x4,所有像素都是16位fffd,几乎是白色的。
如果您对所有字节都使用了过滤器类型 0,那么理解起来可能会更清楚;每行都是 00 ff fd ff fd ff fd ff fd
顺便说一下,IEND 块应该有 4 个字节(CRC);要么是你的编码器有问题,要么是你从十六进制转储的图片中编辑了它们。
我在 Photoshop 中创建了一些 4x4 像素、16 位灰度图像,并将它们保存为 non-compressed、无隔行扫描、PNG 文件。我正在尝试编写一个程序来从这些文件中提取图像数据,但我对 IDAT 块有点困惑。这是为了 self-education 目的,所以我没有使用库。
这是其中一个图像的 IDAT 块的十六进制代码,其中每个像素都是白色的。
我已经用颜色标记了我现在理解的内容。
红色 = 忽略,因为它是 IEND 块的一部分,与 IDAT 无关。
黄色 = 区块信息。前 4 个黄色字节是数据长度。第二个 4 黄色字节是块标识符。图像末尾的最后 4 个黄色字节是循环冗余校验。
Blue = zlib 压缩格式信息。其中第一个蓝色字节是压缩方式和压缩信息。第二个蓝色字节是Flag信息。图像底部附近的最后四个蓝色字节是 ADLER-32 校验和。我假设在这种情况下没有 DICTID。
灰色 = Deflate 压缩算法的信息。在第一个灰色字节中,第一位是最后一个块标记,第二位和第三位是编码方法。第一个灰色字节的其余部分将被忽略。由于这种方法是non-compressed方法,所以第二个和第三个灰色字节是块中数据字节的长度,第四个和第五个灰色字节是第二个和第三个灰色字节的补码。
No Box = 使用 LZ77 算法压缩的图像数据(由于未压缩方法,没有 Huffman 代码),该算法使用 8 位潜在重复长度和 15 位搜索反向距离。
要么我理解有误,要么我不理解如何使用 LZ77 算法正确解码无框图像中的字节。如果有人可以纠正我或展示我不理解的地方,我将不胜感激。谢谢。
顶行: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,len 0000,~len ffff)
所以图像是4x4,所有像素都是16位fffd,几乎是白色的。
如果您对所有字节都使用了过滤器类型 0,那么理解起来可能会更清楚;每行都是 00 ff fd ff fd ff fd ff fd
顺便说一下,IEND 块应该有 4 个字节(CRC);要么是你的编码器有问题,要么是你从十六进制转储的图片中编辑了它们。