📄 blit_soft.c
字号:
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m + 256;
v *= m;
if (v<0)
v -= 128;
else
v += 128;
v >>= 8;
if (r) *r = v;
return (int)v;
}
static NOINLINE int CAdd(blit_soft* p, int64_t* r, int64_t v, int v0, int vUV)
{
int m;
m = p->FX.Saturation;
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m+256;
v += ((256 - m) * vUV) >> 1;
m = p->FX.Contrast;
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m + 256;
v += ((256 - m)*(v0 - v)) >> 8;
if (r) *r = v;
return (int)v;
}
static INLINE bool_t InRange32(int64_t v)
{
return v >= -MAX_INT && v <= MAX_INT;
}
static INLINE uint8_t RotateRight8(int v,int Bits)
{
Bits &= 7;
return (uint8_t)(((v >> Bits) & ((1 << (8-Bits))-1)) | (v << (8-Bits)));
}
void CalcPalYUVLookUp(blit_soft* p)
{
p->LookUp_Size = 256+4+256+256;
p->LookUp_Data = malloc(p->LookUp_Size);
if (p->LookUp_Data)
{
int v,i,n = 1<<p->Src.BitCount;
rgb* Pal = p->Src.Palette;
uint8_t* LookUp = p->LookUp_Data;
for (i=0;i<n;++i)
{
v = (2105*Pal[i].c.r + 4128*Pal[i].c.g + 802*Pal[i].c.b)/0x2000 + 16 + p->FX.Brightness;
LookUp[i] = (uint8_t)SAT(v);
v = (-1212*Pal[i].c.r -2384*Pal[i].c.g + 3596*Pal[i].c.b)/0x2000 + 128;
LookUp[i+256+4] = (uint8_t)SAT(v);
v = (3596*Pal[i].c.r -3015*Pal[i].c.g -582*Pal[i].c.b)/0x2000 + 128;
LookUp[i+256+4+256] = (uint8_t)SAT(v);
}
}
}
void CalcPalRGBLookUp(blit_soft* p)
{
int i,n = 1<<p->Src.BitCount;
int w = p->Dst.BitCount>>3;
if (w<2 || w>4) return;
if (w==3) w=4;
p->LookUp_Size = w*n;
p->LookUp_Data = malloc(p->LookUp_Size);
if (p->LookUp_Data)
{
uint16_t* Pal = p->LookUp_Data;
for (i=0;i<n;++i)
{
uint32_t c = RGBToFormat(p->Src.Palette[i].v,&p->Dst);
if (w==2)
*(Pal++) = (uint16_t)c;
else
{
*(uint32_t*)Pal = c;
Pal += 2;
}
}
}
}
void CalcYUVLookUp(blit_soft* p)
{
if (p->FX.Saturation || p->FX.Contrast || (p->FX.Flags & BLITFX_DITHER) ||
p->FX.RGBAdjust[0] || p->FX.RGBAdjust[1] || p->FX.RGBAdjust[2])
{
p->LookUp_Size = 3*256+4;
p->LookUp_Data = malloc(p->LookUp_Size);
if (p->LookUp_Data)
{
int Ofs = (p->FX.Flags & BLITFX_DITHER)?-2:0;
int n;
uint8_t* i=p->LookUp_Data;
for (n=0;n<256+4;++n,++i)
{
int y = CMul(p,NULL,n+Ofs+p->FX.Brightness+p->FX.RGBAdjust[1]-128,0)+128;
*i = (uint8_t)SAT(y);
}
for (n=0;n<256;++n,++i)
{
int u = CMul(p,NULL,n-128-p->FX.RGBAdjust[1]+p->FX.RGBAdjust[2],1)+128;
*i = (uint8_t)SAT(u);
}
for (n=0;n<256;++n,++i)
{
int v = CMul(p,NULL,n-128-p->FX.RGBAdjust[1]+p->FX.RGBAdjust[0],1)+128;
*i = (uint8_t)SAT(v);
}
}
}
}
void CalcLookUp(blit_soft* p, bool_t Dither)
{
#if defined(ARM)
const int Safe = 512;
// 4*256:Y + (256+Safe*2)*n:SAT + 4*256:U + 4*256:V
int SatOfsR = 4*256+Safe;
int SatOfsG = 4*256+Safe;
int SatOfsB = 4*256+Safe;
p->LookUp_Size = 4*256*3 + (256+Safe*2);
if (Dither)
{
if (p->DstSize[1] == p->DstSize[0])
SatOfsG = SatOfsR;
else
{
p->LookUp_Size += (256+Safe*2);
SatOfsG = SatOfsR + (256+Safe*2);
}
if (p->DstSize[2] == p->DstSize[0])
SatOfsB = SatOfsR;
else
if (p->DstSize[2] == p->DstSize[1])
SatOfsB = SatOfsG;
else
{
p->LookUp_Size += (256+Safe*2);
SatOfsB = SatOfsG + (256+Safe*2);
}
}
p->LookUp_U = (p->LookUp_Size - 4*256*2) >> 2;
p->LookUp_V = (p->LookUp_Size - 4*256) >> 2;
p->LookUp_Data = malloc(p->LookUp_Size);
if (p->LookUp_Data)
{
int v;
int32_t* YMul = (int32_t*)p->LookUp_Data;
int32_t* UMul = (int32_t*)p->LookUp_Data + p->LookUp_U;
int32_t* VMul = (int32_t*)p->LookUp_Data + p->LookUp_V;
uint8_t* SatR = (uint8_t*)p->LookUp_Data + SatOfsR;
uint8_t* SatG = (uint8_t*)p->LookUp_Data + SatOfsG;
uint8_t* SatB = (uint8_t*)p->LookUp_Data + SatOfsB;
memset(p->LookUp_Data,0,p->LookUp_Size);
for (v=0;v<256;++v)
{
*YMul = (p->_YMul * v) << LOOKUP_FIX;
*UMul = (((p->_BUMul * v + p->_BAdd + (SatOfsB << 16)) << LOOKUP_FIX) & 0xFFFF0000) |
(((p->_GUMul * v) >> (16-LOOKUP_FIX)) & 0xFFFF); //BUMul | GUMul
*VMul = (((p->_RVMul * v + p->_RAdd + (SatOfsR << 16)) << LOOKUP_FIX) & 0xFFFF0000) |
(((p->_GVMul * v + p->_GAdd + (SatOfsG << 16)) >> (16-LOOKUP_FIX)) & 0xFFFF); //BUMul | GUMul
++YMul;
++UMul;
++VMul;
}
if (Dither)
{
for (v=-Safe;v<256+Safe;++v)
{
SatR[v] = RotateRight8(SAT(v),8-p->DstSize[0]);
SatG[v] = RotateRight8(SAT(v),8-p->DstSize[1]);
SatB[v] = RotateRight8(SAT(v),8-p->DstSize[2]);
}
}
else
{
for (v=-Safe;v<256+Safe;++v)
SatR[v] = (uint8_t)SAT(v);
}
}
#elif defined(MIPS)
const int Safe = 256;
// 256:Y + (128+Safe*2)*n:SAT + 8*256:U + 8*256:V
int SatOfsR = 256+Safe;
int SatOfsG = 256+Safe;
int SatOfsB = 256+Safe;
p->LookUp_Size = 256+8*256*2 + (128+Safe*2);
if (p->DstSize[1] == p->DstSize[0])
SatOfsG = SatOfsR;
else
{
p->LookUp_Size += (128+Safe*2);
SatOfsG = SatOfsR + (128+Safe*2);
}
if (p->DstSize[2] == p->DstSize[0])
SatOfsB = SatOfsR;
else
if (p->DstSize[2] == p->DstSize[1])
SatOfsB = SatOfsG;
else
{
p->LookUp_Size += (128+Safe*2);
SatOfsB = SatOfsG + (128+Safe*2);
}
p->LookUp_U = p->LookUp_Size - 8*256*2;
p->LookUp_V = p->LookUp_Size - 8*256;
p->LookUp_Data = malloc(p->LookUp_Size);
if (p->LookUp_Data)
{
int v;
uint8_t* YMul = (uint8_t*)p->LookUp_Data;
uint8_t** UMul = (uint8_t**)((uint8_t*)p->LookUp_Data + p->LookUp_U);
uint8_t** VMul = (uint8_t**)((uint8_t*)p->LookUp_Data + p->LookUp_V);
uint8_t* SatR = (uint8_t*)p->LookUp_Data + SatOfsR;
uint8_t* SatG = (uint8_t*)p->LookUp_Data + SatOfsG;
uint8_t* SatB = (uint8_t*)p->LookUp_Data + SatOfsB;
memset(p->LookUp_Data,0,p->LookUp_Size);
for (v=0;v<256;++v)
{
*YMul = (uint8_t)((p->_YMul * v) >> 17);
UMul[0] = SatB + ((p->_BUMul * v + p->_BAdd) >> 17);
*(int*)&UMul[1] = (p->_GUMul * v) >> 17;
VMul[0] = SatR + ((p->_RVMul * v + p->_RAdd) >> 17);
VMul[1] = SatG + ((p->_GVMul * v + p->_GAdd) >> 17);
++YMul;
UMul+=2;
VMul+=2;
}
for (v=-Safe;v<128+Safe;++v)
{
SatR[v] = (uint8_t)(SAT(v*2) >> (8-p->DstSize[0]));
SatG[v] = (uint8_t)(SAT(v*2) >> (8-p->DstSize[1]));
SatB[v] = (uint8_t)(SAT(v*2) >> (8-p->DstSize[2]));
}
}
#elif defined(SH3)
const int Safe = 256;
//LookUp_Data:
// [128..255|0..127]Y + 384 empty + 4*[128..255|0..127]U + 4*[128..255|0..127]V + (128+Safe*2)*n:SAT
int SatOfsR = 256+384+4*256*2+Safe;
int SatOfsG = 256+384+4*256*2+Safe;
int SatOfsB = 256+384+4*256*2+Safe;
p->LookUp_Size = 256+384+4*256*2 + (128+Safe*2);
if (p->DstSize[1] == p->DstSize[0])
SatOfsG = SatOfsR;
else
{
p->LookUp_Size += (128+Safe*2);
SatOfsG = SatOfsR + (128+Safe*2);
}
if (p->DstSize[2] == p->DstSize[0])
SatOfsB = SatOfsR;
else
if (p->DstSize[2] == p->DstSize[1])
SatOfsB = SatOfsG;
else
{
p->LookUp_Size += (128+Safe*2);
SatOfsB = SatOfsG + (128+Safe*2);
}
p->LookUp_U = 128 + 384 + 4*128;
p->LookUp_V = 128 + 384 + 4*256 + 4*128;
p->LookUp_Data = malloc(p->LookUp_Size + Safe*2); //additional safe
if (p->LookUp_Data)
{
int v;
int8_t* YMul = (int8_t*)p->LookUp_Data;
int16_t* UMul = (int16_t*)((uint8_t*)p->LookUp_Data + 256 + 384);
int16_t* VMul = (int16_t*)((uint8_t*)p->LookUp_Data + 256 + 384 + 4*256);
int8_t* SatR = (int8_t*)p->LookUp_Data + SatOfsR;
int8_t* SatG = (int8_t*)p->LookUp_Data + SatOfsG;
int8_t* SatB = (int8_t*)p->LookUp_Data + SatOfsB;
memset(p->LookUp_Data,0,p->LookUp_Size + Safe*2);
for (v=0;v<256;++v)
{
*YMul = (int8_t)(((p->_YMul * ((v+128)&255)) >> 17)-128);
UMul[0] = (int16_t)(SatOfsB + ((p->_BUMul * ((v+128)&255) + p->_BAdd) >> 17));
UMul[1] = (int16_t)((p->_GUMul * ((v+128)&255)) >> 17);
VMul[0] = (int16_t)(SatOfsR + ((p->_RVMul * ((v+128)&255) + p->_RAdd) >> 17));
VMul[1] = (int16_t)(SatOfsG + ((p->_GVMul * ((v+128)&255) + p->_GAdd) >> 17));
++YMul;
UMul+=2;
VMul+=2;
}
for (v=-Safe;v<128+Safe;++v)
{
SatR[v] = (int8_t)(SAT(v*2) >> (8-p->DstSize[0]));
SatG[v] = (int8_t)(SAT(v*2) >> (8-p->DstSize[1]));
SatB[v] = (int8_t)(SAT(v*2) >> (8-p->DstSize[2]));
}
}
#endif
}
void CalcColor(blit_soft* p)
{
#ifdef ARM
if (p->QAdd)
{
//saturation: signed 32bit / 3 (qdadd will triple)
int64_t YMul;
int64_t RVMul;
int64_t RAdd;
int64_t GUMul;
int64_t GVMul;
int64_t GAdd;
int64_t BUMul;
int64_t BAdd;
CMul(p,&YMul,0x63C000,0);
CMul(p,&RVMul,0x88B2AA,1);
CAdd(p,&RAdd,(p->FX.Brightness+p->FX.RGBAdjust[0])*0x63C000 - (int64_t)0x75400000,0x2AAAAAAA,0x88B2AA);
CMul(p,&GUMul,-0x218555,1);
CMul(p,&GVMul,-0x45A555,1);
CAdd(p,&GAdd,(p->FX.Brightness+p->FX.RGBAdjust[1])*0x63C000 + (int64_t)0x02AEAAAA,0x2AAAAAAA,-0x218555-0x45A555);
CMul(p,&BUMul,0xACD2AA,1);
CAdd(p,&BAdd,(p->FX.Brightness+p->FX.RGBAdjust[2])*0x63C000 - (int64_t)0x87500000,0x2AAAAAAA,0xACD2AA);
if (InRange32(YMul*0xF0) &&
InRange32(RVMul*0x10+RAdd) &&
InRange32(RVMul*0xF0+RAdd) &&
InRange32((GVMul+GUMul)*0x10+GAdd) &&
InRange32((GVMul+GUMul)*0xF0+GAdd) &&
InRange32(BUMul*0x10+BAdd) &&
InRange32(BUMul*0xF0+BAdd))
{
p->_YMul = (int)YMul;
p->_RVMul = (int)RVMul;
p->_RAdd = (int)RAdd;
p->_GUMul = (int)GUMul;
p->_GVMul = (int)GVMul;
p->_GAdd = (int)GAdd;
p->_BUMul = (int)BUMul;
p->_BAdd = (int)BAdd;
}
else
p->QAdd = 0;
}
if (!p->QAdd)
#endif
{
//saturation: unsigned 24bit
p->_YMul = CMul(p,NULL,0x12B40,0);
p->_RVMul = CMul(p,NULL,0x19A18,1);
p->_RAdd = CAdd(p,NULL,(p->FX.Brightness+p->FX.RGBAdjust[0])*0x12B40 - 0x0DFC000,0x800000,0x19A18);
p->_GUMul = CMul(p,NULL,-0x06490,1);
p->_GVMul = CMul(p,NULL,-0x0D0F0,1);
p->_GAdd = CAdd(p,NULL,(p->FX.Brightness+p->FX.RGBAdjust[1])*0x12B40 + 0x0880C00,0x800000,-0x06490-0x0D0F0);
p->_BUMul = CMul(p,NULL,0x20678,1);
p->_BAdd = CAdd(p,NULL,(p->FX.Brightness+p->FX.RGBAdjust[2])*0x12B40 - 0x115F000,0x800000,0x20678);
}
}
#if defined(_M_IX86) && !defined(TARGET_SYMBIAN)
static void ColMMX(blit_soft* p, int i, int ofs)
{
int mul = 2048;
int m;
int o = 128;
if (i>0)
{
m = p->FX.Saturation;
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m+256;
mul = (mul*m+128) >> 8;
ofs += 128 - (m>>1);
o = (o*m+128)>>8;
}
m = p->FX.Contrast;
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m + 256;
mul = (mul*m+128)>>8;
ofs += o - ((m*o)>>8);
if ((p->Src.Flags & PF_YUV_PC) && !(p->Dst.Flags & PF_YUV_PC))
{
if (i==0) //y [0..255]->[16..235]
{
mul = (mul*219+127)/255;
ofs = (ofs*219+127)/255+16;
}
else //uv [0..255]->[16..240]
{
mul = (mul*224+127)/255;
ofs = (ofs*224+127)/255+16;
}
}
else
if (!(p->Src.Flags & PF_YUV_PC) && (p->Dst.Flags & PF_YUV_PC))
{
if (i==0) //y [16..235]->[0..255]
{
mul = (mul*255+109)/219;
ofs = ((ofs-16)*255+109)/219;
}
else //uv [16..240]->[0..255]
{
mul = (mul*255+112)/224;
ofs = ((ofs-16)*255+112)/224;
}
}
if (mul<-32768) mul=32768;
if (mul>32767) mul=32767;
p->Col[i][0][3] = p->Col[i][0][2] = p->Col[i][0][1] = p->Col[i][0][0] = (int16_t)mul;
p->Col[i][1][3] = p->Col[i][1][2] = p->Col[i][1][1] = p->Col[i][1][0] = (int16_t)ofs;
}
static int16_t MulMMX(blit_soft* p, int i, int mul)
{
int m;
if (i>0)
{
m = p->FX.Saturation;
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m+256;
mul = (mul*m+128) >> 8;
}
m = p->FX.Contrast;
if (m<0) m >>= 1; // adjust negtive interval: -128..0 -> -64..0
m = 4*m + 256;
mul = (mul*m+128)>>8;
if (mul<-32768) mul=32768;
if (mul>32767) mul=32767;
return (int16_t)mul;
}
void CalcYUVMMX(blit_soft* p)
{
if (AnyYUV(&p->Dst))
{
ColMMX(p,0,p->FX.Brightness+p->FX.RGBAdjust[1]);
ColMMX(p,1,p->FX.RGBAdjust[2]-p->FX.RGBAdjust[1]);
ColMMX(p,2,p->FX.RGBAdjust[0]-p->FX.RGBAdjust[1]);
}
else
{
const int16_t* m = GetYUVToRGB(&p->Src);
p->Col[0][0][3] = p->Col[0][0][2] = p->Col[0][0][1] = p->Col[0][0][0] = MulMMX(p,0,m[0]);
p->Col[0][1][3] = p->Col[0][1][2] = p->Col[0][1][1] = p->Col[0][1][0] = (int16_t)(m[1]+p->FX.Brightness+p->FX.RGBAdjust[1]);
p->Col[1][0][1] = p->Col[1][0][0] = MulMMX(p,1,m[2]); //u_b
p->Col[1][0][3] = p->Col[1][0][2] = MulMMX(p,1,m[3]); //u_g
p->Col[1][1][3] = p->Col[1][1][2] = p->Col[1][1][1] = p->Col[1][1][0] = (int16_t)(m[4]+p->FX.RGBAdjust[2]-p->FX.RGBAdjust[1]);
p->Col[2][0][1] = p->Col[2][0][0] = MulMMX(p,2,m[5]); //v_r
p->Col[2][0][3] = p->Col[2][0][2] = MulMMX(p,2,m[6]); //v_g
p->Col[2][1][3] = p->Col[2][1][2] = p->Col[2][1][1] = p->Col[2][1][0] = (int16_t)(m[7]+p->FX.RGBAdjust[0]-p->FX.RGBAdjust[1]);
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -