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源文件和头文件声明下载看这里: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