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; } }
算法四: 数组.
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源文件和头文件声明下载看这里: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
安防 工控软件定制 QQ 2822八4536