把yuyv422格式的图片转换为pnm格式的图片

版权声明:本文为博主原创文章,转载时请标明来源。 https://blog.csdn.net/aiwangtingyun/article/details/79835537

平台: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;
}

猜你喜欢

转载自blog.csdn.net/aiwangtingyun/article/details/79835537