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转opencv Mat格式
下一篇: 使用OpenLayers叠加天地图