欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

yuv 格式

程序员文章站 2022-07-02 08:55:25
...

1.YUV4:4:4格式意味着Y、U、V三个分量的采集比例相同,因此在生成的图像里,每个像素的三个分量信息完整,都是8bit,也就是一个字节。YUV4:2:2格式的采样特征是在每相邻的两个像素,一个丢弃U分量,一个丢弃V分量.YUV4:2:0格式的采样特征是所有像素都保留Y分量,同一行的像素只保留U分量,或者是V分量,同一行中相邻的两个像素只保留同一个Y分量或者U分量。
2.将YUV444转换为NV12(YUV420):从偶数行(YUV444)提取U分量,且从每一偶数行(YUV444)的每四个像素提取2个U分量。同理从奇数行(YUV444)提取V分量,且从每一偶数行(YUV444)的每四个像素提取2个V分量.若将一幅格式为YUV444,分辨率为n x m的图片转换为NV12.YUV444格式图片大小M=n x m x 3.转换为NV12后大小M=3 / 2 x n x m.实现代码如下:

int yuv444_to_nv12(unsigned char *buffer_src,int fd)
{

    unsigned char *yuvIn,*yuvOutput,*y_in,*u_in,*v_in,*y_output,*u_output,*v_output;
    int i,j,u_count=0,v_count=0,temp_count=0;
    int  ret;
    //yuv444------->NV12
    yuvOutput =(unsigned char*) malloc(SIZE_NV12);
    if(yuvOutput == NULL){

                ALOGE("malloc memory failed\n");
                return -1;
        }
     yuvIn = buffer_src;
     y_in = yuvIn;
     u_in = yuvIn;
     v_in = yuvIn;
     y_output = yuvOutput;
     u_output = (yuvOutput + WIDTH * HEIGHT);
     v_output = (yuvOutput + WIDTH * HEIGHT);
     //Y
        for(i =0; i <HEIGHT; i++){
                for(j=0; j <WIDTH; j++){
                        *y_output = *y_in;//yuv yuv yuv------>yyyy  uvuvuv

                         y_in += 3;
                         y_output++;
                         count++;
            }
       }
   //UV 
        for(i =0; i <HEIGHT; i++){
           for(j=0; j<WIDTH / 4; j++){ //每一次处理4个像素
                   //偶数行
                if((i % 2) == 0){
                      *(u_output)  = *(u_in + 1);
                      count++;
                      *(u_output + 2) = *(u_in +4);
                      count++;
                      //调整输入输出的位置
                      u_in += 12;    //每四个像素提取2个u量,指向下一次要处理的起始位置
                      u_output += 4; //指向下一个u的位置 
                }
                  //奇数行
                else {
                     *(v_output + 1) = *(v_in + 2);
                     count++;
                     *(v_output + 3) = *(v_in + 5);
                     count++;
                     v_in += 12;
                     v_output += 4;

                }
        }
        if((i % 2) == 0){
                v_in += WIDTH * 3; //不从偶数行提取v
         }
        else{
                u_in += WIDTH * 3;
        }
   }
        ret = write(fd,yuvOutput,SIZE_NV12);
        ALOGE(" cout:%d,SIZE_NV12:%d,ret:%d\n",count,SIZE_NV12,ret);
        count = 0;
        free(yuvOutput);
        return 0;

}

3.将NV12(YUV420)转换为YUYV(YUV422)。我们从1可以看到,YUV444,YUYV,NV12的Y分量是一样的。而YUYV的UV分量大小是YUV444的一半,NV12的UV分量大小是YUYV的一半。那么我们可以采用将NV12的UV分量扩大一倍来填充YUYV的UV分量。部分实现代码如下:

    y = mem_buffer;
    uv = mem_buffer + mCamDrvHeight * mCamDrvWidth;
    yuyv = mCamDriverV4l2Buffer[index_buf];
    for (j = 0; j < mCamDrvHeight;j++)
        {
            for (i = 0; i < mCamDrvWidth / 2;i++)
            {
                yuyv[0] = y[2 * i];//y
                yuyv[1] = uv[2 * i];//u
                yuyv[2] = y[2 * i + 1];//y
                yuyv[3] = uv[2 * i + 1];//v
                yuyv += 4;
            }
            y += mCamDrvWidth;
            if (j & 1)
            {
                uv += mCamDrvWidth;
            }
        }

相关标签: yuv