我在解压缩png文件方面遇到了麻烦。这是处理IDAT块的代码:
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
只是一个包含图像宽度,高度和深度的结构,并且有一个大小为{的unsigned char数组{1}}。
我尝试解压缩的图片是:arial.png
它没有过滤(0)并且是带有alpha的truecolor png。它也只包含一个IDAT块。
但我得到的是这样的东西:incorrect png
我意识到图像是颠倒的,这是我的渲染器自下而上,png是自上而下的问题;它不是我现在关心的事情。
我还应该注意width*height*depth
实际只运行一次并返回Z_OK,所以我不认为问题在于不处理扫描线过滤器。我尝试过每行添加一个字节,然后不将每行的第一个字节复制到inflate
数组,但这并没有太大的区别。
任何想法我可能做错了什么?
答案 0 :(得分:0)
看起来您可能忽略了每条扫描线开头的过滤器方法字节。它就在那里,即使它是0。
答案 1 :(得分:0)
我认为你应该成功while(Stream.avail_out == 0);
只要z.avail_out
等于零,就意味着压缩数据的压缩数据填充字节和inflate()
需要再次调用。
总是想到它的含义,当有可用(未填充)的字节输出时,我们应该停止avail_out > 0
。
答案 2 :(得分:0)
首先,在最后一次通话中返回Z_OK
是不行的。如果它没有返回Z_STREAM_END
,那么您没有解压缩并验证完整的压缩数据。
其次,您的avail_out
不允许每条扫描线开头的滤波器字节。将高度添加到avail_out
并为其提供空间。
第三,我不知道你是如何从原始512x512 RGBA图像中获得643x514 RGB图像的。你需要跳过每一行的滤波器字节,然后每个像素四个字节。