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

平台:Linux


理论基础:

在一帧yuyv422图像中,y的个数为像素个数,u和v的个数为像素个数的一半;在yuyv420中,y的个数不变,u,v 个数再减半,为像素个数的1/4 ;yuv420p中的p表示yuv420中的数据 y u v 三种数据分开存放,先存放y数据,在存放u数据,最后存放v数据。


/********************************************************************
 * 文件名:Yuv422ToYuv420p.c
 * 文件描述:把 yuyv422 格式的图片转换为 yuv420p 格式 
 * 编写人:王廷云
 * 编写日期:2017-12-1
 * 修改日期:2018-1-1
********************************************************************/
#include 
#include 
#include 

int main(int argc, char **argv)
{
	int width;                          // 图片的宽度
	int height;                         // 图片的高度
	
	/* 第一步:检查参数 */
	if (4 != argc)
	{
		/* 参数:程序名、yuv422文件名、yuv422宽度、yuv422高度、yuv420p文件名 */
		printf("Usage: [%s] [src] [width]x[height] [dest]\n", argv[0]);
		return -1;
	}
	
	/* 第二步:打开yuyv422源文件 */
	FILE *fin;
	fin = fopen(argv[1], "r");
	if (NULL == fin)
	{
		fprintf(stderr,"open file: %s failed\n", argv[1]);
		return -2;
	}

	/* 第三步:获取yuyv422图片的信息 */
	sscanf(argv[3], "%dx%d", &width, &height);  // yuv422图片宽高
	
	/* 第四步:yuv422数据转换为yuv420数据 */
	int len = width*height + width*height/2;    // yuv420p文件大小
	unsigned char *data= malloc(len);           // 转换后的yuv420p的数据就存放在这
	if (NULL == data)
	{
		fprintf(stderr, "malloc data failed\n");
		fclose(fin);
		return -3;
	}
	
	/* 配置yuv420p的 y u v 数据位置 */
	unsigned char *y = data;                    // y数据存放的位置
	unsigned char *u = data+width*height;       // u数据存放的位置
	unsigned char *v = u+width*height/4;        // v数据存放的位置
	
	/* 数据转换:两行像素一起处理 */
	int i, j;
	unsigned char *buff = malloc(width*2);      
	if (NULL == buff)
	{
		fprintf(stderr, "malloc buff failed\n");
		fclose(fin);
		return -4;
	}	
	for (i = 0; i < height; i += 2)     	
	{

		/* 第一行:两个像素一起处理,一个像素两个字节 */
		fread(buff, 2, width, fin);
		for (j = 0; j < width*2; j +=4) 
		{
			*y++ = buff[j];     /* y0 */
			*u++ = buff[j+1];   /* u0 */
			*y++ = buff[j+2];   /* y1 */
			//*v++ = buff[j+3]; /* v1 */
		}
		/* 第二行:两个像素一起处理,一个像素两个字节 */
		fread(buff, 2, width, fin);
		for (j = 0; j < width*2; j += 4) 
		{
			*y++ = buff[j];     /* y0 */
			//*u++ = buff[j+1]; /* u0 */
			*y++ = buff[j+2];   /* y1 */
			*v++ = buff[j+3];   /* v1 */
		}
	}
	
	/* 第五步:创建目标yuyv420p文件并把数据写入到文件中 */ 
	FILE *fout;
	fout = fopen(argv[2], "w");
	if (NULL == fout)
	{
		fprintf(stderr,"open file: %s failed\n", argv[2]);
		return -3;
	}
	
	/* 写入数据 */
	int ret = 0;
	while (1)                                   // 此操作保证数据写完 
	{
		ret += fwrite(data+ret, 1, len, fout);
		if (ret == len)
		{
			break;
		}
	}
	
	return 0;
}


如果对yuv之间的数据关系不理解的话可以参考我的另一篇博客:

深入探讨 yuv 之间的关系和转换

你可能感兴趣的:(C语言)