Advertisement
cr88192

Slightly Higher-Quality DXT1+Alpha Encoder

May 31st, 2013
229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.46 KB | None | 0 0
  1. /*
  2. Copyright (C) 2013 by Brendan G Bohannon
  3. Email: cr88192@gmail.com
  4. Copying: http://pastebin.com/iJxtZHm6
  5.  */
  6.  
  7. void BGBBTJ_BCn_EncodeBlockDXT1A(byte *block,
  8.     byte *rgba, int xstride, int ystride)
  9. {
  10.     static char idxtaba[16]=
  11.         { 0,0,0,0, 0,0,2,2, 3,3,1,1, 1,1,1,1 };
  12.     static char idxtabb[16]=
  13.         { 1,1,1,1, 1,1,3,3, 2,2,0,0, 0,0,0,0 };
  14.     static char idxtabc[16]=
  15.         { 0,0,0,0, 0,0,2,2, 2,2,1,1, 1,1,1,1 };
  16.     static char idxtabd[16]=
  17.         { 1,1,1,1, 1,1,2,2, 2,2,0,0, 0,0,0,0 };
  18.     byte pxa[16], pxy[16];
  19.     char *idxtab;
  20.     int p0, p1, p2, p3, p4, p5, p6, p7;
  21.     int l0, l1, l2, l3a, l3b;
  22.     int mcr, mcg, mcb, mca, mcy;
  23.     int ncr, ncg, ncb, nca, ncy;
  24.     int acr, acg, acb, aca, acy;
  25.     int cr, cg, cb, ca, cy;
  26.     int i, j, k, l;
  27.    
  28.     mcr=255; mcg=255; mcb=255; mca=255; mcy=255;
  29.     ncr=  0; ncg=  0; ncb=  0; nca=  0; ncy=  0;
  30.     acr=  0; acg=  0; acb=  0; aca=  0; acy=  0;
  31.    
  32.     for(i=0; i<4; i++)
  33.         for(j=0; j<4; j++)
  34.     {
  35.         k=(i*ystride)+(j*xstride);
  36.         cr=rgba[k+0];   cg=rgba[k+1];
  37.         cb=rgba[k+2];   ca=rgba[k+3];
  38.         cy=(cr+(2*cg)+cb)>>2;       //Luma
  39.  
  40.         pxa[i*4+j]=ca;
  41.         pxy[i*4+j]=cy;
  42.  
  43.         //Find Mins/Maxs
  44.         if(cy<mcy) { mcr=cr; mcg=cg; mcb=cb; mcy=cy; }
  45.         if(cy>ncy) { ncr=cr; ncg=cg; ncb=cb; ncy=cy; }
  46.         if(ca<mca) { mca=ca; }
  47.         if(ca>nca) { nca=ca; }
  48.        
  49.         acr+=cr; acg+=cg;
  50.         acb+=cb; acy+=cy;
  51.     }
  52.  
  53. #if 1
  54.     acr=(acr+8)>>4;
  55.     acg=(acg+8)>>4;
  56.     acb=(acb+8)>>4;
  57.     acy=(acr+(2*acg)+acb)>>2;
  58.    
  59.     l=(256*mcy)/(acy+1);
  60.     cr=(acr*l+128)>>8;
  61.     cg=(acg*l+128)>>8;
  62.     cb=(acb*l+128)>>8;
  63.    
  64.     mcr=(mcr+cr)>>1;
  65.     mcg=(mcg+cg)>>1;
  66.     mcb=(mcb+cb)>>1;
  67.    
  68.  
  69.     l=(256*ncy)/(acy+1);
  70.     cr=(acr*l+128)>>8;
  71.     cg=(acg*l+128)>>8;
  72.     cb=(acb*l+128)>>8;
  73.    
  74.     ncr=(ncr+cr)>>1;
  75.     ncg=(ncg+cg)>>1;
  76.     ncb=(ncb+cb)>>1;
  77. #endif
  78.  
  79. #if 1
  80.     mcr=((mcr+3)>>3)<<3;
  81.     mcg=((mcg+1)>>2)<<2;
  82.     mcb=((mcb+3)>>3)<<3;
  83.     ncr=((ncr+5)>>3)<<3;
  84.     ncg=((ncg+3)>>2)<<2;
  85.     ncb=((ncb+5)>>3)<<3;
  86.     mcr=(mcr<0)?0:((mcr>255)?255:mcr);
  87.     mcg=(mcg<0)?0:((mcg>255)?255:mcg);
  88.     mcb=(mcb<0)?0:((mcb>255)?255:mcb);
  89.     ncr=(ncr<0)?0:((ncr>255)?255:ncr);
  90.     ncg=(ncg<0)?0:((ncg>255)?255:ncg);
  91.     ncb=(ncb<0)?0:((ncb>255)?255:ncb);
  92. #endif
  93.  
  94.     aca=(mca+nca)>>1;           //Median Alpha
  95.     acy=(mcy+ncy)>>1;           //Median Luma
  96.     l0=49152/(nca-aca+1);       //Fix-Point Scale (Alpha)
  97.     l1=32768/(ncy-acy+1);       //Fix-Point Scale (Luma)
  98.     l2=65536-2048;
  99.  
  100.     if(nca<128)
  101.     {
  102.         //Fully Transparent Block
  103.         i=((acr<<8)&0xF800) | ((acg<<3)&0x07E0) | ((acb>>3)&0x001F);
  104.         block[0]=i; block[1]=i>>8;
  105.         block[2]=i; block[3]=i>>8;
  106.  
  107.         block[4]=255;   block[5]=255;
  108.         block[6]=255;   block[7]=255;
  109.     }else if((mcr==ncr) && (mcg==ncg) && (mcb==ncb) && (mca==nca))
  110.     {  
  111.         //Flat Color Block
  112.         i=((mcr<<8)&0xF800) | ((mcg<<3)&0x07E0) | ((mcb>>3)&0x001F);
  113.         j=((ncr<<8)&0xF800) | ((ncg<<3)&0x07E0) | ((ncb>>3)&0x001F);
  114.         if(j<=i)
  115.         {
  116.             block[0]=i; block[1]=i>>8;
  117.             block[2]=j; block[3]=j>>8;
  118.         }else
  119.         {
  120.             block[0]=j; block[1]=j>>8;
  121.             block[2]=i; block[3]=i>>8;
  122.         }
  123.  
  124.         if(i!=j)
  125.         {
  126.             block[4]=(2<<6)|(3<<4)|(2<<2)|3;
  127.             block[5]=(3<<6)|(2<<4)|(3<<2)|2;
  128.             block[6]=(2<<6)|(3<<4)|(2<<2)|3;
  129.             block[7]=(3<<6)|(2<<4)|(3<<2)|2;
  130.         }else
  131.         {
  132.             block[4]=0; block[5]=0;
  133.             block[6]=0; block[7]=0;
  134.         }
  135.     }else if(mca>=128)
  136.     {
  137.         //Emit RGB Block (Opaque)
  138.  
  139.         l1=(32768-6144)/(ncy-acy+1);        //Fix-Point Scale (Luma)
  140.         l3a=65536-1024;
  141.         l3b=65536+1024;
  142.  
  143.         i=((mcr<<8)&0xF800) | ((mcg<<3)&0x07E0) | ((mcb>>3)&0x001F);
  144.         j=((ncr<<8)&0xF800) | ((ncg<<3)&0x07E0) | ((ncb>>3)&0x001F);
  145.  
  146.         if(j<i)
  147.         {
  148.             block[0]=i; block[1]=i>>8;
  149.             block[2]=j; block[3]=j>>8;
  150.             idxtab=idxtaba;
  151.         }else if(i<j)
  152.         {
  153.             block[0]=j; block[1]=j>>8;
  154.             block[2]=i; block[3]=i>>8;
  155.             idxtab=idxtabb;
  156.         }else
  157.         {
  158.             block[0]=i; block[1]=i>>8;
  159.             block[2]=j; block[3]=j>>8;
  160.             idxtab=idxtabc;
  161.         }
  162.  
  163.         p0=idxtab[((pxy[ 0]-acy)*l1+l3a)>>13];
  164.         p1=idxtab[((pxy[ 1]-acy)*l1+l3b)>>13];
  165.         p2=idxtab[((pxy[ 2]-acy)*l1+l3a)>>13];
  166.         p3=idxtab[((pxy[ 3]-acy)*l1+l3b)>>13];
  167.         block[4]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  168.         p0=idxtab[((pxy[ 4]-acy)*l1+l3b)>>13];
  169.         p1=idxtab[((pxy[ 5]-acy)*l1+l3a)>>13];
  170.         p2=idxtab[((pxy[ 6]-acy)*l1+l3b)>>13];
  171.         p3=idxtab[((pxy[ 7]-acy)*l1+l3a)>>13];
  172.         block[5]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  173.         p0=idxtab[((pxy[ 8]-acy)*l1+l3a)>>13];
  174.         p1=idxtab[((pxy[ 9]-acy)*l1+l3b)>>13];
  175.         p2=idxtab[((pxy[10]-acy)*l1+l3a)>>13];
  176.         p3=idxtab[((pxy[11]-acy)*l1+l3b)>>13];
  177.         block[6]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  178.         p0=idxtab[((pxy[12]-acy)*l1+l3b)>>13];
  179.         p1=idxtab[((pxy[13]-acy)*l1+l3a)>>13];
  180.         p2=idxtab[((pxy[14]-acy)*l1+l3b)>>13];
  181.         p3=idxtab[((pxy[15]-acy)*l1+l3a)>>13];
  182.         block[7]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  183.     }else
  184.     {
  185.         //Emit RGB Block (Alpha)
  186.  
  187.         l1=(32768-6144)/(ncy-acy+1);        //Fix-Point Scale (Luma)
  188.  
  189.         l3a=65536-1024;
  190.         l3b=65536+1024;
  191.  
  192.         i=((mcr<<8)&0xF800) | ((mcg<<3)&0x07E0) | ((mcb>>3)&0x001F);
  193.         j=((ncr<<8)&0xF800) | ((ncg<<3)&0x07E0) | ((ncb>>3)&0x001F);
  194.  
  195.         if(i<=j)
  196.         {
  197.             block[0]=i; block[1]=i>>8;
  198.             block[2]=j; block[3]=j>>8;
  199.             idxtab=idxtabc;
  200.         }else
  201.         {
  202.             block[0]=j; block[1]=j>>8;
  203.             block[2]=i; block[3]=i>>8;
  204.             idxtab=idxtabd;
  205.         }
  206.  
  207.         p0=idxtab[((pxy[ 0]-acy)*l1+l3a)>>13] | (((pxa[ 0]-128)>>10)&3);
  208.         p1=idxtab[((pxy[ 1]-acy)*l1+l3b)>>13] | (((pxa[ 1]-128)>>10)&3);
  209.         p2=idxtab[((pxy[ 2]-acy)*l1+l3a)>>13] | (((pxa[ 2]-128)>>10)&3);
  210.         p3=idxtab[((pxy[ 3]-acy)*l1+l3b)>>13] | (((pxa[ 3]-128)>>10)&3);
  211.         block[4]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  212.         p0=idxtab[((pxy[ 4]-acy)*l1+l3b)>>13] | (((pxa[ 4]-128)>>10)&3);
  213.         p1=idxtab[((pxy[ 5]-acy)*l1+l3a)>>13] | (((pxa[ 5]-128)>>10)&3);
  214.         p2=idxtab[((pxy[ 6]-acy)*l1+l3b)>>13] | (((pxa[ 6]-128)>>10)&3);
  215.         p3=idxtab[((pxy[ 7]-acy)*l1+l3a)>>13] | (((pxa[ 7]-128)>>10)&3);
  216.         block[5]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  217.         p0=idxtab[((pxy[ 8]-acy)*l1+l3a)>>13] | (((pxa[ 8]-128)>>10)&3);
  218.         p1=idxtab[((pxy[ 9]-acy)*l1+l3b)>>13] | (((pxa[ 9]-128)>>10)&3);
  219.         p2=idxtab[((pxy[10]-acy)*l1+l3a)>>13] | (((pxa[10]-128)>>10)&3);
  220.         p3=idxtab[((pxy[11]-acy)*l1+l3b)>>13] | (((pxa[11]-128)>>10)&3);
  221.         block[6]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  222.         p0=idxtab[((pxy[12]-acy)*l1+l3b)>>13] | (((pxa[12]-128)>>10)&3);
  223.         p1=idxtab[((pxy[13]-acy)*l1+l3a)>>13] | (((pxa[13]-128)>>10)&3);
  224.         p2=idxtab[((pxy[14]-acy)*l1+l3b)>>13] | (((pxa[14]-128)>>10)&3);
  225.         p3=idxtab[((pxy[15]-acy)*l1+l3a)>>13] | (((pxa[15]-128)>>10)&3);
  226.         block[7]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  227.     }
  228. }
  229.  
  230. BGBBTJ_API void BGBBTJ_BCn_EncodeImageDXT1(byte *block,
  231.     byte *rgba, int xs, int ys, int stride)
  232. {
  233.     int xs1, ys1;
  234.     int i, j;
  235.    
  236.     xs1=xs>>2; ys1=ys>>2;
  237.     for(i=0; i<ys1; i++)
  238.         for(j=0; j<xs1; j++)
  239.     {
  240.         BGBBTJ_BCn_EncodeBlockDXT1A(
  241.             block+(i*xs1+j)*8,
  242.             rgba+(i*4*xs+j*4)*stride,
  243.             stride, xs*stride);
  244.     }
  245. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement