【发布时间】:2020-10-18 02:55:57
【问题描述】:
我正在尝试在没有任何外部库的情况下编写自己的 png 阅读器。我需要使用 Zlib 来解压 png 的 IDAT 块。我已经设法在 python 中使用zlib.decompress() 做到这一点,我正试图在 C 中复制它。我正在阅读 zlib 的文档并找到 uncompress(),但是它需要一个我不知道的目标长度。
我可以将目标设置得比 png 可能的大得多,但这似乎是一种逃避,如果我有一张非常大的图片,这会破坏我的程序。但是,我发现了一个可以多次使用的函数inflate()。如果我能做到这一点,如果每次通话都需要,我可以realloc() 内存。但是我不太了解它的文档,也没有找到很多这类事情的例子。谁能提供一些代码或帮助我指出正确的方向?
【问题讨论】:
-
如您所料,
zlib函数是面向 stream 的。因此,您使用循环和realloc来扩展解压缩数据缓冲区的长度,一次一个块(例如)在每次 decompress [deflate] 调用之前,您调用realloc并增加长度。您在z_stream结构中设置大小,当缓冲区已满[或没有更多输入数据] 时,函数将停止。您循环直到所有数据都被解压缩。zlib.h文件有相当完整的文档。例如,将源下载到使用zlib(例如gzip)的程序中,zlib源有示例 -
请注意,使用
realloc将需要每次复制整个现有缓冲区,因此不应过于频繁地调用它(我会说不超过一次 4096 字节)。如果你想要更好的性能,你应该增加这个数量,或者更好:根本不使用realloc,而是处理几个缓冲区。不过,我暂时不会担心这个。一旦工作正常,您可以随时进行优化。 -
@AndreasWenzel 有一个恒定的
realloc()频率是非常低效的,例如“每 4096 字节一次”。然后每个字节将被复制多次。相反,如果您将每个realloc()的内存大小 加倍,那么您可以证明这些字节平均只被复制一次。 -
@MarkAdler:是的,我同意自适应缓冲区大小比恒定缓冲区更好,特别是当文件大小可能很大时。我也同意您提出的将每次分配的缓冲区大小加倍的算法可能是最好的,因为该算法平均不会多次复制内存。
-
@MarkAdler:据我所知,最有效的解决方案是根本不调用
realloc,而是使用指向固定长度内存缓冲区的指针的数组或链表.这样,可以根据需要分配新的缓冲区,并且不必复制内存。但是,如果程序员的任务需要在之后合并这些缓冲区,以便使用它们,那么所有内存缓冲区都必须复制一次。在这种情况下,我的解决方案与realloc解决方案相比没有优势。
标签: c compression zlib