1

编辑:这是指 IDAT 中的实际数据流块(以及唯一的 IDAT 块)。我成功地浏览了从 IHDR 到 IEND 的相关关键块——问题在于实际块之间的导航。

所以,出于好奇,我正在做一个小宠物项目,编写一个 PNG 加载器,并首先尝试使用未压缩的文件来真正了解它的要点。对于压缩类型 00(无压缩),2^16 - 1如果最终块有问题,则其大小应为 , 65535 或更小。

因此,我正确加载了第一个块并尝试添加最后一个块长度的偏移量(这是可变的,如果最后一个则为 65535 或更小)。所以,我希望第 65535 个偏移量应该落在下一个块的第一个字节上,因为最后一个字节是从 0 读取到非包含 65535 或第 65534 个字节是第一个块的最后一个字节。但出于某种奇怪的原因,我未压缩的 PNG 文件(用 Photoshop 输出)读取了应该是第二个块传递的虚假数据(它使用动态霍夫曼代码将其标记为压缩和最终,因此 LZ77 压缩算法的变体,在不同的图像,它在 1MB 文件的 100k 字节标记处输出 77 用于压缩类型等)。

所以,我一定是登陆了错误的字节,也许?这应该是微不足道的,但我看不出我在哪里失败,这是相关的一点:

unsigned int accumulatedOffset = 0;
CBlock cblock; // initializes length to 0

do {

    accumulatedOffset += cblock.length; // Adds 65535 on second pass

    // Extract block header
    unsigned char bheader = IDATChunk[Description::BlockHeaderOffset + accumulatedOffset];

    // The second pass reads from the wrong byte, it seems.

} while(...)

我在第二次通过之间错过了什么吗?

4

1 回答 1

1

Ah, thank you for the edit. So you are talking about deflate blocks.

If you have all stored deflate blocks, the format will be:

00 rs pq ~rs ~pq [ pqrs bytes ] ... same thing repeated ... 01 rs pq ~rs ~pq [ pqrs bytes ]

where ~ means the inverse, or one's complement.

Note that this will follow a zlib header and be followed by a zlib trailer. See RFC 1950.

于 2013-05-25T14:50:54.920 回答