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<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]];
}
}
*/
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值