Advertisement
cr88192

Experimental DXT5-UVAY Encoder.

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