平台: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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
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之间的数据关系不理解的话可以参考我的另一篇博客: