1、用查表的方法实现相互转换,代码可以参考“点对点视频会议程序VideoNet”
2、用C语言定点乘加运算实现,代码参考XviD
参考其中的ConvertYUV2RGB函数
http://hi.baidu.com/yeyingxian/blog/item/193a8882729c9dbf6d8119cd.html
http://hi.baidu.com/yeyingxian/blog/item/7bbcd8bfc8d6d20a18d81f58.html
3、MMX实现,代码参考XviD,还有libmpeg2的rgb_mmx.c
int ConvertRGB2YUV(int w,int h,unsigned char *bmp,unsigned char *yuv)
{
unsigned char *u,*v,*y;
unsigned char *r;
int i,j;
int rgbw=w*3;
short y_mul[]={66,129,25,0};
short u_mul[]={-38,-74,112,0};
short v_mul[]={112,-94,-18,0};
int Y_ADD=16;
int C_ADD=128;
y=yuv;
u=yuv+w*h;
v=u+(w*h)/4;
// Get r,g,b pointers from bmp image data....
r=bmp;
//Get YUV values for rgb values...
_asm {
movq mm7,[y_mul]
}
for(i=0;i<h;i+=2)
{
for(j=0;j<w;j+=2)
{
_asm {
mov edx,rgbw
mov esi,r
movq mm0,[esi]
movq mm2,[esi+edx]
pxor mm4,mm4
pxor mm5,mm5
punpcklbw mm0, mm4 ; [ |b |g |r ]
punpcklbw mm2, mm5 ; [ |b |g |r ]
movq mm6, mm0 ; = [ |b4|g4|r4]
paddw mm6, mm2 ; +[ |b4|g4|r4]
pmaddwd mm0, mm7 ; *= Y_MUL
pmaddwd mm2, mm7 ; *= Y_MUL
movq mm4, mm0 ; [r]
movq mm5, mm2 ; [r]
psrlq mm4, 32 ; +[g]
psrlq mm5, 32 ; +[g]
paddd mm0, mm4 ; +[b]
paddd mm2, mm5 ; +[b]
movd mm1, [esi+3] ; src[%1...]
movd mm3, [esi+edx+3] ; src[x_stride+%1...]
pxor mm4, mm4
pxor mm5, mm5
punpcklbw mm1, mm4 ; [ |b |g |r ]
punpcklbw mm3, mm5 ; [ |b |g |r ]
paddw mm6, mm1 ; +[ |b4|g4|r4]
paddw mm6, mm3 ; +[ |b4|g4|r4]
pmaddwd mm1, mm7 ; *= Y_MUL
pmaddwd mm3, mm7 ; *= Y_MUL
movq mm4, mm1 ; [r]
movq mm5, mm3 ; [r]
psrlq mm4, 32 ; +[g]
psrlq mm5, 32 ; +[g]
paddd mm1, mm4 ; +[b]
paddd mm3, mm5 ; +[b]
mov edi,y
mov ebx,u
mov ecx,v
mov edx,w
movd eax, mm0
shr eax, 8
add eax, Y_ADD
mov [edi], al ; y_ptr[0]
movd eax, mm1
shr eax, 8
add eax, Y_ADD
mov [edi + 1], al ; y_ptr[1]
movd eax, mm2
shr eax, 8
add eax, Y_ADD
mov [edi + edx*1 + 0], al ; y_ptr[y_stride + 0]
movd eax, mm3
shr eax, 8
add eax, Y_ADD
mov [edi + edx*1 + 1], al ; y_ptr[y_stride + 1]
; u_ptr, v_ptr
movq mm0, mm6 ; = [ |b4|g4|r4]
pmaddwd mm6, [v_mul] ; *= V_MUL
pmaddwd mm0, [u_mul] ; *= U_MUL
movq mm1, mm0
movq mm2, mm6
psrlq mm1, 32
psrlq mm2, 32
paddd mm0, mm1
paddd mm2, mm6
movd eax, mm0
shr eax, 10
add eax, C_ADD
mov [ebx], al
movd eax, mm2
shr eax, 10
add eax, C_ADD
mov [ecx], al
add esi, 6 ;r+=6
add edi,2 ;y+=2
add ebx,1 ;u+=1
add ecx,1 ;v+=1
mov r,esi
mov y,edi
mov u,ebx
mov v,ecx
}
}
r+=w*3;
y+=w;
}
// Get the right pointers...
return 1;
}