工作上需要测试视频解码之后的数据或是经过算法处理之后图像是否符合预期,可以使用一些现有的格式比如 JPG、PNG等常见格式。因为只是临时需要我们可以使用一种更简单的图像格式 PPM
。PPM是一种简单的图片格式,我们可以通过PPM进行图像相关的学习。
PPM格式介绍:
PPM图像格式分为两部分,分别为头部分和图像数据部分。
头部分:
由3部分组成,通过换行或空格进行分割,一般PPM的标准是空格。 第1部分:P3或P6,指明PPM的编码格式, 第2部分:图像的宽度和高度,通过ASCII表示, 第3部分:最大像素值,0-255字节表示。
每个图像文件的开头都通过2个字节「magic number」来表明文件格式的类型(PBM, PGM, PPM),以及编码方式(ASCII 或 Binary),magic number分别为P1、P2、P3、P4、P5、P。
Magic Number | Type | Encoding |
---|---|---|
P1 | Bitmap | ASCII |
P2 | Graymap | ASCII |
P3 | Pixmap | ASCII |
P4 | Bitmap | Binary |
P5 | Graymap | Binary |
P6 | Pixmap | Binary |
图像数据部分:
ASCII格式:按RGB的顺序排列,RGB中间用空格隔开,图片每一行用回车隔开。 Binary格式:PPM用24bits代表每一个像素,红绿蓝分别占用8bits。
PPM文件示例代码:
C\C++:
static int save_rgba_as_ppm(unsigned char* p_rgba, int width, int height, const char *filepath)
{
FILE *pFile;
pFile = fopen(filepath, "wb");
if (pFile == NULL)
return -1;
// Write header
// 默认是 P6 颜色像素 binary 版本
fprintf(pFile, "P6\n%d %d\n255\n", width, height);
// Write pixel data
for (int i = width*height; i > 0; i--)
{
fwrite(pRGBA, 1, 1, pFile);
fwrite(pRGBA + 1, 1, 1, pFile);
fwrite(pRGBA + 2, 1, 1, pFile);
pRGBA += 4;
}
// Close file
fclose(pFile);
return 0;
}
Java:
public void save_rgba_as_ppm(byte[] rgba, int w, int h, String filepath) {
try {
FileOutputStream fileOutputStream = new FileOutputStream(new File(filepath));
BufferedOutputStream outputStream = new BufferedOutputStream(fileOutputStream);
String s = String.format("P6\n%d %d\n255\n", w, h);
outputStream.write(s.getBytes());
int offset = 0;
for (int i = w*h; i > 0; i--)
{
outputStream.write(rgba[offset]);
outputStream.write(rgba[offset + 1]);
outputStream.write(rgba[offset + 2]);
offset += 4;
}
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
总结:
使用PPM可以给图像处理相关的调试工作带来便利。没有复杂的压缩计算,原始流数据存储。希望能帮助到从事相关工作的童鞋。:)