YUV420_to_RGB24 算法


 转自: 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

 

欢迎试用,升级现有产品 http://www.jianjiesoft.com 网络矩阵/视频监控平台

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值