我在解压缩 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/