平台:Linux
/****************************************************************************
* 文件名:Yuyv422ToPnm.c
* 文件描述:把yuyv422格式的图片转换为pnm格式的图片,需要提供yuv422源文件名
* yuv图片的宽,yuv图片的高以及需要转换的pnm图片名称
* 编写人:王廷云
* 编写日期:2017-12-1
* 修改日期:2018-1-1
****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h> // 下面四个头文件是linux系统编程特有的
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <linux/videodev2.h> // 操作摄像头设备
#define CLAMP(v) ((v<0?0:(v>255?255:v))) // 钳制像素值的范围
int main(int argc, char **argv)
{
int width; // yuv图片的宽
int height; // yuv图片的高
/* 参数检查是否足够*/
if (argc != 5)
{
/* yuv图片名 yuv图片的宽,yuv图片的高,pnm图片名称 */
printf("Usage: [%s] [srcName] [width] [height] [destName]\n", argv[0]);
return -1;
}
/* 打开yuyv文件:用open是因为后面的内存映射要的是文件描述符 */
int fin = open(argv[1], O_RDONLY);
if (-1 == fin)
{
perror("open");
return -2;
}
/* 获取yuv图片信息 */
struct stat st_buf;
fstat(fin, &st_buf); // 用于获取图片大小
sscanf(argv[2], "%d", &width); // 获取图片宽度
sscanf(argv[3], "%d", &height); // 获取图片高度
/* 把文件进行内存映射:加快操作速度(此步骤可以不用) */
unsigned char *yuyv;
yuyv = mmap(NULL, st_buf.st_size, PROT_READ, MAP_SHARED, fin, 0);
if (MAP_FAILED == yuyv)
{
perror("mmap");
return -2;
}
/* 进行数据转换并保存到文件中去 */
FILE *fout = fopen(argv[4], "w");
if (NULL == fout)
{
perror("fopen");
return -3;
}
unsigned char *p = yuyv;
unsigned char y0, y1, u0, v1;
unsigned char rgb[3];
int x, y;
/* 写pnm文件头 */
fprintf(fout, "P6\n%d %d\n255\n", width, height);
/* 把yuv数据转换为rgb数据并写入pnm文件中 */
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x += 2) // 两个像素一起写
{
/* 读2个yuv422像素:共4个字节 yu yv */
y0 = *p++;
u0 = *p++;
y1 = *p++;
v1 = *p++;
/* 转换为2个rgb像素:共6个字节rgb rgb */
rgb[0] = CLAMP(y0 + 1.402 * (v1 - 128));
rgb[1] = CLAMP(y0 - 0.344 * (u0 - 128) - 0.714 * (v1 - 128));
rgb[2] = CLAMP(y0 + 1.772 * (u0 - 128));
fwrite(rgb, 1, 3, fout); // 写第一个rgb像素
rgb[0] = CLAMP(y1 + 1.402 * (v1 - 128));
rgb[1] = CLAMP(y1 - 0.344 * (u0 - 128) - 0.714 * (v1 - 128));
rgb[2] = CLAMP(y1 + 1.772 * (u0 - 128));
fwrite(rgb, 1, 3, fout); // 写第二个rgb像素
}
}
/* 尾部处理工作 */
munmap(yuyv, st_buf.st_size); // 解除内存映射
close(fin); // 关闭已打开的文件
fclose(fout);
return 0;
}