c++ - 使用 inflate 解压 png 文件

标签 c++ c png zlib inflate

我在解压缩 png 文件时遇到问题。这是处理 IDAT block 的代码:

case PNG_CHUNK_IDAT: {
            z_stream Stream = {};
            int Error = inflateInit(&Stream);

            if(Error == Z_OK) {
                Stream.avail_in = ChunkLength;
                Stream.next_in = At;
                Stream.avail_out = PngImage.Width * PngImage.Height * PngImage.Depth;
                Stream.next_out = PngImage.Pixels;

                do {
                    Error = inflate(&Stream, Z_NO_FLUSH);
                    if(Error != Z_OK) {
                        break;
                    }
                } while(Stream.avail_out != 0);
                inflateEnd(&Stream);
            }

            At += ChunkLength;
            break;
        }

其中 At 是 png 文件缓冲区中的当前位置,而 PngImage 只是一个保存图像宽度、高度和深度的结构体,并具有大小为宽度*高度*深度的无符号字符数组。

我试图解压缩的图像是这样的:arial.png

它没有过滤 (0),是带有 alpha 的真彩色 png。它也只包含一个 IDAT block 。

但我得到的是这样的东西:incorrect png

我知道图像是颠倒的,这是我的渲染器是自下而上而 png 是自上而下的问题;这不是我现在关心的事情。

我还应该注意,inflate 实际上只运行一次并返回 Z_OK,所以我认为问题不在于不处理扫描线过滤器。我尝试每行添加一个字节,然后不将每行的第一个字节复制到 Pixels 数组,但这并没有太大区别。

知道我可能做错了什么吗?

最佳答案

首先,在最后一次调用时返回 Z_OK 是不行的。如果它不返回 Z_STREAM_END,则说明您没有解压并验证完整的压缩数据。

其次,您的 avail_out 不允许在每个扫描行的开头使用过滤字节。将高度添加到 avail_out 并为其提供空间。

第三,我不知道如何从原始 512x512 RGBA 图像中获得 643x514 RGB 图像。您需要跳过每行上的过滤字节,然后每个像素是四个字节。

关于c++ - 使用 inflate 解压 png 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42915084/

相关文章:

c++ - 在 C++ 代码中转换字符串

c++ - boost 表现力 : wrong match?

c++ - 类标识符从不工作?

c - 在c中识别并打印货币符号

c++ - Gnuplot - 保存输出

python - 如何将cpp结构中的字符串转换为python结构

c - 当我删除第一个节点时,它会生成无限循环错误

c - 无法从 C 中的数组中打印出值

iphone - iphone 中的 jpg 图像和 2x 图像

binary - 解释 PNG 像素数据