您的位置:首页 > 其它

RGB YUV420 相互转换

2009-12-03 12:54 337 查看
如果用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<b)

{

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<l && l<=0.5f)

{

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<<SCALEBITS) + 0.5))

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]];

}

}

*/

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: