您的位置:首页 > 其它

YUV420_to_RGB24 算法

2011-01-02 21:23 316 查看
算法一: 查表法

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;
}
}


算法四: 数组.

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: