PNG:使用多个IDAT块的好处是什么?

9
我想知道在PNG图像中使用多个IDAT块的好处是什么。
PNG文档说明如下:
“可能有多个IDAT块;如果是这样,它们应该连续出现,没有其他插入的块。压缩数据流是所有IDAT块数据字段内容的串联”。
我不认为这是由于块内数据块的最大大小(2^32字节)。

我想最合理的原因是“这样压缩器就不需要一次性加载和展开整个图像。” - Jongware
2个回答

7
请注意,所有PNG块(包括IDAT块)都有一个带有块长度的前缀。把所有压缩流放在一个巨大的IDAT块中会引起以下两个不便:
- 对于编码器: 在压缩完成之前,压缩器不知道总压缩数据大小。 然后,它需要在写入块前将完整的压缩数据缓冲到内存中。 - 对于解码器: 这取决于如何实现块解码; 如果它在内存中缓冲每个块(分配由块长度前缀给出的空间),然后,在填充和检查CRC后将内容传递给未压缩器,则再次使用单个巨大的IDAT块将占用大量内存。
考虑到这一点,我认为应该推荐使用相对较小的IDAT块(例如16KB或64KB)。开销(每个块12字节,如果len=64KB小于1/5000)可以忽略不计。

我不确定它是否对解码器有任何好处。如果文件作为一个太大而无法加载的单个块出现,它应该做什么?放弃并声明文件“不受支持”吗?编码器如何知道每个可能尝试读取文件的解码器的限制是什么?我认为这只对编码器有益,没有理由人为地限制大小以推测性地解决您无法预料的问题。 - sh1

3

看起来,在读取PNG文件时,即使文件中的IDAT块大小更大,libpng 限制其缓冲的数据块为8192字节。这对于libpng读取和解压IDAT块所需的分配大小设置了上限。然而,在完全读取整个IDAT块之前,仍然无法检测到校验和错误,而对于大型IDAT块,这可能需要更长时间。

假设您不关心CRC错误的早期检测(如果发生错误,它们仍然会被检测到,但稍后),那么小的IDAT块对读者没有任何好处。实际上,小的IDAT块意味着更多单独的zlib调用以及zlib中的更多前导/后导费用,因此在处理时间和磁盘空间方面通常效率较低。
对于编写者来说,编写有限长度的IDAT块很方便,因为您可以在编写之前确定块的长度。如果您想写一个单独的IDAT块,那么您必须在开始写入任何内容之前完成压缩(需要大量临时存储),或者在了解其长度后在输出中寻找以更新IDAT块长度。
如果您正在同时压缩图像并流式传输结果,则可能无法完成此操作。如果您将图像写入磁盘,则这可能并不是一个大问题。
简而言之,小块适用于即时压缩、流式输出的情况。在大多数其他情况下,使用单个块更好。

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