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

 

posted @ 2011-01-02 21:23  小阿枫  阅读(7977)  评论(1编辑  收藏  举报