我在内存中有一个原始图像,组织为一个32位RGB值数组。我想尽快将其写出到图像文件中,以便释放内存。有没有一种方法可以执行以下操作来写入未压缩的JPEG,PNG或TIFF图像?也许我应该说,哪种图像格式与这种写入原始像素数据的方法兼容?请注意,左上像素位于像素数据的前4个字节中。
void write_image(uint32_t *pixels, int width, int height) {
FILE *file=fopen("file.jpg","wb");
write_header (file, width, height);
fwrite (pixels,1,width*height*4,file); // write raw pixel data
write_end (file);
fclose(file);
}
答案 0 :(得分:3)
未压缩的 JPEG 和 PNG 不重要,结果可能会存在可移植性问题。您最简单的选择可能是 TGA:
TGA 旨在存储可以快速加载以显示到帧缓冲区中的光栅化图像。它有一个非常简单的 18 字节标头,然后是原始像素数据。它是可流式传输的,这意味着图像数据可以在生成时写入,前提是它是光栅化的。对长度/偏移/CRC 表没有要求。最大的限制是样本必须是光栅化的 BGR 顺序和可选的第四个通道(通常是 alpha 但可以是任何东西)。标头中的宽度/高度字段必须是 16 位小端。 TGA 格式不像 GIF/JPEG/PNG 那样受到广泛支持,但您应该会找到一些能够渲染它的查看器。
对于 BGR 数据,标题可能是(十六进制值): 0x00 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 (width%256) (width/256) (height%256) (height/256) 0x18 0x20
对于 BGRA 数据,标题可能是: 0x00 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 (width%256) (width/256) (height%256) (height/256) 0x20 0x28
如果您的数据不是 BGR/BGRA 顺序并且您不能或不想转换它,我的第二个建议是 TIFF:
TIFF 设计专注于存储文档的光栅化扫描,并使用更复杂的 TTLV 样式标题。它不是那么可流式传输并且需要偏移表,但是您可以通过蛮力预计算并将整个图像定义为单个条带来解决此问题。完成标头后,您可以在生成时以光栅化 RGB 或 RGBA 顺序流式传输原始像素数据。 TIFF 还可以支持 big-endian 或 little-endian,每个样本最多 16 位。它通常是扫描仪选择的输出格式,因此查看器/编辑器支持相当普遍。
前四个字节是幻数(字节顺序和 TIFF 文件版本),后跟图像文件目录 (IFD) 的 4 字节偏移量。通常这个偏移量只是文件中的 8 个字节,以便紧跟在下一个放置 IFD。 IFD 是一个计数值 (N),后跟 N 个 12 字节条目的表,这些条目的形式为标签、类型、计数和值/偏移量。其余的细节在这里无法描述,但您可以阅读规范以获取更多信息。
答案 1 :(得分:1)
您似乎有两个不同的问题或动机。
首先,希望以某种未压缩格式写入图像以(大概)获得速度。 PNG和JPEG是压缩格式,尽管您可以指示编码器(至少在某些PNG实现中)使用“无压缩”设置。
但是:a)在很少的情况下,“优化”会产生关键的影响,普通的压缩器很快。
b)即使使用某些compression_level=0
设置进行编码,您仍将以特定格式(通常是标头)对图像进行编码。是什么导致我们产生第二种动机。
第二,您似乎想避免完全(仅)避免压缩,而是避免编码。也就是说,您要以未编码(“原始”)格式写入像素。当然,在这种情况下,您将无法写入PNG或JPEG图像。您可以使用自己的格式或some standard RAW format或准原始BMP格式。但是,您仍然需要注意内存中像素的组织方式(例如,每个通道一个字节,RGB,BGR,RGBA吗?)以及其他一些问题(例如,BMP要求将bytes per line 4的倍数。
答案 2 :(得分:0)
TGA格式是一个很好的选择。它只是一个简单的标头,后跟数据。 24或32位。