YUV2RGB总结

这两天写播放器测试插件,涉及到了yuv2rgb的部分,这里我说现实到PC上,所以是转成32位RGBA,准确的来说windows是BGRA的现实方式,参考了下广大网友的很多做法,最简单典型的算整形法了,而且速度也很快,不会涉及到浮点数运算。当然如果要PORTING到嵌入式平台,做好的当然是使用查表法咯,查表分部分查表法和完全查表法,等会研究下,在贴出具体情况。

自我感觉代码还算简单,理解起来也不难,这里贴出来分享:

/*------------------------
yuv420 to rgb8888
转换公式:
R=Y+1.4075*(V-128)
G=Y-0.3455*(U-128) - 0.7169*(V-128)
B=Y+1.779*(U-128)
为了加快运算速度,采用下面的整形计算法:
u = YUVdata[UPOS] - 128;
v = YUVdata[VPOS] - 128;

rdif = v + ((v * 103) >> 8);
invgdif = ((u * 88) >> 8) +((v * 183) >> 8);
bdif = u +( (u*198) >> 8);
 
r = YUVdata[YPOS] + rdif;
g = YUVdata[YPOS] - invgdif;
b = YUVdata[YPOS] + bdif;
r=r>255?:255:(r<0:?0:r);
g=g>255?:255:(g<0:?0:g);
b=b>255?:255:(b<0:?0:b);
--------------------------*/
void yuv_to_rgb(  unsigned char * src[3],  // yuv420
      int stride_s,     // stride of lum, assume strides of U,V are stride_s/2
      int W,       // width, assume W%2 == 0
      int H,       // height, assume H%2 == 0
      unsigned char* _dst    // rgb32
    )
{
 unsigned char * pY = src[0];
 unsigned char * pU = src[1];
 unsigned char * pV = src[2];
 unsigned char * outbuf = _dst;
 int    stride = stride_s;
 int    width = W, height = H;
 int    i,j,k,y,u,v,r,g,b,rdif,invgdif,bdif;
 int    YPOS,UPOS,VPOS;

 YPOS = UPOS= VPOS = 0;
 for(i=0; i {
  for (j=0; j  {
   k = 0;
   y = pY[YPOS];
   u = pU[UPOS] - 128;
   v = pV[VPOS] - 128;
   
   rdif = v + ((v * 103) >> 8);
   invgdif = ((u * 88) >> 8) +((v * 183) >> 8);
   bdif = u +( (u*198) >> 8);
   
   r = y + rdif;
   g = y - invgdif;
   b = y + bdif;

   r=r>255?255:(r<0?0:r);
   g=g>255?255:(g<0?0:g);
   b=b>255?255:(b<0?0:b);

   outbuf[(i*width + j)*4 + k++] = b;
   outbuf[(i*width + j)*4 + k++] = g;
   outbuf[(i*width + j)*4 + k++] = r;
   outbuf[(i*width + j)*4 + k++] = 0xff;

   YPOS++;     
   if(j & 0x01)  //u,v是二分之一y
   {
    UPOS++;
    VPOS++;     
   }
  }
  if((i & 0x01)== 0)  //u,v是二分之一y
  {
   UPOS -= width>>1;
   VPOS -= width>>1;
    }
 } 
}

 

另外,对于YUV的调试可能会比较多的想把转化的图片保存成位图来分析,再贴出自己写的位图保存函数,当然这只是针对windows平台的,如果是嵌入式平台,只需要吧BITMAPHEADER结构体自己定义和填充咯

#include
#include "stdio.h"

 

//将视频帧保存成一张位图,存到工程文件夹下
void DramBMP( unsigned char *buffer, int w, int h, int bitCount,char *url)
{
 FILE *file_out;
 int len;
 BITMAPFILEHEADER bfh;
 BITMAPINFOHEADER bih;
 memset( &bfh, 0, sizeof( bfh ) );
    memset( &bih, 0, sizeof( bih ) );
 
 file_out = fopen( url, "wb" );
 
 if( file_out == 0 )
 {
  return;
 }
 len = w*h*4;
 bfh.bfType = 'MB';
 bfh.bfSize = sizeof( bfh ) + len + sizeof( BITMAPINFOHEADER );
 bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );
 fwrite( &bfh, sizeof(bfh), 1, file_out );
 
 
    bih.biSize = sizeof( bih );
    bih.biWidth = w;
    bih.biHeight = -h;
    bih.biPlanes = 1;
    bih.biBitCount = bitCount;
 
 fwrite( &bih, sizeof(bih), 1, file_out );
 fwrite( buffer, len, 1, file_out );
 fclose(file_out);
}

 

你可能感兴趣的:(日志)