TexConv/YUV.cpp
2020-01-08 15:54:58 +08:00

135 lines
2.7 KiB
C++

#include<hgl/type/DataType.h>
#include<string.h>
using namespace hgl;
namespace hgl
{
const double clamp_u=0.436*255.0;
const double clamp_v=0.615*255.0;
void RGB2YUV(uint8 *y,uint8 *u,uint8 *v,const uint8 *rgb,const uint count)
{
uint8 r,g,b;
for(uint i=0;i<count;i++)
{
r=*rgb++;
g=*rgb++;
b=*rgb++;
*y++= 0.299 * r + 0.587 * g + 0.114 * b;
*u++=(clamp_u - 0.14713 * r - 0.28886 * g + 0.436 * b) / 0.872;
*v++=(clamp_v + 0.615 * r - 0.51499 * g - 0.10001 * b) / 1.230;
}
}
}//namespace hgl
namespace hgl
{
static bool yuv2rgb=false;
static int sAdjCrr[256];
static int sAdjCrg[256];
static int sAdjCbg[256];
static int sAdjCbb[256];
static int sAdjY[256];
static unsigned char sClampBuff[1024];
static unsigned char *sClamp = sClampBuff + 384;
static unsigned char YV_R[256][256];
static unsigned char YU_B[256][256];
inline int getMin(int a, int b)
{
return a>b ? b : a;
}
inline int getMax(int a, int b)
{
return a>b ? a : b;
}
inline int mClamp(int val, int low, int high)
{
return getMax(getMin(val, high), low);
}
void InitYUV2RGBDecode()
{
int i;
for(i = 0; i < 256; i++)
{
sAdjCrr[i] = (409 * (i - 128) + 128) >> 8;
sAdjCrg[i] = (208 * (i - 128) + 128) >> 8;
sAdjCbg[i] = (100 * (i - 128) + 128) >> 8;
sAdjCbb[i] = (516 * (i - 128) + 128) >> 8;
sAdjY[i] = (298 * (i - 16) ) >> 8;
}
for(i = -384; i < 640; i++)
sClamp[i] = mClamp(i, 0, 0xFF);
for(int v=0;v<256;v++)
for(int y=0;y<256;y++)
{
YV_R[v][y]=sClamp[sAdjY[y]+sAdjCrr[v]];
YU_B[v][y]=sClamp[sAdjY[y]+sAdjCbb[v]];
}
yuv2rgb=true;
}
void YUV2RGB(uint8 *rgb,const uint8 *y,const uint8 *u,const uint8 *v,const uint w,const uint h)
{
const uint line_gap=w*3;
const uint y_stride=w;
const uint uv_stride=w>>1;
const uint8 *pY0, *pY1, *pU, *pV;
for(int _y = 0; _y < h; _y += 2)
{
pY0 = y + _y * y_stride;
pY1 = y + (_y | 1)* y_stride;
pU = u + (( _y * uv_stride) >> 1);
pV = v + (( _y * uv_stride) >> 1);
unsigned __int8 *dst0=rgb;
unsigned __int8 *dst1=rgb+line_gap;
for(int _x = 0; _x < w; _x += 2)
{
const int G = sAdjCrg[*pV] + sAdjCbg[*pU];
const uint8 *r =YV_R[*pV++];
const uint8 *b =YU_B[*pU++];
// pixel 0x0
*dst0++ = r[*pY0];
*dst0++ = sClamp[sAdjY[*pY0] - G];
*dst0++ = b[*pY0++];
// pixel 1x0
*dst0++ = r[*pY0];
*dst0++ = sClamp[sAdjY[*pY0] - G];
*dst0++ = b[*pY0++];
// pixel 0x1
*dst1++ = r[*pY1];
*dst1++ = sClamp[sAdjY[*pY1] - G];
*dst1++ = b[*pY1++];
// pixel 1x1
*dst1++ = r[*pY1];
*dst1++ = sClamp[sAdjY[*pY1] - G];
*dst1++ = b[*pY1++];
}
rgb+=line_gap*2;
}
}
}//namespace hgl