【问题标题】:PNG: What is the benefit of using multiple IDAT-Chunks?PNG:使用多个 IDAT-Chunk 有什么好处?
【发布时间】:2015-06-13 08:18:28
【问题描述】:

我想知道在 PNG 图像中使用多个 IDAT-Chunk 有什么好处。

PNG 文档说

可能有多个 IDAT 块;如果是这样,它们将连续出现,没有其他中间块。压缩后的数据流是所有 IDAT 块的数据字段内容的串联。

我无法想象这是因为块内数据块的最大大小(2^32 字节)。

【问题讨论】:

  • 我想最合乎逻辑的原因是“这样压缩器就不需要一次加载和扩展整个图像。”

标签: png


【解决方案1】:

回想一下,所有 PNG 块(包括 IDAT 块)都有一个带有块长度的前缀。将所有压缩流放在一个巨大的 IDAT 块中会导致以下两个不便:

  • 在编码器端:压缩器在完成压缩之前不知道总压缩数据大小。然后,在写入块前缀之前,它需要在内存中缓冲完整的压缩数据。

  • 在解码端:这取决于如何实现块解码;如果它在内存中缓冲每个块(分配由块长度前缀给出的空间),并且在填充它并检查 CRC 之后,它将内容传递给解压缩器,那么,再一次,拥有一个巨大的 IDAT 块将是一个内存猪。

考虑到这一点,我认为应该推荐使用相当小的 IDAT 块(例如 16KB 或 64KB)。开销(每个块 12 个字节,如果 len=64KB 则小于 1/5000)可以忽略不计。

【讨论】:

  • 我不确定这对解码器有什么好处。如果文件作为一个太大而无法加载的单个块出现,该怎么办?举手宣布文件“不受支持”?编码器如何知道每个可能尝试读取文件的解码器的限制是多少?我认为这只是对编码器有好处,没有理由人为地限制大小来推测性地解决您无法预料的问题。
【解决方案2】:

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

假设您不关心 CRC 错误的早期检测(如果它们确实发生,它们仍然会被检测到,但稍后会检测到),那么小的 IDAT 块不会为读者带来任何好处。实际上,小的 IDAT 块意味着对 zlib 的更多单独调用以及 zlib 中更多的前导/后导成本,因此它通常在处理时间和磁盘空间方面效率较低。

对于写入者来说,写入有限长度的 IDAT 块很方便,因为您可以在写入之前确定块的长度。如果要写入单个 IDAT 块,则必须在开始写入任何内容之前完成压缩(需要大量临时存储),或者一旦知道它有多长,就必须在输出中查找以更新 IDAT 块长度.

如果您同时压缩图像并流式传输结果,这可能是不可能的。如果您将图像写入磁盘,那么这可能没什么大不了的。

简而言之,小块用于动态压缩、流式输出用例。在大多数其他情况下,最好只使用一个块。

【讨论】:

    猜你喜欢
    • 2017-09-19
    • 1970-01-01
    • 2014-05-05
    • 2011-11-09
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-28
    相关资源
    最近更新 更多