cr88192

slightly higher quality vaguely fast DXT5 encoder.

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