yuv 格式

孤者浪人 提交于 2019-12-24 07:44:38

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;
            }
        }

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!