Want more features on Pastebin? Sign Up, it's FREE!
Guest

slightly higher quality vaguely fast DXT5 encoder.

By: cr88192 on Mar 25th, 2013  |  syntax: C  |  size: 5.64 KB  |  views: 26  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2. Copyright (C) 2013 by Brendan G Bohannon
  3. Email: cr88192@gmail.com
  4. Copying: http://pastebin.com/iJxtZHm6
  5.  */
  6.  
  7. /*
  8. Tries to deliver moderate quality, while still trying to allow for reasonably fast encoding.
  9. Generally handles interpolation by treating it like a fixed-point fraction, and using this fraction to index into a table.
  10.  
  11. This version also adds fixed-pattern dither and some tweaks to try to improve image quality.
  12. */
  13.  
  14. void BGBBTJ_BCn_EncodeBlockDXT5(byte *block,
  15.         byte *rgba, int xstride, int ystride)
  16. {
  17.         static const char idxtab[16]=
  18.                 { 0,0,0,0, 0,0,2,2, 3,3,1,1, 1,1,1,1 };
  19.         static const char idxtab2[16]=
  20.                 { 0,0,0,0, 2,2,3,3, 4,4,5,5, 1,1,1,1 };
  21.         byte pxa[16], pxy[16];
  22.         int p0, p1, p2, p3, p4, p5, p6, p7;
  23.         int l0, l1, l2, l3a, l3b;
  24.         int mcr, mcg, mcb, mca, mcy;
  25.         int ncr, ncg, ncb, nca, ncy;
  26.         int acr, acg, acb, aca, acy;
  27.         int cr, cg, cb, ca, cy;
  28.         int i, j, k, l;
  29.        
  30.         mcr=255; mcg=255; mcb=255; mca=255; mcy=255;
  31.         ncr=  0; ncg=  0; ncb=  0; nca=  0; ncy=  0;
  32.         acr=  0; acg=  0; acb=  0; aca=  0; acy=  0;
  33.        
  34.         for(i=0; i<4; i++)
  35.                 for(j=0; j<4; j++)
  36.         {
  37.                 k=(i*ystride)+(j*xstride);
  38.                 cr=rgba[k+0];   cg=rgba[k+1];
  39.                 cb=rgba[k+2];   ca=rgba[k+3];
  40.                 cy=(cr+(2*cg)+cb)>>2;           //Luma
  41.  
  42.                 pxa[i*4+j]=ca;
  43.                 pxy[i*4+j]=cy;
  44.  
  45.                 //Find Mins/Maxs
  46.                 if(cy<mcy) { mcr=cr; mcg=cg; mcb=cb; mcy=cy; }
  47.                 if(cy>ncy) { ncr=cr; ncg=cg; ncb=cb; ncy=cy; }
  48.                 if(ca<mca) { mca=ca; }
  49.                 if(ca>nca) { nca=ca; }
  50.                
  51.                 acr+=cr; acg+=cg;
  52.                 acb+=cb; acy+=cy;
  53.         }
  54.  
  55.         acr=(acr+8)>>4;
  56.         acg=(acg+8)>>4;
  57.         acb=(acb+8)>>4;
  58.         acy=(acr+(2*acg)+acb)>>2;
  59.        
  60.         l=(256*mcy)/(acy+1);
  61.         cr=(acr*l+128)>>8;
  62.         cg=(acg*l+128)>>8;
  63.         cb=(acb*l+128)>>8;
  64.        
  65.         mcr=(mcr+cr)>>1;
  66.         mcg=(mcg+cg)>>1;
  67.         mcb=(mcb+cb)>>1;
  68.        
  69.  
  70.         l=(256*ncy)/(acy+1);
  71.         cr=(acr*l+128)>>8;
  72.         cg=(acg*l+128)>>8;
  73.         cb=(acb*l+128)>>8;
  74.        
  75.         ncr=(ncr+cr)>>1;
  76.         ncg=(ncg+cg)>>1;
  77.         ncb=(ncb+cb)>>1;
  78.  
  79.         aca=(mca+nca)>>1;                       //Median Alpha
  80.         acy=(mcy+ncy)>>1;                       //Median Luma
  81.         l0=49152/(nca-aca+1);           //Fix-Point Scale (Alpha)
  82.         l1=32768/(ncy-acy+1);           //Fix-Point Scale (Luma)
  83.         l2=65536-2048;
  84.  
  85.         if(mca==nca)
  86.         {
  87.                 block[0]=mca; block[1]=nca;
  88.                 block[2]=0;     block[3]=0;
  89.                 block[4]=0;     block[5]=0;
  90.                 block[6]=0;     block[7]=0;
  91.         }else
  92.         {
  93.                 //Emit Alpha Block
  94.                 block[0]=mca;
  95.                 block[1]=nca;
  96.        
  97.                 p0=idxtab2[((pxa[ 0]-aca)*l0+l2)>>13];
  98.                 p1=idxtab2[((pxa[ 1]-aca)*l0+l2)>>13];
  99.                 p2=idxtab2[((pxa[ 2]-aca)*l0+l2)>>13];
  100.                 p3=idxtab2[((pxa[ 3]-aca)*l0+l2)>>13];
  101.                 p4=idxtab2[((pxa[ 4]-aca)*l0+l2)>>13];
  102.                 p5=idxtab2[((pxa[ 5]-aca)*l0+l2)>>13];
  103.                 p6=idxtab2[((pxa[ 6]-aca)*l0+l2)>>13];
  104.                 p7=idxtab2[((pxa[ 7]-aca)*l0+l2)>>13];
  105.                 block[2]=p0|(p1<<3)|(p2<<6);
  106.                 block[3]=(p2>>2)|(p3<<1)|(p4<<4)|(p5<<7);
  107.                 block[4]=(p5>>1)|(p6<<2)|(p7<<5);
  108.                 p0=idxtab2[((pxa[ 8]-aca)*l0+l2)>>13];
  109.                 p1=idxtab2[((pxa[ 9]-aca)*l0+l2)>>13];
  110.                 p2=idxtab2[((pxa[10]-aca)*l0+l2)>>13];
  111.                 p3=idxtab2[((pxa[11]-aca)*l0+l2)>>13];
  112.                 p4=idxtab2[((pxa[12]-aca)*l0+l2)>>13];
  113.                 p5=idxtab2[((pxa[13]-aca)*l0+l2)>>13];
  114.                 p6=idxtab2[((pxa[14]-aca)*l0+l2)>>13];
  115.                 p7=idxtab2[((pxa[15]-aca)*l0+l2)>>13];
  116.                 block[5]=p0|(p1<<3)|(p2<<6);
  117.                 block[6]=(p2>>2)|(p3<<1)|(p4<<4)|(p5<<7);
  118.                 block[7]=(p5>>1)|(p6<<2)|(p7<<5);
  119.         }
  120.  
  121.         if((mcr==ncr) && (mcg==ncg) && (mcb==ncb))
  122.         {
  123.                 //Flat Color Block
  124.                 mcr=((mcr+3)>>3)<<3;
  125.                 mcg=((mcg+1)>>2)<<2;
  126.                 mcb=((mcb+3)>>3)<<3;
  127.                 ncr=((ncr+5)>>3)<<3;
  128.                 ncg=((ncg+3)>>2)<<2;
  129.                 ncb=((ncb+5)>>3)<<3;
  130.                 mcr=(mcr<0)?0:((mcr>255)?255:mcr);
  131.                 mcg=(mcg<0)?0:((mcg>255)?255:mcg);
  132.                 mcb=(mcb<0)?0:((mcb>255)?255:mcb);
  133.                 ncr=(ncr<0)?0:((ncr>255)?255:ncr);
  134.                 ncg=(ncg<0)?0:((ncg>255)?255:ncg);
  135.                 ncb=(ncb<0)?0:((ncb>255)?255:ncb);
  136.                 i=((mcr<<8)&0xF800) | ((mcg<<3)&0x07E0) | ((mcb>>3)&0x001F);
  137.                 j=((ncr<<8)&0xF800) | ((ncg<<3)&0x07E0) | ((ncb>>3)&0x001F);
  138.                 block[ 8]=i;    block[ 9]=i>>8;
  139.                 block[10]=j;    block[11]=j>>8;
  140.                 block[12]=(2<<6)|(3<<4)|(2<<2)|3;
  141.                 block[13]=(3<<6)|(2<<4)|(3<<2)|2;
  142.                 block[14]=(2<<6)|(3<<4)|(2<<2)|3;
  143.                 block[15]=(3<<6)|(2<<4)|(3<<2)|2;
  144.         }else
  145.         {
  146.                 //Emit RGB Block
  147.  
  148.                 mcr=((mcr+3)>>3)<<3;
  149.                 mcg=((mcg+1)>>2)<<2;
  150.                 mcb=((mcb+3)>>3)<<3;
  151.                 ncr=((ncr+5)>>3)<<3;
  152.                 ncg=((ncg+3)>>2)<<2;
  153.                 ncb=((ncb+5)>>3)<<3;
  154.                 mcr=(mcr<0)?0:((mcr>255)?255:mcr);
  155.                 mcg=(mcg<0)?0:((mcg>255)?255:mcg);
  156.                 mcb=(mcb<0)?0:((mcb>255)?255:mcb);
  157.                 ncr=(ncr<0)?0:((ncr>255)?255:ncr);
  158.                 ncg=(ncg<0)?0:((ncg>255)?255:ncg);
  159.                 ncb=(ncb<0)?0:((ncb>255)?255:ncb);
  160.  
  161.                 l3a=65536-1024;
  162.                 l3b=65536+1024;
  163.  
  164.                 i=((mcr<<8)&0xF800) | ((mcg<<3)&0x07E0) | ((mcb>>3)&0x001F);
  165.                 j=((ncr<<8)&0xF800) | ((ncg<<3)&0x07E0) | ((ncb>>3)&0x001F);
  166.                 block[ 8]=i;    block[ 9]=i>>8;
  167.                 block[10]=j;    block[11]=j>>8;
  168.  
  169.                 p0=idxtab[((pxy[ 0]-acy)*l1+l3a)>>13];
  170.                 p1=idxtab[((pxy[ 1]-acy)*l1+l3b)>>13];
  171.                 p2=idxtab[((pxy[ 2]-acy)*l1+l3a)>>13];
  172.                 p3=idxtab[((pxy[ 3]-acy)*l1+l3b)>>13];
  173.                 block[12]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  174.                 p0=idxtab[((pxy[ 4]-acy)*l1+l3b)>>13];
  175.                 p1=idxtab[((pxy[ 5]-acy)*l1+l3a)>>13];
  176.                 p2=idxtab[((pxy[ 6]-acy)*l1+l3b)>>13];
  177.                 p3=idxtab[((pxy[ 7]-acy)*l1+l3a)>>13];
  178.                 block[13]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  179.                 p0=idxtab[((pxy[ 8]-acy)*l1+l3a)>>13];
  180.                 p1=idxtab[((pxy[ 9]-acy)*l1+l3b)>>13];
  181.                 p2=idxtab[((pxy[10]-acy)*l1+l3a)>>13];
  182.                 p3=idxtab[((pxy[11]-acy)*l1+l3b)>>13];
  183.                 block[14]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  184.                 p0=idxtab[((pxy[12]-acy)*l1+l3b)>>13];
  185.                 p1=idxtab[((pxy[13]-acy)*l1+l3a)>>13];
  186.                 p2=idxtab[((pxy[14]-acy)*l1+l3b)>>13];
  187.                 p3=idxtab[((pxy[15]-acy)*l1+l3a)>>13];
  188.                 block[15]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  189.         }
  190. }
  191.  
  192. BGBBTJ_API void BGBBTJ_BCn_EncodeImageDXT5(byte *block,
  193.         byte *rgba, int xs, int ys, int stride)
  194. {
  195.         int xs1, ys1;
  196.         int i, j;
  197.        
  198.         xs1=xs>>2; ys1=ys>>2;
  199.         for(i=0; i<ys1; i++)
  200.                 for(j=0; j<xs1; j++)
  201.         {
  202.                 BGBBTJ_BCn_EncodeBlockDXT5(
  203.                         block+(i*xs1+j)*16,
  204.                         rgba+(i*4*xs+j*4)*stride,
  205.                         stride, xs*stride);
  206.         }
  207. }
clone this paste RAW Paste Data