cr88192

Slightly Higher-Quality DXT1+Alpha Encoder

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