YUV420 && RGB24


//*************************************************YUV***********************************************//

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

  1. int yuv420_split(char *url, int w, int h,int num){  
  2.     FILE *fp=fopen(url,"rb+");  
  3.     FILE *fp1=fopen("output_420_y.y","wb+");  
  4.     FILE *fp2=fopen("output_420_u.y","wb+");  
  5.     FILE *fp3=fopen("output_420_v.y","wb+");  
  6.   
  7.     unsigned char *pic=(unsigned char *)malloc(w*h*3/2);  
  8.   
  9.     for(int i=0;i<num;i++){  
  10.   
  11.         fread(pic,1,w*h*3/2,fp);  
  12.         //Y  
  13.         fwrite(pic,1,w*h,fp1);  
  14.         //U  
  15.         fwrite(pic+w*h,1,w*h/4,fp2);  
  16.         //V  
  17.         fwrite(pic+w*h*5/4,1,w*h/4,fp3);  
  18.     }  
  19.   
  20.     free(pic);  
  21.     fclose(fp);  
  22.     fclose(fp1);  
  23.     fclose(fp2);  
  24.     fclose(fp3);  
  25.   
  26.     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三个分量分离开来并保存成三个文件。函数的代码如下所示。

  1. int rgb24_split(char *url, int w, int h,int num){  
  2.     FILE *fp=fopen(url,"rb+");  
  3.     FILE *fp1=fopen("output_r.y","wb+");  
  4.     FILE *fp2=fopen("output_g.y","wb+");  
  5.     FILE *fp3=fopen("output_b.y","wb+");  
  6.   
  7.     unsigned char *pic=(unsigned char *)malloc(w*h*3);  
  8.   
  9.     for(int i=0;i<num;i++){  
  10.   
  11.         fread(pic,1,w*h*3,fp);  
  12.   
  13.         for(int j=0;j<w*h*3;j=j+3){  
  14.             //R  
  15.             fwrite(pic+j,1,1,fp1);  
  16.             //G  
  17.             fwrite(pic+j+1,1,1,fp2);  
  18.             //B  
  19.             fwrite(pic+j+2,1,1,fp3);  
  20.         }  
  21.     }  
  22.   
  23.     free(pic);  
  24.     fclose(fp);  
  25.     fclose(fp1);  
  26.     fclose(fp2);  
  27.     fclose(fp3);  
  28.   
  29.     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格式的像素数据

  1. unsigned char clip_value(unsigned char x,unsigned char min_val,unsigned char  max_val){  
  2.     if(x>max_val){  
  3.         return max_val;  
  4.     }else if(x<min_val){  
  5.         return min_val;  
  6.     }else{  
  7.         return x;  
  8.     }  
  9. }  
  10.   
  11. //RGB to YUV420  
  12. bool RGB24_TO_YUV420(unsigned char *RgbBuf,int w,int h,unsigned char *yuvBuf)  
  13. {  
  14.     unsigned char*ptrY, *ptrU, *ptrV, *ptrRGB;  
  15.     memset(yuvBuf,0,w*h*3/2);  
  16.     ptrY = yuvBuf;  
  17.     ptrU = yuvBuf + w*h;  
  18.     ptrV = ptrU + (w*h*1/4);  
  19.     unsigned char y, u, v, r, g, b;  
  20.     for (int j = 0; j<h;j++){  
  21.         ptrRGB = RgbBuf + w*j*3 ;  
  22.         for (int i = 0;i<w;i++){  
  23.               
  24.             r = *(ptrRGB++);  
  25.             g = *(ptrRGB++);  
  26.             b = *(ptrRGB++);  
  27.             y = (unsigned char)( ( 66 * r + 129 * g +  25 * b + 128) >> 8) + 16  ;            
  28.             u = (unsigned char)( ( -38 * r -  74 * g + 112 * b + 128) >> 8) + 128 ;            
  29.             v = (unsigned char)( ( 112 * r -  94 * g -  18 * b + 128) >> 8) + 128 ;  
  30.             *(ptrY++) = clip_value(y,0,255);  
  31.             if (j%2==0&&i%2 ==0){  
  32.                 *(ptrU++) =clip_value(u,0,255);  
  33.             }  
  34.             else{  
  35.                 if (i%2==0){  
  36.                 *(ptrV++) =clip_value(v,0,255);  
  37.                 }  
  38.             }  
  39.         }  
  40.     }  
  41.     return true;  
  42. }  
  43.   
  44. int rgb24_to_yuv420(char *url_in, int w, int h,int num,char *url_out){  
  45.     FILE *fp=fopen(url_in,"rb+");  
  46.     FILE *fp1=fopen(url_out,"wb+");  
  47.   
  48.     unsigned char *pic_rgb24=(unsigned char *)malloc(w*h*3);  
  49.     unsigned char *pic_yuv420=(unsigned char *)malloc(w*h*3/2);  
  50.   
  51.     for(int i=0;i<num;i++){  
  52.         fread(pic_rgb24,1,w*h*3,fp);  
  53.         RGB24_TO_YUV420(pic_rgb24,w,h,pic_yuv420);  
  54.         fwrite(pic_yuv420,1,w*h*3/2,fp1);  
  55.     }  
  56.   
  57.     free(pic_rgb24);  
  58.     free(pic_yuv420);  
  59.     fclose(fp);  
  60.     fclose(fp1);  
  61.   
  62.     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的一半
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值