/*
Copyright (C) 2013 by Brendan G Bohannon
Email: cr88192@gmail.com
Copying: http://pastebin.com/iJxtZHm6
*/
void BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(byte *block,
short *pxy, short *pxu, short *pxv)
{
int p0, p1, p2, p3;
int mcy, ncy, acy;
int acr, acg, acb;
int cy, cu, cv;
int cra, cga, cba;
int crb, cgb, cbb;
int u1, v1, l0, l1, l2;
int i, j, k;
cu=(pxu[0]+pxu[1]+pxu[8]+pxu[9])>>2;
cv=(pxv[0]+pxv[1]+pxv[8]+pxv[9])>>2;
mcy=pxy[0]; ncy=mcy;
i=pxy[ 1]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[ 2]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[ 3]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[ 8]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[ 9]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[10]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[11]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[16]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[17]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[18]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[19]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[24]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[25]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[26]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[27]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
acy=(mcy+ncy)>>1;
u1=cu-128; v1=cv-128;
l0=91881*v1;
l1=-22554*u1-46802*v1;
l2=116130*u1;
//EDIT: fixed math
cra=(65536*mcy+l0)>>16; cga=(65536*mcy+l1)>>16; cba=(65536*mcy+l2)>>16;
crb=(65536*ncy+l0)>>16; cgb=(65536*ncy+l1)>>16; cbb=(65536*ncy+l2)>>16;
if((cra|cga|cba|crb|cgb|cbb)&(~255))
{
cra=(cra<0)?0:((cra>255)?255:cra);
cga=(cga<0)?0:((cga>255)?255:cga);
cba=(cba<0)?0:((cba>255)?255:cba);
crb=(crb<0)?0:((crb>255)?255:crb);
cgb=(cgb<0)?0:((cgb>255)?255:cgb);
cbb=(cbb<0)?0:((cbb>255)?255:cbb);
}
i=((cra<<8)&0xF800) | ((cga<<3)&0x07E0) | (cba>>3);
j=((crb<<8)&0xF800) | ((cgb<<3)&0x07E0) | (cbb>>3);
block[0]=i; block[1]=i>>8;
block[2]=j; block[3]=j>>8;
p0=-((acy-pxy[ 0])>>16);
p1=-((acy-pxy[ 1])>>16);
p2=-((acy-pxy[ 2])>>16);
p3=-((acy-pxy[ 3])>>16);
block[4]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
p0=-((acy-pxy[ 8])>>16);
p1=-((acy-pxy[ 9])>>16);
p2=-((acy-pxy[10])>>16);
p3=-((acy-pxy[11])>>16);
block[5]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
p0=-((acy-pxy[16])>>16);
p1=-((acy-pxy[17])>>16);
p2=-((acy-pxy[18])>>16);
p3=-((acy-pxy[19])>>16);
block[6]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
p0=-((acy-pxy[24])>>16);
p1=-((acy-pxy[25])>>16);
p2=-((acy-pxy[26])>>16);
p3=-((acy-pxy[27])>>16);
block[7]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
}
/*
Alternate Version
Flipped vertically, uses DXT5 interpolation (via index table).
true DXT1 is color1/color2/average/transparent
{ 0,0,0,0, 0,0,2,2, 2,2,1,1, 1,1,1,1 };
The use of interpolation is mostly for slightly higher image quality.
*/
void BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(byte *block,
short *pxy, short *pxu, short *pxv)
{
static const char idxtab[16]=
{ 0,0,0,0, 0,0,2,2, 3,3,1,1, 1,1,1,1 };
int p0, p1, p2, p3;
int mcy, ncy, acy;
int acr, acg, acb;
int cy, cu, cv;
int cra, cga, cba;
int crb, cgb, cbb;
int u1, v1, l0, l1, l2;
int i, j, k;
cu=(pxu[0]+pxu[1]+pxu[8]+pxu[9])>>2;
cv=(pxv[0]+pxv[1]+pxv[8]+pxv[9])>>2;
mcy=pxy[0]; ncy=mcy;
i=pxy[ 1]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[ 2]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[ 3]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[ 8]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[ 9]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[10]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[11]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[16]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[17]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[18]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[19]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[24]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[25]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[26]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
i=pxy[27]; j=(i-mcy)>>24; k=(ncy-i)>>24;
mcy=(j&i)|((~j)&mcy); ncy=(k&i)|((~k)&ncy);
acy=(mcy+ncy)>>1;
u1=cu-128; v1=cv-128;
l0=359*v1;
l1=-88*u1-183*v1;
l2=454*u1;
cra=(256*mcy+l0)>>8; cga=(256*mcy+l1)>>8; cba=(256*mcy+l2)>>8;
crb=(256*ncy+l0)>>8; cgb=(256*ncy+l1)>>8; cbb=(256*ncy+l2)>>8;
if((cra|cga|cba|crb|cgb|cbb)&(~255))
{
cra=(cra<0)?0:((cra>255)?255:cra);
cga=(cga<0)?0:((cga>255)?255:cga);
cba=(cba<0)?0:((cba>255)?255:cba);
crb=(crb<0)?0:((crb>255)?255:crb);
cgb=(cgb<0)?0:((cgb>255)?255:cgb);
cbb=(cbb<0)?0:((cbb>255)?255:cbb);
}
i=((cra<<8)&0xF800) | ((cga<<3)&0x07E0) | (cba>>3);
j=((crb<<8)&0xF800) | ((cgb<<3)&0x07E0) | (cbb>>3);
block[0]=i; block[1]=i>>8;
block[2]=j; block[3]=j>>8;
if(i==j)
{
block[4]=0; block[5]=0;
block[6]=0; block[7]=0;
return;
}
// l0=(256+64)/(ncy-acy+1);
l0=32768/(ncy-acy+1); //Quality FIX
p0=idxtab[(((pxy[24]-acy)*l0)>>13)+8];
p1=idxtab[(((pxy[25]-acy)*l0)>>13)+8];
p2=idxtab[(((pxy[26]-acy)*l0)>>13)+8];
p3=idxtab[(((pxy[27]-acy)*l0)>>13)+8];
block[4]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
p0=idxtab[(((pxy[16]-acy)*l0)>>13)+8];
p1=idxtab[(((pxy[17]-acy)*l0)>>13)+8];
p2=idxtab[(((pxy[18]-acy)*l0)>>13)+8];
p3=idxtab[(((pxy[19]-acy)*l0)>>13)+8];
block[5]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
p0=idxtab[(((pxy[ 8]-acy)*l0)>>13)+8];
p1=idxtab[(((pxy[ 9]-acy)*l0)>>13)+8];
p2=idxtab[(((pxy[10]-acy)*l0)>>13)+8];
p3=idxtab[(((pxy[11]-acy)*l0)>>13)+8];
block[6]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
p0=idxtab[(((pxy[ 0]-acy)*l0)>>13)+8];
p1=idxtab[(((pxy[ 1]-acy)*l0)>>13)+8];
p2=idxtab[(((pxy[ 2]-acy)*l0)>>13)+8];
p3=idxtab[(((pxy[ 3]-acy)*l0)>>13)+8];
block[7]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
}
//Logic for YUV -> DXT
int BGBBTJ_JPG_DecodeColorTransform_YCbCr420_DXT1(
BGBBTJ_JPG_Context *ctx, byte *obuf, int xs, int ys, int stride)
{
short *yblk, *ublk, *vblk;
byte *oblk;
int xs1, ys1, xs2, ys2, xs3, ys3, xs4, ys4;
int i, j, k, i1;
xs1=xs>>1; ys1=ys>>1;
xs2=xs>>2; ys2=ys>>2;
xs3=xs>>3; ys3=ys>>3;
xs4=xs>>4; ys4=ys>>4;
for(i=0; i<ys4; i++)
for(j=0; j<xs4; j++)
{
k=i*xs4+j;
ublk=ctx->jpg_sibuf[1]+k*64;
vblk=ctx->jpg_sibuf[2]+k*64;
#if 1 //Vertical Flip
i1=ys4-i-1;
k=((i*2+0)*xs3)+(j*2+0);
yblk=ctx->jpg_sibuf[0]+k*64;
k=((i1*4+3)*xs2)+(j*4+0); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+0, ublk+0, vblk+0);
k=((i1*4+3)*xs2)+(j*4+1); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+4, ublk+2, vblk+2);
k=((i1*4+2)*xs2)+(j*4+0); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+32, ublk+16, vblk+16);
k=((i1*4+2)*xs2)+(j*4+1); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+36, ublk+18, vblk+18);
k=((i*2+0)*xs3)+(j*2+1);
yblk=ctx->jpg_sibuf[0]+k*64;
k=((i1*4+3)*xs2)+(j*4+2); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+0, ublk+4, vblk+4);
k=((i1*4+3)*xs2)+(j*4+3); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+4, ublk+6, vblk+6);
k=((i1*4+2)*xs2)+(j*4+2); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+32, ublk+20, vblk+20);
k=((i1*4+2)*xs2)+(j*4+3); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+36, ublk+22, vblk+22);
k=((i*2+1)*xs3)+(j*2+0);
yblk=ctx->jpg_sibuf[0]+k*64;
k=((i1*4+1)*xs2)+(j*4+0); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+0, ublk+32, vblk+32);
k=((i1*4+1)*xs2)+(j*4+1); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+4, ublk+34, vblk+34);
k=((i1*4+0)*xs2)+(j*4+0); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+32, ublk+48, vblk+48);
k=((i1*4+0)*xs2)+(j*4+1); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+36, ublk+50, vblk+50);
k=((i*2+1)*xs3)+(j*2+1);
yblk=ctx->jpg_sibuf[0]+k*64;
k=((i1*4+1)*xs2)+(j*4+2); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+0, ublk+36, vblk+36);
k=((i1*4+1)*xs2)+(j*4+3); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+4, ublk+38, vblk+38);
k=((i1*4+0)*xs2)+(j*4+2); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+32, ublk+52, vblk+52);
k=((i1*4+0)*xs2)+(j*4+3); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+36, ublk+54, vblk+54);
#endif
#if 0 //No Vertical Flip
k=((i*2+0)*xs3)+(j*2+0);
yblk=ctx->jpg_sibuf[0]+k*64;
k=((i*4+0)*xs2)+(j*4+0); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+0, ublk+0, vblk+0);
k=((i*4+0)*xs2)+(j*4+1); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+4, ublk+2, vblk+2);
k=((i*4+1)*xs2)+(j*4+0); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+32, ublk+16, vblk+16);
k=((i*4+1)*xs2)+(j*4+1); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+36, ublk+18, vblk+18);
k=((i*2+0)*xs3)+(j*2+1);
yblk=ctx->jpg_sibuf[0]+k*64;
k=((i*4+0)*xs2)+(j*4+2); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+0, ublk+4, vblk+4);
k=((i*4+0)*xs2)+(j*4+3); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+4, ublk+6, vblk+6);
k=((i*4+1)*xs2)+(j*4+2); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+32, ublk+20, vblk+20);
k=((i*4+1)*xs2)+(j*4+3); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+36, ublk+22, vblk+22);
k=((i*2+1)*xs3)+(j*2+0);
yblk=ctx->jpg_sibuf[0]+k*64;
k=((i*4+2)*xs2)+(j*4+0); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+0, ublk+32, vblk+32);
k=((i*4+2)*xs2)+(j*4+1); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+4, ublk+34, vblk+34);
k=((i*4+3)*xs2)+(j*4+0); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+32, ublk+48, vblk+48);
k=((i*4+3)*xs2)+(j*4+1); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+36, ublk+50, vblk+50);
k=((i*2+1)*xs3)+(j*2+1);
yblk=ctx->jpg_sibuf[0]+k*64;
k=((i*4+2)*xs2)+(j*4+2); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+0, ublk+36, vblk+36);
k=((i*4+2)*xs2)+(j*4+3); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+4, ublk+38, vblk+38);
k=((i*4+3)*xs2)+(j*4+2); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+32, ublk+52, vblk+52);
k=((i*4+3)*xs2)+(j*4+3); oblk=obuf+k*stride;
BGBBTJ_BCn_EncodeBlockDXT1F_YUV420(oblk, yblk+36, ublk+54, vblk+54);
#endif
}
}