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