gpt4 book ai didi

c++ - 使用 libpng 将位图缓冲区快速编码为 png

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:24:43 25 4
gpt4 key购买 nike

我的目标是使用 C/C++ 将 32 位位图 (BGRA) 缓冲区实时转换为 png 图像。为了实现它,我使用了 libpng 库来转换位图缓冲区,然后写入一个 png 文件。然而,在单线程目标 arm 板(四核处理器)上执行似乎需要很长时间(~5 秒)。在分析时,我发现 libpng 压缩过程(放气算法)占用了 90% 以上的时间。所以我试图通过以某种方式使用并行化来减少它。这里的最终目标是至少在 0.5 秒内完成。

既然 png 可以有多个 IDAT block ,我想到了用多个 IDAT 并行编写 png。采用以下方法编写具有多个 IDAT 的自定义 png 文件

   1. Write PNG IHDR chunk
2. Write IDAT chunks in parallel
i. Split input buffer in 4 parts.
ii. compress each part in parallel using zlib "compress" function.
iii. compute CRC of chunk { "IDAT"+zlib compressed data }.
iv. create IDAT chunk i.e. { "IDAT"+zlib compressed data+ CRC}.
v. Write length of IDAT chunk created.
vi. Write complete chunk in sequence.
3. write IEND chunk

现在的问题是用这种方法创建的 png 文件无效或已损坏。有人可以指出吗

  1. 我做错了什么?
  2. 是否有任何快速实现 zlib 压缩或多线程 png 创建,最好是在 C/C++ 中?
  3. 还有其他替代方法可以实现目标吗?

注意:PNG specification接下来是创建 block

更新: 此方法适用于并行创建 IDAT

    1. add one filter byte before each row of input image. 
2. split image in four equal parts. <-- may not be required passing pointer to buffer and their offsets
3. Compress Image Parts in parallel
(A)for first image part
--deflateinit(zstrm,Z_BEST_SPEED)
--deflate(zstrm, Z_FULL_FLUSH)
--deflateend(zstrm)
--store compressed buffer and its length
--store adler32 for current chunk, {a1=zstrm->adler} <--adler is of uncompressed data
(B)for second and third image part
--deflateinit(zstrm,Z_BEST_SPEED)
--deflate(zstrm, Z_FULL_FLUSH)
--deflateend(zstrm)
--store compressed buffer and its length
--strip first 2-bytes, reduce length by 2
--store adler32 for current chunk zstrm->adler,{a2,a3 similar to A} <--adler is of uncompressed data
(C) for last image part
--deflateinit(zstrm,Z_BEST_SPEED)
--deflate(zstrm, Z_FINISH)
--deflateend(zstrm)
--store compressed buffer and its length
--strip first 2-bytes and last 4-bytes of buffer, reduce length by 6
--here last 4 bytes should be equal to ztrm->adler,{a4=zstrm->adler} <--adler is of uncompressed data

4. adler32_combine() all four parts i.e. a1,a2,a3 & a4 <--last arg is length of uncompressed data used to calculate adler32 of 2nd arg
5. store total length of compressed buffers <--to be used in calculating CRC of complete IDAT & to be written before IDaT in file
6. Append "IDAT" to Final chunk
7. Append all four compressed parts in sequence to Final chunk
8. Append adler32 checksum computed in step 4 to Final chunk
9. Append CRC of Final chunk i.e.{"IDAT"+data+adler}

To be written in png file in this manner: [PNG_HEADER][PNG_DATA][PNG_END]
where [PNG_DATA] ->Length(4-bytes)+{"IDAT"(4-bytes)+data+adler(4-bytes)}+CRC(4-bytes)

最佳答案

即使 PNG 数据流中有多个 IDAT block ,它们仍然包含一个 zlib 压缩数据流。第一个 IDAT 的前两个字节是 zlib header ,最终 IDAT 的最后四个字节是整个数据流(2 字节 header 除外)的 zlib“adler32”校验和,在压缩之前计算。

zlib.net/pigz 有一个正在开发的并行 gzip (pigz) .当作为“pigz -z”调用时,它将生成 zlib 数据流而不是 gzip 数据流。

为此,您不需要拆分输入文件,因为并行压缩发生在 pigz 内部。

关于c++ - 使用 libpng 将位图缓冲区快速编码为 png,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22355998/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com