RGB YUV420 相互转换

如果用ffmpeg的话就不要用下面的函数了,效率实在是太.......

直接用ffmpeg的sws_scale 很快的

 

#define min3v(v1, v2, v3) ((v1)>(v2)? ((v2)>(v3)?(v3):(v2)):((v1)>(v3)?(v3):(v2)))
#define max3v(v1, v2, v3) ((v1)<(v2)? ((v2)<(v3)?(v3):(v2)):((v1)<(v3)?(v3):(v1)))
typedef struct
{
    BYTE red; // [0,255]
    BYTE green; // [0,255]
    BYTE blue; // [0,255]
   
}COLOR_RGB;

typedef struct
{
    float hue; // [0,360]
    float saturation; // [0,100]
    float luminance; // [0,100]
}COLOR_HSL;

// Converts RGB to HSL

static void RGBtoHSL(/*[in]*/const COLOR_RGB *rgb, /*[out]*/COLOR_HSL *hsl)
{
    float h=0, s=0, l=0;
    // normalizes red-green-blue values
    float r = rgb->red/255.f;
    float g = rgb->green/255.f;
    float b = rgb->blue/255.f;
    float maxVal = max3v(r, g, b);
    float minVal = min3v(r, g, b);
   
   
    // hue
   
    if(maxVal == minVal)
    {
        h = 0; // undefined
    }
   
    else if(maxVal==r && g>=b)
    {
        h = 60.0f*(g-b)/(maxVal-minVal);
    }
   
    else if(maxVal==r && g     {
        h = 60.0f*(g-b)/(maxVal-minVal) + 360.0f;
    }
   
    else if(maxVal==g)
    {
        h = 60.0f*(b-r)/(maxVal-minVal) + 120.0f;
    }
    else if(maxVal==b)
    {
        h = 60.0f*(r-g)/(maxVal-minVal) + 240.0f;
    }
   
    // luminance
   
    l = (maxVal+minVal)/2.0f;
    // saturation
   
    if(l == 0 || maxVal == minVal)
    {
        s = 0;
    }
   
    else if(0     {
        s = (maxVal-minVal)/(maxVal+minVal);
    }
    else if(l>0.5f)
    {
        s = (maxVal-minVal)/(2 - (maxVal+minVal)); //(maxVal-minVal > 0)?
    }
    hsl->hue = (h>360)? 360 : ((h<0)?0:h);
    hsl->saturation = ((s>1)? 1 : ((s<0)?0:s))*100;
    hsl->luminance = ((l>1)? 1 : ((l<0)?0:l))*100;
}
// Converts HSL to RGB

static void HSLtoRGB(const COLOR_HSL *hsl, COLOR_RGB *rgb)
{
    float h = hsl->hue; // h must be [0, 360]
    float s = hsl->saturation/100.f; // s must be [0, 1]
    float l = hsl->luminance/100.f; // l must be [0, 1]
    float R, G, B;
   
    if(hsl->saturation == 0)
    {
        // achromatic color (gray scale)
        R = G = B = l*255.f;
    }
    else
    {
        float q = (l<0.5f)?(l * (1.0f+s)):(l+s - (l*s));
        float p = (2.0f * l) - q;
        float Hk = h/360.0f;
        float T[3];
        T[0] = Hk + 0.3333333f; // Tr 0.3333333f=1.0/3.0
        T[1] = Hk; // Tb
        T[2] = Hk - 0.3333333f; // Tg
       
        for(int i=0; i<3; i++)
        {
            if(T[i] < 0) T[i] += 1.0f;
            if(T[i] > 1) T[i] -= 1.0f;
           
            if((T[i]*6) < 1)
            {
                T[i] = p + ((q-p)*6.0f*T[i]);
            }
            else if((T[i]*2.0f) < 1) //(1.0/6.0)<=T[i] && T[i]<0.5
            {
                T[i] = q;
            }
            else if((T[i]*3.0f) < 2) // 0.5<=T[i] && T[i]<(2.0/3.0)
            {
                T[i] = p + (q-p) * ((2.0f/3.0f) - T[i]) * 6.0f;
            }
            else T[i] = p;
        }
        R = T[0]*255.0f;
        G = T[1]*255.0f;
        B = T[2]*255.0f;
       
    }
    rgb->red = (BYTE)((R>255)? 255 : ((R<0)?0 : R));
    rgb->green = (BYTE)((G>255)? 255 : ((G<0)?0 : G));
    rgb->blue = (BYTE)((B>255)? 255 : ((B<0)?0 : B));
   
}



#define SCALEBITS            8
#define ONE_HALF             (1 << (SCALEBITS - 1))
#define FIX(x)               ((int) ((x) * (1L< typedef unsigned char        uint8_t;
void rgb24_to_yuv420p(uint8_t *lum, uint8_t *cb, uint8_t *cr, uint8_t *src, int width, int height)
{
    int wrap, wrap3, x, y;
    int r, g, b, r1, g1, b1;
    uint8_t *p;
    wrap = width;
    wrap3 = width * 3;
    p = src;
    for (y = 0; y < height; y += 2)
    {
        for (x = 0; x < width; x += 2)
        {
            r = p[0];
            g = p[1];
            b = p[2];
            r1 = r;
            g1 = g;
            b1 = b;
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
            r = p[3];
            g = p[4];
            b = p[5];
            r1 += r;
            g1 += g;
            b1 += b;
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
            p += wrap3;
            lum += wrap;
            r = p[0];
            g = p[1];
            b = p[2];
            r1 += r;
            g1 += g;
            b1 += b;
            lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
            r = p[3];
            g = p[4];
            b = p[5];
            r1 += r;
            g1 += g;
            b1 += b;
            lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
           
            cb[0] = (((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
                FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128);
            cr[0] = (((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
                FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128);
            cb++;
            cr++;
            p += -wrap3+2 * 3;
            lum += -wrap + 2;
        }
        p += wrap3;
        lum += wrap;
    }
}

inline byte ADJUST(double tmp)
{
    return (byte)((tmp >= 0 && tmp <= 255)?tmp:(tmp < 0 ? 0 : 255));
}

void YUV420P_TO_RGB24(unsigned char* yuv_src,unsigned char* rgb_dst,int nWidth,int nHeight)
{
    unsigned char  tmpbuf[CAM_WIDTH*CAM_HEIGHT*3];
    byte Y,U,V,R,G,B;
    byte* y_planar,*u_planar,*v_planar;
    int C,D,E;
    int rgb_width , u_width;
    rgb_width = nWidth * 3;
    u_width = (nWidth >> 1);
    int ypSize = nWidth * nHeight;
    int upSize = (ypSize>>2);
    int offSet = 0;
   
    y_planar = yuv_src;
    u_planar = yuv_src + ypSize;
    v_planar = u_planar + upSize;

    /*
    int ns_r[256],ns_g[256],ns_b[256];
    memset(ns_r,0,sizeof(ns_r));
    memset(ns_g,0,sizeof(ns_r));
    memset(ns_b,0,sizeof(ns_r));

    double ps_r[256],ps_g[256],ps_b[256];
    double temp_r[256],temp_g[256],temp_b[256];
*/

    for(int i = 0; i < nHeight; i++)
    {
        for(int j = 0; j < nWidth; j ++)
        {
            // Get the Y value from the y planar
            Y = *(y_planar + nWidth * i + j);
            // Get the V value from the u planar
            offSet = (i>>1) * (u_width) + (j>>1);
            V = *(u_planar + offSet);
            // Get the U value from the v planar
            U = *(v_planar + offSet);
           
            // Cacular the R,G,B values
            /*R = ADJUST((Y + (1.4075 * (V - 128))));
            G = ADJUST((Y - (0.3455 * (U - 128) - 0.7169 * (V - 128))));
            B = ADJUST((Y + (1.7790 * (U - 128))));*/
           
            // The following formulas are from MicroSoft' MSDN
            // the result is better than the former
            //
            C = Y - 16;
            D = U - 128;
            E = V - 128;
           
            R = ADJUST(( 298 * C          + 409 * E + 128) >> 8);
            G = ADJUST(( 298 * C - 100 * D - 208 * E + 128) >> 8);
            B = ADJUST(( 298 * C + 516 * D          + 128) >> 8);
            R  =   ((R   -   128)   *   .6   +   128  )>255?255:(R   -   128)   *   .6   +   128; 
            G  =   ((G   -   128)   *   .6  +   128  )>255?255:(G   -   128)   *   .6   +   128; 
            B  =   ((B   -   128)   *   .6   +   128  )>255?255:(B   -   128)   *   .6  +   128; 
            //COLOR_RGB rgb={R,G,B};
            //COLOR_HSL hsl;
            //RGBtoHSL((const COLOR_RGB *)&rgb,&hsl);
            //hsl.saturation =hsl.saturation>90?100:hsl.saturation+10;
            //hsl.luminance=hsl.luminance>90?100:hsl.luminance+10;
            //HSLtoRGB((const COLOR_HSL *)&hsl,&rgb);
            // Set the values

            //ns_r为R分量的统计记数
//            ns_r[R]++;
            //ns_g为G分量的统计记数
//            ns_g[G]++;
            //ns_b为B分量的统计记数
//            ns_b[B]++;
            offSet = rgb_width * i + j * 3;
            //tmpbuf[offSet] = R;
            //tmpbuf[offSet + 1] = G;
            //tmpbuf[offSet + 2] = B;

            rgb_dst[offSet] = B;
            rgb_dst[offSet + 1] = G;
            rgb_dst[offSet + 2] = R;
        }
    }
    /*
    for(i=0;i<256;i++) //计算R、G、B三分量的直方图分布
    {
        //ps_r[i]为R分量中i灰度级出现的概率
        ps_r[i]=ns_r[i]/((nWidth*nHeight)/1.0f);
        //ps_b[i]为G分量中i灰度级出现的概率
        ps_g[i]=ns_g[i]/((nWidth*nHeight)/1.0f);
        //ps_b[i]为B分量中i灰度级出现的概率
        ps_b[i]=ns_b[i]/((nWidth*nHeight)/1.0f);
    }
    for(i=0;i<256;i++)
    {
        //计算累计直方图分布
        temp_r[i]=(i>0?temp_r[i-1]:0)+ps_r[i];
        temp_g[i]=(i>0?temp_g[i-1]:0)+ps_g[i];
        temp_b[i]=(i>0?temp_b[i-1]:0)+ps_b[i];
        //累计分布取整,ns_r[]、ns_g[]、ns_b[]保存有计算出来的灰度映射关系
        ns_r[i]=(int)(255.0f*temp_r[i]+0.5f);
        ns_g[i]=(int)(255.0f*temp_g[i]+0.5f);
        ns_b[i]=(int)(255.0f*temp_b[i]+0.5f);
    }
    for(i = 0; i < nHeight; i++)
    {
        for(int j = 0; j < nWidth; j ++)
        {
            offSet = rgb_width * i + j * 3;
            rgb_dst[offSet]=ns_r[tmpbuf[offSet]] ;
            rgb_dst[offSet+ 1]=ns_r[tmpbuf[offSet + 1] ];
            rgb_dst[offSet+ 2]=ns_r[tmpbuf[offSet + 2]];
        }
    }
 */
}

你可能感兴趣的:(RGB YUV420 相互转换)