zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    CF353D Queue(结论)
    CF1147C Thanos Nim(博弈论、结论推导)
    牛客:CBX and children(平衡树+二分+贪心)
    牛客:Gambling Monster(权值线段树+离散化+离线)
    剑指49.把字符串转换成整数
    剑指48.不用加减乘除做加法
    剑指47.求1+2+3+...+n
    剑指46.孩子们的游戏(圆圈中最后剩下的数字)
    剑指45.扑克牌顺子
    剑指44.翻转单词顺序
  • 原文地址:https://www.cnblogs.com/doorsky/p/1924253.html
Copyright © 2011-2022 走看看