Advertisement
cr88192

Experimental DXT5-UVAY Encoder.

Feb 12th, 2013
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.45 KB | None | 0 0
  1. /*
  2. Copyright (C) 2013 by Brendan G Bohannon
  3. Copying: http://pastebin.com/iJxtZHm6
  4.  */
  5.  
  6. /*
  7. Experimental encoder for DXT5 using a "UVAY" color mapping (YUVA stored in UVAY ordering).
  8. Colorspace is basically a modified RCT.
  9.  
  10. The idea is that the color conversion back to RGBA can be handled in a fragment shader, and this "could" allow slightly higher image quality (by giving more bits to Y).
  11.  
  12. Issues: Color artifacts exist and I was unable to figure out their exact cause or exactly how to go about fixing them. They were generally showing up as typically purple or sometimes green spots in otherwise low-saturation areas (as well as other color-related artifacts). This could be due to numerical precision.
  13.  
  14. Details seem slightly sharper than with normal DXT5 though.
  15.  
  16. Another possibility: UV are Y relative, or use A as a scale, rather than for Alpha (could improve quality but at the cost of an Alpha channel).
  17. */
  18.  
  19. void BGBBTJ_BCn_EncodeBlockDXT5_UVAY(byte *block,
  20.     byte *rgba, int xstride, int ystride, int nclr)
  21. {
  22.     static const char idxtab[16]=
  23.         { 0,0,0,0, 0,0,2,2, 3,3,1,1, 1,1,1,1 };
  24.     static const char idxtab2[16]=
  25.         { 0,0,0,0, 2,2,3,3, 4,4,5,5, 1,1,1,1 };
  26.     short pxy[16], pxu[16], pxv[16], pxa[16], pxz[16];
  27. //  int peuva[3], pxuva[3], pwuva[3];
  28.     int p0, p1, p2, p3, p4, p5, p6, p7;
  29.     int l0, l1;
  30.     int mcy, mcu, mcv, mca, mcz;
  31.     int ncy, ncu, ncv, nca, ncz;
  32.     int acy, acu, acv, aca, acz;
  33.     int cr, cg, cb, ca;
  34.     int cy, cu, cv, cz, czb;
  35.     int i, j, k, l;
  36.    
  37.     mcy=255; mcu=255; mcv=255; mca=255; mcz=255;
  38.     ncy=  0; ncu=  0; ncv=  0; nca=  0; ncz=  0;
  39.     acy=  0; acu=  0; acv=  0; aca=  0; acz=  0;
  40.     czb=  0;
  41.    
  42.     for(i=0; i<4; i++)
  43.         for(j=0; j<4; j++)
  44.     {
  45.         k=(i*ystride)+(j*xstride);
  46.         cr=rgba[k+0];   cg=rgba[k+1];
  47.         cb=rgba[k+2];   ca=rgba[k+3];
  48.         cy=(cr+(2*cg)+cb)>>2;       //Y (Luma)
  49.         cu=((cb-cg)>>1)+128;
  50.         cv=((cr-cg)>>1)+128;
  51. //      cz=(cu+(2*cv)+ca)>>2;       //Z (Chroma+Alpha)
  52. //      cz=((3*cu)+(4*cv)+ca)>>3;   //Z (Chroma+Alpha)
  53.         cz=((256-cu)+(2*cv)+ca)>>2;     //Z (Chroma+Alpha)
  54.  
  55.         czb+=(cu-128)*(cv-128);
  56.  
  57. //      cy=(cy<0)?0:((cy>255)?255:cy);
  58. //      cu=(cu<0)?0:((cu>255)?255:cu);
  59. //      cv=(cv<0)?0:((cv>255)?255:cv);
  60. //      ca=(ca<0)?0:((ca>255)?255:ca);
  61. //      cz=(cz<0)?0:((cz>255)?255:cz);
  62.  
  63. #if 0
  64.         if((cy+32)>=ca)
  65.             { cy=(224*ca)>>8; }
  66. #endif
  67.  
  68.         pxy[i*4+j]=cy;
  69.         pxz[i*4+j]=cz;
  70.  
  71. //      pxu[i*4+j]=cu;
  72. //      pxv[i*4+j]=cv;
  73. //      pxa[i*4+j]=ca;
  74.  
  75. #if 0
  76.         //Energy Balance (UVA)
  77.         peuva[0]+=(cu-128)*(cu-128);
  78.         peuva[1]+=(cv-128)*(cv-128);
  79.         peuva[2]+=(ca-128)*(ca-128);
  80.         //Correlation (UVA)
  81.         pxuva[0]+=(cu-128)*(cv-128);
  82.         pxuva[1]+=(cv-128)*(ca-128);
  83.         pxuva[2]+=(cu-128)*(ca-128);
  84. #endif
  85.  
  86.         //Find Mins/Maxs YUVA
  87.         if(cz<mcz) { mcu=cu; mcv=cv; mca=ca; mcz=cz; }
  88.         if(cz>ncz) { ncu=cu; ncv=cv; nca=ca; ncz=cz; }
  89.         if(cy<mcy) { mcy=cy; }
  90.         if(cy>ncy) { ncy=cy; }
  91.  
  92. #if 0
  93.         if(cu<mcu) { mcu=cu; }
  94.         if(cu>ncu) { ncu=cu; }
  95.         if(cv<mcv) { mcv=cv; }
  96.         if(cv>ncv) { ncv=cv; }
  97.         if(ca<mca) { mca=ca; }
  98.         if(ca>nca) { nca=ca; }
  99.         if(cz<mcz) { mcz=cz; }
  100.         if(cz>ncz) { ncz=cz; }
  101. #endif
  102.  
  103.         //For Average YUVA
  104.         acy+=cy;    acu+=cu;
  105.         acv+=cv;    aca+=ca;
  106.     }
  107.    
  108.     //Calculate Average YUVA
  109.     acy=acy>>4; acu=acu>>4;
  110.     acv=acv>>4; aca=aca>>4;
  111.  
  112. //  if(pxuva[0]<0) { k=mcu; mcu=ncu; ncu=k; }
  113. //  if(pxuva[1]<0) { k=mca; mca=nca; nca=k; }
  114.  
  115. #if 0
  116.     k=peuva[0]+peuva[1]+peuva[2];
  117.     l=(256*peuva[0])/k;
  118.     pwuva[0]=(pxuva[0]>>28)*l;
  119.     l=(256*peuva[1])/k;
  120.     pwuva[1]=l;
  121.     l=(256*peuva[2])/k;
  122.     pwuva[2]=(pxuva[2]>>28)*l;
  123.  
  124.     if(pxuva[0]<0) { k=mcu; mcu=ncu; ncu=k; }
  125.     if(pxuva[1]<0) { k=mca; mca=nca; nca=k; }
  126.  
  127.     mcz=255; ncz=0;
  128.     for(i=0; i<16; i++)
  129.     {
  130.         cu=pxu[i]; cv=pxv[i]; ca=pxv[i];
  131.         cz=(cu*pwuva[0]+cv*pwuva[1]+cv*pwuva[2])>>8;
  132.         pxz[i]=cz;
  133.         if(cz<mcz) { mcz=cz; }
  134.         if(cz>ncz) { ncz=cz; }
  135.     }
  136.  
  137. #endif
  138.  
  139. #if 0
  140.     if(czb<0)
  141. //  if(czb>0)
  142.     {
  143.         k=mcu; mcu=ncu; ncu=k;
  144.         mcz=255; ncz=0;
  145.         for(i=0; i<16; i++)
  146.         {
  147.             cu=256-pxu[i];
  148.             cv=pxv[i];
  149.             ca=pxv[i];
  150.             cz=(l+(2*cv)+ca)>>2;    //Z (Chroma+Alpha)
  151. //          cz=((4*l)+(3*cv)+ca)>>3;    //Z (Chroma+Alpha)
  152.             pxz[i]=cz;
  153.             if(cz<mcz) { mcz=cz; }
  154.             if(cz>ncz) { ncz=cz; }
  155.         }
  156.     }
  157. #endif
  158.  
  159. //  mcu=((mcu+4)>>3)<<3;
  160. //  mcv=((mcv+2)>>2)<<2;
  161. //  ncu=((ncu+4)>>3)<<3;
  162. //  ncv=((ncv+2)>>2)<<2;
  163.  
  164. //  mcu=(((mcu-128)>>3)<<3)+128;
  165. //  mcv=(((mcv-128)>>2)<<2)+128;
  166. //  ncu=(((ncu-128)>>3)<<3)+128;
  167. //  ncv=(((ncv-128)>>2)<<2)+128;
  168.  
  169. //  mcu=(11*mcu+5*acu)>>4;
  170. //  mcv=(11*mcv+5*acv)>>4;
  171. //  mca=(11*mca+5*aca)>>4;
  172. //  ncu=(11*ncu+5*acu)>>4;
  173. //  ncv=(11*ncv+5*acv)>>4;
  174. //  nca=(11*nca+5*aca)>>4;
  175.  
  176. //  mcu=(mcu<128)?(((mcu+7)>>3)<<3):mcu;
  177. //  mcv=(mcv<128)?(((mcv+3)>>2)<<2):mcv;
  178.  
  179.     if(mcy<0)mcy=0;
  180.     if(mcu<0)mcu=0;
  181.     if(mcv<0)mcv=0;
  182.     if(mca<0)mca=0;
  183.     if(mcz<0)mcz=0;
  184.     if(ncy>255)ncy=255;
  185.     if(ncu>255)ncu=255;
  186.     if(ncv>255)ncv=255;
  187.     if(nca>255)nca=255;
  188.     if(ncz>255)ncz=255;
  189.  
  190.     acy=(mcy+ncy)>>1;           //Median Y
  191.     acz=(mcz+ncz)>>1;           //Median Z
  192. //  l0=(256+128)/(ncy-acy+1);   //Fix-Point Scale (Y)
  193. //  l1=(256+64)/(ncz-acz+1);    //Fix-Point Scale (Z)
  194. //  l0=(ncy>acy)?(32768/(ncy-acy)):0;       //Fix-Point Scale (Y)
  195. //  l1=(ncz>acz)?(32768/(ncz-acz)):0;       //Fix-Point Scale (Z)
  196. //  l0=32768/(ncy-acy+1);       //Fix-Point Scale (Y)
  197.     l0=49152/(ncy-acy+1);       //Fix-Point Scale (Y)
  198.     l1=32768/(ncz-acz+1);       //Fix-Point Scale (Z)
  199.  
  200.     //Emit Y Block
  201.     block[0]=mcy;
  202.     block[1]=ncy;
  203.    
  204.     p0=idxtab2[(((pxy[ 0]-acy)*l0)>>13)+8];
  205.     p1=idxtab2[(((pxy[ 1]-acy)*l0)>>13)+8];
  206.     p2=idxtab2[(((pxy[ 2]-acy)*l0)>>13)+8];
  207.     p3=idxtab2[(((pxy[ 3]-acy)*l0)>>13)+8];
  208.     p4=idxtab2[(((pxy[ 4]-acy)*l0)>>13)+8];
  209.     p5=idxtab2[(((pxy[ 5]-acy)*l0)>>13)+8];
  210.     p6=idxtab2[(((pxy[ 6]-acy)*l0)>>13)+8];
  211.     p7=idxtab2[(((pxy[ 7]-acy)*l0)>>13)+8];
  212.     block[2]=p0|(p1<<3)|(p2<<6);
  213.     block[3]=(p2>>2)|(p3<<1)|(p4<<4)|(p5<<7);
  214.     block[4]=(p5>>1)|(p6<<2)|(p7<<5);
  215.     p0=idxtab2[(((pxy[ 8]-acy)*l0)>>13)+8];
  216.     p1=idxtab2[(((pxy[ 9]-acy)*l0)>>13)+8];
  217.     p2=idxtab2[(((pxy[10]-acy)*l0)>>13)+8];
  218.     p3=idxtab2[(((pxy[11]-acy)*l0)>>13)+8];
  219.     p4=idxtab2[(((pxy[12]-acy)*l0)>>13)+8];
  220.     p5=idxtab2[(((pxy[13]-acy)*l0)>>13)+8];
  221.     p6=idxtab2[(((pxy[14]-acy)*l0)>>13)+8];
  222.     p7=idxtab2[(((pxy[15]-acy)*l0)>>13)+8];
  223.     block[5]=p0|(p1<<3)|(p2<<6);
  224.     block[6]=(p2>>2)|(p3<<1)|(p4<<4)|(p5<<7);
  225.     block[7]=(p5>>1)|(p6<<2)|(p7<<5);
  226.  
  227. //  if(czb<0) { k=mcu; mcu=ncu; ncu=k; }
  228.  
  229.     //Emit UVA Block
  230.     i=((mcu<<8)&0xF800) | ((mcv<<3)&0x07E0) | ((mca>>3)&0x001F);
  231.     j=((ncu<<8)&0xF800) | ((ncv<<3)&0x07E0) | ((nca>>3)&0x001F);
  232.     block[ 8]=i;    block[ 9]=i>>8;
  233.     block[10]=j;    block[11]=j>>8;
  234.  
  235.     p0=idxtab[(((pxz[ 0]-acz)*l1)>>13)+8];
  236.     p1=idxtab[(((pxz[ 1]-acz)*l1)>>13)+8];
  237.     p2=idxtab[(((pxz[ 2]-acz)*l1)>>13)+8];
  238.     p3=idxtab[(((pxz[ 3]-acz)*l1)>>13)+8];
  239.     block[12]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  240.     p0=idxtab[(((pxz[ 4]-acz)*l1)>>13)+8];
  241.     p1=idxtab[(((pxz[ 5]-acz)*l1)>>13)+8];
  242.     p2=idxtab[(((pxz[ 6]-acz)*l1)>>13)+8];
  243.     p3=idxtab[(((pxz[ 7]-acz)*l1)>>13)+8];
  244.     block[13]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  245.     p0=idxtab[(((pxz[ 8]-acz)*l1)>>13)+8];
  246.     p1=idxtab[(((pxz[ 9]-acz)*l1)>>13)+8];
  247.     p2=idxtab[(((pxz[10]-acz)*l1)>>13)+8];
  248.     p3=idxtab[(((pxz[11]-acz)*l1)>>13)+8];
  249.     block[14]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  250.     p0=idxtab[(((pxz[12]-acz)*l1)>>13)+8];
  251.     p1=idxtab[(((pxz[13]-acz)*l1)>>13)+8];
  252.     p2=idxtab[(((pxz[14]-acz)*l1)>>13)+8];
  253.     p3=idxtab[(((pxz[15]-acz)*l1)>>13)+8];
  254.     block[15]=(p3<<6)|(p2<<4)|(p1<<2)|p0;
  255. }
  256.  
  257. BGBBTJ_API void BGBBTJ_BCn_EncodeImageDXT5_UVAY(byte *block,
  258.     byte *rgba, int xs, int ys, int stride)
  259. {
  260.     int xs1, ys1;
  261.     int i, j;
  262.    
  263.     xs1=xs>>2; ys1=ys>>2;
  264.     for(i=0; i<ys1; i++)
  265.         for(j=0; j<xs1; j++)
  266.     {
  267.         BGBBTJ_BCn_EncodeBlockDXT5_UVAY(
  268.             block+(i*xs1+j)*16,
  269.             rgba+(i*4*xs+j*4)*stride,
  270.             stride, xs*stride, 4);
  271.     }
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement