您的位置:首页 > 其它

YUV420 && RGB24

2017-04-08 18:48 288 查看
//*************************************************YUV***********************************************//

以将YUV420P数据中的Y、U、V三个分量分离开来并保存成三个文件。函数的代码如下所示

int yuv420_split(char *url, int w, int h,int num){  
    FILE *fp=fopen(url,"rb+");  
    FILE *fp1=fopen("output_420_y.y","wb+");  
    FILE *fp2=fopen("output_420_u.y","wb+");  
    FILE *fp3=fopen("output_420_v.y","wb+");  
  
    unsigned char *pic=(unsigned char *)malloc(w*h*3/2);  
  
    for(int i=0;i<num;i++){  
  
        fread(pic,1,w*h*3/2,fp);  
        //Y  
        fwrite(pic,1,w*h,fp1);  
        //U  
        fwrite(pic+w*h,1,w*h/4,fp2);  
        //V  
        fwrite(pic+w*h*5/4,1,w*h/4,fp3);  
    }  
  
    free(pic);  
    fclose(fp);  
    fclose(fp1);  
    fclose(fp2);  
    fclose(fp3);  
  
    return 0;  


  视频帧的宽和高分别为w和h,那么一帧YUV420P像素数据一共占用w*h*3/2 Byte的数据。其中前w*h Byte存储Y,接着的w*h*1/4 Byte存储U,最后w*h*1/4 Byte存储V。上述调用函数的代码运行后,将会把一张分辨率为256x256的YUV420P格式的像素数据文件分离成为三个文件:

output_420_y.y:纯Y数据,分辨率为256x256。

output_420_u.y:纯U数据,分辨率为128x128。
output_420_v.y:纯V数据,分辨率为128x128。

 //*************************************************RGB***********************************************//

函数可以将RGB24数据中的R、G、B三个分量分离开来并保存成三个文件。函数的代码如下所示。

int rgb24_split(char *url, int w, int h,int num){  
    FILE *fp=fopen(url,"rb+");  
    FILE *fp1=fopen("output_r.y","wb+");  
    FILE *fp2=fopen("output_g.y","wb+");  
    FILE *fp3=fopen("output_b.y","wb+");  
  
    unsigned char *pic=(unsigned char *)malloc(w*h*3);  
  
    for(int i=0;i<num;i++){  
  
        fread(pic,1,w*h*3,fp);  
  
        for(int j=0;j<w*h*3;j=j+3){  
            //R  
            fwrite(pic+j,1,1,fp1);  
            //G  
            fwrite(pic+j+1,1,1,fp2);  
            //B  
            fwrite(pic+j+2,1,1,fp3);  
        }  
    }  
  
    free(pic);  
    fclose(fp);  
    fclose(fp1);  
    fclose(fp2);  
    fclose(fp3);  
  
    return 0;  


从代码可以看出,与YUV420P三个分量分开存储不同,RGB24格式的每个像素的三个分量是连续存储的。一帧宽高分别为w、h的RGB24图像一共占用w*h*3 Byte的存储空间。RGB24格式规定首先存储第一个像素的R、G、B,然后存储第二个像素的R、G、B…以此类推。类似于YUV420P的存储方式称为Planar方式,而类似于RGB24的存储方式称为Packed方式。上述调用函数的代码运行后,将会把一张分辨率为500x500的RGB24格式的像素数据文件分离成为三个文件:

output_r.y:R数据,分辨率为256x256。

output_g.y:G数据,分辨率为256x256。

output_b.y:B数据,分辨率为256x256。

 //*************************************************RGB2YUV***********************************************//

将RGB24格式的像素数据转换为YUV420P格式的像素数据

unsigned char clip_value(unsigned char x,unsigned char min_val,unsigned char  max_val){  
    if(x>max_val){  
        return max_val;  
    }else if(x<min_val){  
        return min_val;  
    }else{  
        return x;  
    }  
}  
  
//RGB to YUV420  
bool RGB24_TO_YUV420(unsigned char *RgbBuf,int w,int h,unsigned char *yuvBuf)  
{  
    unsigned char*ptrY, *ptrU, *ptrV, *ptrRGB;  
    memset(yuvBuf,0,w*h*3/2);  
    ptrY = yuvBuf;  
    ptrU = yuvBuf + w*h;  
    ptrV = ptrU + (w*h*1/4);  
    unsigned char y, u, v, r, g, b;  
    for (int j = 0; j<h;j++){  
        ptrRGB = RgbBuf + w*j*3 ;  
        for (int i = 0;i<w;i++){  
              
            r = *(ptrRGB++);  
            g = *(ptrRGB++);  
            b = *(ptrRGB++);  
            y = (unsigned char)( ( 66 * r + 129 * g +  25 * b + 128) >> 8) + 16  ;            
            u = (unsigned char)( ( -38 * r -  74 * g + 112 * b + 128) >> 8) + 128 ;            
            v = (unsigned char)( ( 112 * r -  94 * g -  18 * b + 128) >> 8) + 128 ;  
            *(ptrY++) = clip_value(y,0,255);  
            if (j%2==0&&i%2 ==0){  
                *(ptrU++) =clip_value(u,0,255);  
            }  
            else{  
                if (i%2==0){  
                *(ptrV++) =clip_value(v,0,255);  
                }  
            }  
        }  
    }  
    return true;  
}  
  
int rgb24_to_yuv420(char *url_in, int w, int h,int num,char *url_out){  
    FILE *fp=fopen(url_in,"rb+");  
    FILE *fp1=fopen(url_out,"wb+");  
  
    unsigned char *pic_rgb24=(unsigned char *)malloc(w*h*3);  
    unsigned char *pic_yuv420=(unsigned char *)malloc(w*h*3/2);  
  
    for(int i=0;i<num;i++){  
        fread(pic_rgb24,1,w*h*3,fp);  
        RGB24_TO_YUV420(pic_rgb24,w,h,pic_yuv420);  
        fwrite(pic_yuv420,1,w*h*3/2,fp1);  
    }  
  
    free(pic_rgb24);  
    free(pic_yuv420);  
    fclose(fp);  
    fclose(fp1);  
  
    return 0;  


RGB到YUV的转换公式:
Y= 0.299*R+0.587*G+0.114*B
U=-0.147*R-0.289*G+0.463*B
V= 0.615*R-0.515*G-0.100*B
在转换的过程中有以下几点需要注意:
1) RGB24存储方式是Packed,YUV420P存储方式是Packed。
2) U,V在水平和垂直方向的取样数是Y的一半
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: