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

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

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

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

猜你喜欢

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