这两天写播放器测试插件,涉及到了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);
}