http://www.cnblogs.com/doorsky/archive/2011/01/02/1924253.html
算法一: 查表法
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; } } |
算法四: 數組.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
long int crv_tab[256]; long int cbu_tab[256]; long int cgu_tab[256]; long int cgv_tab[256]; long int tab_76309[256]; unsigned
char clp[1024]; init_dither_tab() { long int crv,cbu,cgu,cgv; int i,ind; crv
= 104597; cbu = 132201; cgu
= 25675; cgv = 53279; for (i
= 0; i < 256; i++) { crv_tab[i]
= (i-128) * crv; cbu_tab[i]
= (i-128) * cbu; cgu_tab[i]
= (i-128) * cgu; cgv_tab[i]
= (i-128) * cgv; tab_76309[i]
= 76309*(i-16); } for (i=0;
i<384; i++) clp[i]
=0; ind=384; for (i=0;i<256;
i++) clp[ind++]=i; ind=640; for (i=0;i<384;i++) clp[ind++]=255; } YUV2RGB420(unsigned
char *src0,unsigned
char *src1,unsigned
char *src2,unsigned
char *dst_ori, int width, int height) { int y1,y2,u,v;
unsigned
char *py1,*py2; int i,j,
c1, c2, c3, c4; unsigned
char *d1,
*d2; py1=src0; py2=py1+width; d1=dst_ori; d2=d1+3*width; for (j
= 0; j < height; j += 2) { for (i
= 0; i < width; i += 2) { u
= *src1++; v
= *src2++; c1
= crv_tab[v]; c2
= cgu_tab[u]; c3
= cgv_tab[v]; c4
= cbu_tab[u]; //up-left y1
= tab_76309[*py1++]; *d1++
= clp[384+((y1 + c1)>>16)]; *d1++
= clp[384+((y1 - c2 - c3)>>16)]; *d1++
= clp[384+((y1 + c4)>>16)]; //down-left y2
= tab_76309[*py2++]; *d2++
= clp[384+((y2 + c1)>>16)]; *d2++
= clp[384+((y2 - c2 - c3)>>16)]; *d2++
= clp[384+((y2 + c4)>>16)]; //up-right y1
= tab_76309[*py1++]; *d1++
= clp[384+((y1 + c1)>>16)]; *d1++
= clp[384+((y1 - c2 - c3)>>16)]; *d1++
= clp[384+((y1 + c4)>>16)]; //down-right y2
= tab_76309[*py2++]; *d2++
= clp[384+((y2 + c1)>>16)]; *d2++
= clp[384+((y2 - c2 - c3)>>16)]; *d2++
= clp[384+((y2 + c4)>>16)]; } d1
+= 3*width; d2
+= 3*width; py1+=
width; py2+=
width; } } |
算法五: ffmpeg 中的swscale函數
這幾個算法都實驗了一下, 前4種算法在低分辨率的情況下都可以正常顯示, 在解1280*720的視頻時雪花點點, 只能採用第五種算法,
第五種的話可能比較麻煩一點, 涉及開源的ffmpeg.
cscc.lib源文件和頭文件聲明下載看這裏:http://files.cnblogs.com/doorsky/cscc.lib.rar
ffmepg源碼實例看這裏:http://files.cnblogs.com/doorsky/ffmepg_H.264.rar
SDLDemo下載看這裏:http://files.cnblogs.com/doorsky/SDLDemo.rar
更多ffmepg的相關資料參閱: http://www.bairuitech.com/html/ruanjianxiazai/index.html
中華視頻網論壇: http://bbs.chinavideo.org/index.php