使用膨胀来解压缩 png 文件
Using inflate to decompress a png file
我一直在解压缩 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
只是一个结构,它保存图像的宽度、高度和深度,并具有大小为width*height*depth
的无符号 char 数组。
我试图解压缩的图像是这样的:arial.png
它没有过滤 (0),是带有 alpha 的真彩色 png。它也只包含一个 IDAT 块。
但相反,我得到这样的东西:不正确的 png
我知道图像是颠倒的,这是我的渲染器是自下而上的,而png是自上而下的问题;这不是我现在关心的事情。
我还应该注意,inflate
实际上只运行一次并返回Z_OK,所以我认为问题不在于不处理扫描线过滤器。我尝试过每行添加一个字节,然后不将每行的第一个字节复制到Pixels
数组中,但这并没有太大区别。
知道我可能做错了什么吗?
首先,在最后一次调用时返回Z_OK
是不行的。如果它没有返回Z_STREAM_END
,则您没有解压缩并验证完整的压缩数据。
其次,您的avail_out
不允许在每个扫描行的开头使用筛选器字节。将高度添加到avail_out
并为此提供空间。
第三,我不知道您是如何从原始的512x512 RGBA图像中获得643x514 RGB图像的。您需要跳过每行的过滤器字节,然后每个像素是四个字节。
看起来您可能忽略了每条扫描线开头的过滤器方法字节。它就在那里,即使它是 0。
我认为你应该让它while(Stream.avail_out == 0);
只要z.avail_out
等于零,就意味着需要再次调用可用于解压缩数据和inflate()
的压缩数据填充字节。
始终考虑它的含义,当有可用(未填充)的输出字节时,我们应该停止,以便avail_out > 0
.
- 从存储为 Windows 资源 (c++) 的 png 中获取 png 文件数据
- 使用 stbi_write_png,如何将 0 和 1 的矩形字节数组转换为单色 png 文件?
- 如何启用libMagick++以保存.png文件格式
- 无法在CLion(macOS)上打开带有CImg的.png文件
- 尝试使用 CPP 在一个 Qt 窗口中显示多个 png 文件
- 我正在尝试SDL_DisplayFormat一个.png文件,我想,我可能缺少依赖项
- 从.ppm转换为.png文件
- 未找到"png.h"文件,当包含在Qt小部件项目中时
- 将较小的PNG文件组合在C 中的较大PNG文件中
- 使用膨胀来解压缩 png 文件
- 从 cin 读取 PNG 文件
- 以编程方式馈送 KML 文件并检索/生成.png文件
- SDL_Image libpng 错误:不是 PNG 文件
- 使用 C++、libpng 和 OpenMP 并行创建 PNG 文件
- 使用 boost.gil 逐像素读取.png文件
- Visual Studio 2012(C++)-使用附带的.png文件
- 0x00000000处的访问冲突正在使用SDL_image库加载PNG文件
- 需要从png文件中读取数据并将其保存到新文件中,如何?C++
- QT .png文件没有显示在屏幕上
- 如何使用c++从png文件中提取像素