代码改变世界

转:YCbCr420 to RGB

2011-08-20 09:33  yucan  阅读(672)  评论(0编辑  收藏  举报

YUV420_to_RGB24 算法

算法一: 查表法

const int Table_fv1[256]={ -180, -179, -177, -176, -174, -173, -172, -170, -169, -167, -166, -165, -163, -162, -160, -159, -158, -156, -155, -153, -152, -151, -149, -148, -146, -145, -144, -142, -141, -139, -138, -137, -135, -134, -132, -131, -130, -128, -127, -125, -124, -123, -121, -120, -118, -117, -115, -114, -113, -111, -110, -108, -107, -106, -104, -103, -101, -100, -99, -97, -96, -94, -93, -92, -90, -89, -87, -86, -85, -83, -82, -80, -79, -78, -76, -75, -73, -72, -71, -69, -68, -66, -65, -64, -62, -61, -59, -58, -57, -55, -54, -52, -51, -50, -48, -47, -45, -44, -43, -41, -40, -38, -37, -36, -34, -33, -31, -30, -29, -27, -26, -24, -23, -22, -20, -19, -17, -16, -15, -13, -12, -10, -9, -8, -6, -5, -3, -2, 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 16, 18, 19, 21, 22, 23, 25, 26, 28, 29, 30, 32, 33, 35, 36, 37, 39, 40, 42, 43, 44, 46, 47, 49, 50, 51, 53, 54, 56, 57, 58, 60, 61, 63, 64, 65, 67, 68, 70, 71, 72, 74, 75, 77, 78, 79, 81, 82, 84, 85, 86, 88, 89, 91, 92, 93, 95, 96, 98, 99, 100, 102, 103, 105, 106, 107, 109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 124, 126, 127, 129, 130, 131, 133, 134, 136, 137, 138, 140, 141, 143, 144, 145, 147, 148, 150, 151, 152, 154, 155, 157, 158, 159, 161, 162, 164, 165, 166, 168, 169, 171, 172, 173, 175, 176, 178 };

const int Table_fv2[256]={ -92, -91, -91, -90, -89, -88, -88, -87, -86, -86, -85, -84, -83, -83, -82, -81, -81, -80, -79, -78, -78, -77, -76, -76, -75, -74, -73, -73, -72, -71, -71, -70, -69, -68, -68, -67, -66, -66, -65, -64, -63, -63, -62, -61, -61, -60, -59, -58, -58, -57, -56, -56, -55, -54, -53, -53, -52, -51, -51, -50, -49, -48, -48, -47, -46, -46, -45, -44, -43, -43, -42, -41, -41, -40, -39, -38, -38, -37, -36, -36, -35, -34, -33, -33, -32, -31, -31, -30, -29, -28, -28, -27, -26, -26, -25, -24, -23, -23, -22, -21, -21, -20, -19, -18, -18, -17, -16, -16, -15, -14, -13, -13, -12, -11, -11, -10, -9, -8, -8, -7, -6, -6, -5, -4, -3, -3, -2, -1, 0, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24, 25, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 37, 38, 39, 40, 40, 41, 42, 42, 43, 44, 45, 45, 46, 47, 47, 48, 49, 50, 50, 51, 52, 52, 53, 54, 55, 55, 56, 57, 57, 58, 59, 60, 60, 61, 62, 62, 63, 64, 65, 65, 66, 67, 67, 68, 69, 70, 70, 71, 72, 72, 73, 74, 75, 75, 76, 77, 77, 78, 79, 80, 80, 81, 82, 82, 83, 84, 85, 85, 86, 87, 87, 88, 89, 90, 90 };

const int Table_fu1[256]={ -44, -44, -44, -43, -43, -43, -42, -42, -42, -41, -41, -41, -40, -40, -40, -39, -39, -39, -38, -38, -38, -37, -37, -37, -36, -36, -36, -35, -35, -35, -34, -34, -33, -33, -33, -32, -32, -32, -31, -31, -31, -30, -30, -30, -29, -29, -29, -28, -28, -28, -27, -27, -27, -26, -26, -26, -25, -25, -25, -24, -24, -24, -23, -23, -22, -22, -22, -21, -21, -21, -20, -20, -20, -19, -19, -19, -18, -18, -18, -17, -17, -17, -16, -16, -16, -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -11, -11, -11, -10, -10, -10, -9, -9, -9, -8, -8, -8, -7, -7, -7, -6, -6, -6, -5, -5, -5, -4, -4, -4, -3, -3, -3, -2, -2, -2, -1, -1, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43 };

const int Table_fu2[256]={ -227, -226, -224, -222, -220, -219, -217, -215, -213, -212, -210, -208, -206, -204, -203, -201, -199, -197, -196, -194, -192, -190, -188, -187, -185, -183, -181, -180, -178, -176, -174, -173, -171, -169, -167, -165, -164, -162, -160, -158, -157, -155, -153, -151, -149, -148, -146, -144, -142, -141, -139, -137, -135, -134, -132, -130, -128, -126, -125, -123, -121, -119, -118, -116, -114, -112, -110, -109, -107, -105, -103, -102, -100, -98, -96, -94, -93, -91, -89, -87, -86, -84, -82, -80, -79, -77, -75, -73, -71, -70, -68, -66, -64, -63, -61, -59, -57, -55, -54, -52, -50, -48, -47, -45, -43, -41, -40, -38, -36, -34, -32, -31, -29, -27, -25, -24, -22, -20, -18, -16, -15, -13, -11, -9, -8, -6, -4, -2, 0, 1, 3, 5, 7, 8, 10, 12, 14, 15, 17, 19, 21, 23, 24, 26, 28, 30, 31, 33, 35, 37, 39, 40, 42, 44, 46, 47, 49, 51, 53, 54, 56, 58, 60, 62, 63, 65, 67, 69, 70, 72, 74, 76, 78, 79, 81, 83, 85, 86, 88, 90, 92, 93, 95, 97, 99, 101, 102, 104, 106, 108, 109, 111, 113, 115, 117, 118, 120, 122, 124, 125, 127, 129, 131, 133, 134, 136, 138, 140, 141, 143, 145, 147, 148, 150, 152, 154, 156, 157, 159, 161, 163, 164, 166, 168, 170, 172, 173, 175, 177, 179, 180, 182, 184, 186, 187, 189, 191, 193, 195, 196, 198, 200, 202, 203, 205, 207, 209, 211, 212, 214, 216, 218, 219, 221, 223, 225 };

#define WIDTH 176

#define HEIGHT 144

#define PIXELSIZE WIDTH*HEIGHT

static void YV12_to_RGB24(unsigned char* pYV0, unsigned char* pYV1,

unsigned char* pYV2,unsigned char* pRGB24)

{

if(!pYV0 || !pRGB24)

return ;

const long nYLen = long(PIXELSIZE);

const int nHfWidth = (WIDTH>>1);

if(nYLen<1 || nHfWidth<1)

return ;

// Y data

unsigned char* yData = pYV0;

// v data

unsigned char* vData = pYV1;

// u data

unsigned char* uData = pYV2;

if(!uData || !vData)

return ;

int rgb[3];

int i, j, m, n, x, y, pu, pv, py, rdif, invgdif, bdif;

m = -WIDTH;

n = -nHfWidth;

bool addhalf = true;

for(y=0; y<HEIGHT;y++) {

m += WIDTH;

if( addhalf ){

n+=nHfWidth;

addhalf = false;

} else {

addhalf = true;

}

for(x=0; x<WIDTH;x++) {

i = m + x;

j = n + (x>>1);

py = yData[i];

// search tables to get rdif invgdif and bidif

rdif = Table_fv1[vData[j]]; // fv1

invgdif = Table_fu1[uData[j]] + Table_fv2[vData[j]]; // fu1+fv2

bdif = Table_fu2[uData[j]]; // fu2

rgb[0] = py+rdif; // R

rgb[1] = py-invgdif; // G

rgb[2] = py+bdif; // B

j = nYLen - WIDTH - m + x;

i = (j<<1) + j;

// copy this pixel to rgb data

for(j=0; j<3; j++)

{

if(rgb[j]>=0 && rgb[j]<=255){

pRGB24[i + j] = rgb[j];

}

else{

pRGB24[i + j] = (rgb[j] < 0)? 0 : 255;

}

}

}

}

}

算法二: cscc.lib

void YV12_to_RGB24(unsigned char *src0,unsigned char *src1,unsigned char *src2,unsigned char *dst_ori,int width,int height);

在很多进行yuv与rgb图像格式转换的程序中都使用了cscc.lib这个库.

算法三: asm

 

typedef UCHAR uint8_t;

typedef ULONGLONG uint64_t;

#define MAXIMUM_Y_WIDTH 1280

static uint64_t mmw_mult_Y = 0x2568256825682568;

static uint64_t mmw_mult_U_G = 0xf36ef36ef36ef36e;

static uint64_t mmw_mult_U_B = 0x40cf40cf40cf40cf;

static uint64_t mmw_mult_V_R = 0x3343334333433343;

static uint64_t mmw_mult_V_G = 0xe5e2e5e2e5e2e5e2;

static uint64_t mmb_0x10 = 0x1010101010101010;

static uint64_t mmw_0x0080 = 0x0080008000800080;

static uint64_t mmw_0x00ff = 0x00ff00ff00ff00ff;

static uint64_t mmw_cut_red = 0x7c007c007c007c00;

static uint64_t mmw_cut_green = 0x03e003e003e003e0;

static uint64_t mmw_cut_blue = 0x001f001f001f001f;

static void YUV_TO_RGB24(uint8_t *puc_y, int stride_y,

uint8_t *puc_u, uint8_t *puc_v, int stride_uv,

uint8_t *puc_out, int width_y, int height_y,int stride_out)

{

int y, horiz_count;

uint8_t *puc_out_remembered;

//int stride_out = width_y * 3;

if (height_y < 0) {

//we are flipping our output upside-down

height_y = -height_y;

puc_y += (height_y - 1) * stride_y ;

puc_u += (height_y/2 - 1) * stride_uv;

puc_v += (height_y/2 - 1) * stride_uv;

stride_y = -stride_y;

stride_uv = -stride_uv;

}

horiz_count = -(width_y >> 3);

for (y=0; y<height_y; y++) {

if (y == height_y-1) {

//this is the last output line - we need to be careful not to overrun the end of this line

uint8_t temp_buff[3*MAXIMUM_Y_WIDTH+1];

puc_out_remembered = puc_out;

puc_out = temp_buff; //write the RGB to a temporary store

}

_asm {

push eax

push ebx

push ecx

push edx

push edi

mov eax, puc_out

mov ebx, puc_y

mov ecx, puc_u

mov edx, puc_v

mov edi, horiz_count

horiz_loop:

movd mm2, [ecx]

pxor mm7, mm7

movd mm3, [edx]

punpcklbw mm2, mm7

movq mm0, [ebx]

punpcklbw mm3, mm7

movq mm1, mmw_0x00ff

psubusb mm0, mmb_0x10

psubw mm2, mmw_0x0080

pand mm1, mm0

psubw mm3, mmw_0x0080

psllw mm1, 3

psrlw mm0, 8

psllw mm2, 3

pmulhw mm1, mmw_mult_Y

psllw mm0, 3

psllw mm3, 3

movq mm5, mm3

pmulhw mm5, mmw_mult_V_R

movq mm4, mm2

pmulhw mm0, mmw_mult_Y

movq mm7, mm1

pmulhw mm2, mmw_mult_U_G

paddsw mm7, mm5

pmulhw mm3, mmw_mult_V_G

packuswb mm7, mm7

pmulhw mm4, mmw_mult_U_B

paddsw mm5, mm0

packuswb mm5, mm5

paddsw mm2, mm3

movq mm3, mm1

movq mm6, mm1

paddsw mm3, mm4

paddsw mm6, mm2

punpcklbw mm7, mm5

paddsw mm2, mm0

packuswb mm6, mm6

packuswb mm2, mm2

packuswb mm3, mm3

paddsw mm4, mm0

packuswb mm4, mm4

punpcklbw mm6, mm2

punpcklbw mm3, mm4

// 32-bit shuffle.

pxor mm0, mm0

movq mm1, mm6

punpcklbw mm1, mm0

movq mm0, mm3

punpcklbw mm0, mm7

movq mm2, mm0

punpcklbw mm0, mm1

punpckhbw mm2, mm1

// 24-bit shuffle and sav

movd [eax], mm0

psrlq mm0, 32

movd 3[eax], mm0

movd 6[eax], mm2

psrlq mm2, 32

movd 9[eax], mm2

// 32-bit shuffle.

pxor mm0, mm0

movq mm1, mm6

punpckhbw mm1, mm0

movq mm0, mm3

punpckhbw mm0, mm7

movq mm2, mm0

punpcklbw mm0, mm1

punpckhbw mm2, mm1

// 24-bit shuffle and sav

movd 12[eax], mm0

psrlq mm0, 32

movd 15[eax], mm0

add ebx, 8

movd 18[eax], mm2

psrlq mm2, 32

add ecx, 4

add edx, 4

movd 21[eax], mm2

add eax, 24

inc edi

jne horiz_loop

pop edi

pop edx

pop ecx

pop ebx

pop eax

emms

}

if (y == height_y-1) {

//last line of output - we have used the temp_buff and need to copy

int x = 3 * width_y; //interation counter

uint8_t *ps = puc_out; // source pointer (temporary line store)

uint8_t *pd = puc_out_remembered; // dest pointer

while (x--) *(pd++) = *(ps++); // copy the line

} puc_y += stride_y;

if (y%2) {

puc_u += stride_uv;

puc_v += stride_uv;

}

puc_out += stride_out;

}

}

算法四: 数组.

 

01
long int crv_tab[256];

02
long int cbu_tab[256];

03
long int cgu_tab[256];

04
long int cgv_tab[256];

05
long int tab_76309[256];

06
unsigned char clp[1024];

07

08
init_dither_tab()

09
{

10
long int crv,cbu,cgu,cgv;

11
int i,ind;

12

13
crv = 104597; cbu = 132201;

14
cgu = 25675; cgv = 53279;

15

16
for (i = 0; i < 256; i++) {

17
crv_tab[i] = (i-128) * crv;

18
cbu_tab[i] = (i-128) * cbu;

19
cgu_tab[i] = (i-128) * cgu;

20
cgv_tab[i] = (i-128) * cgv;

21
tab_76309[i] = 76309*(i-16);

22
}

23

24
for (i=0; i<384; i++)

25
clp[i] =0;

26
ind=384;

27
for (i=0;i<256; i++)

28
clp[ind++]=i;

29
ind=640;

30
for (i=0;i<384;i++)

31
clp[ind++]=255;

32
}

33

34
YUV2RGB420(unsigned char *src0,unsigned char *src1,unsigned char *src2,unsigned char *dst_ori,int width,int height)

35
{

36
int y1,y2,u,v;

37
unsigned char *py1,*py2;

38
int i,j, c1, c2, c3, c4;

39
unsigned char *d1, *d2;

40

41
py1=src0;

42
py2=py1+width;

43
d1=dst_ori;

44
d2=d1+3*width;

45
for (j = 0; j < height; j += 2) {

46
for (i = 0; i < width; i += 2) {

47

48
u = *src1++;

49
v = *src2++;

50

51
c1 = crv_tab[v];

52
c2 = cgu_tab[u];

53
c3 = cgv_tab[v];

54
c4 = cbu_tab[u];

55

56
//up-left

57
y1 = tab_76309[*py1++];

58
*d1++ = clp[384+((y1 + c1)>>16)];

59
*d1++ = clp[384+((y1 - c2 - c3)>>16)];

60
*d1++ = clp[384+((y1 + c4)>>16)];

61

62
//down-left

63
y2 = tab_76309[*py2++];

64
*d2++ = clp[384+((y2 + c1)>>16)];

65
*d2++ = clp[384+((y2 - c2 - c3)>>16)];

66
*d2++ = clp[384+((y2 + c4)>>16)];

67

68
//up-right

69
y1 = tab_76309[*py1++];

70
*d1++ = clp[384+((y1 + c1)>>16)];

71
*d1++ = clp[384+((y1 - c2 - c3)>>16)];

72
*d1++ = clp[384+((y1 + c4)>>16)];

73

74
//down-right

75
y2 = tab_76309[*py2++];

76
*d2++ = clp[384+((y2 + c1)>>16)];

77
*d2++ = clp[384+((y2 - c2 - c3)>>16)];

78
*d2++ = clp[384+((y2 + c4)>>16)];

79
}

80
d1 += 3*width;

81
d2 += 3*width;

82
py1+= width;

83
py2+= width;

84
}

85
}

算法五: ffmpeg 中的swscale函数

这几个算法都实验了一下, 前4种算法在低分辨率的情况下都可以正常显示, 在解1280*720的视频时雪花点点, 只能采用第五种算法,

第五种的话可能比较麻烦一点, 涉及开源的ffmpeg.

cscc.lib源文件和头文件声明下载看这里:https://files.cnblogs.com/doorsky/cscc.lib.rar

ffmepg源码实例看这里:https://files.cnblogs.com/doorsky/ffmepg_H.264.rar

SDLDemo下载看这里:https://files.cnblogs.com/doorsky/SDLDemo.rar

更多ffmepg的相关资料参阅: http://www.bairuitech.com/html/ruanjianxiazai/index.html

中华视频网论坛: http://bbs.chinavideo.org/index.php