Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Packed DXTn Encoder

By: cr88192 on Feb 20th, 2013  |  syntax: C  |  size: 4.84 KB  |  views: 23  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2. Copyright (C) 2013 by Brendan G Bohannon
  3. Email: cr88192@gmail.com
  4. Copying: http://pastebin.com/iJxtZHm6
  5.  */
  6.  
  7. /*
  8. DXTn packed images.
  9.  
  10. Each block tag will be encoded in the form (byte):
  11. 0 <block:QWORD>         Literal Block.
  12. 1-127                           Single byte block index.
  13. 128-191 X                       Two byte block index (16384 blocks).
  14. 192-223 XX                      Three byte block index (2097152 blocks).
  15. 224-238 I                       LZ/RLE Run (2-16 blocks, Index)
  16. 239             LI                      LZ/RLE Run (Length, Index)
  17. 240             XXX                     24-Bit Index
  18. 241             XXXX            32-Bit Index
  19. 242-246                         Literal Blocks (2-6 Blocks)
  20. 247             L                       Literal Blocks (L Blocks)
  21. 248-255                         Reserved
  22.  
  23. The block index will indicate how many blocks backwards to look for a matching block (1 will repeat the prior block).
  24.  
  25. Length/Index values will use the same organization as above, only limited to encoding numeric values.
  26.  
  27. 0-127                           0-127.
  28. 128-191 X                       128-16383.
  29. 192-223 XX                      16384-2097151.
  30. 240             XXX                     24-Bit Index (0-16777215)
  31. 241             XXXX            32-Bit Index (0-4294967295)
  32.  
  33. Note that DXT5 images will be split into 2 block-planes, with the first encoding the alpha component, followed by the plane encoding the RGB components.
  34. */
  35.  
  36. byte *BGBBTJ_PackBCn_EmitValue(byte *ct, int val)
  37. {
  38.         if(val<128)
  39.         {
  40.                 *ct++=val;
  41.                 return(ct);
  42.         }
  43.         if(val<16384)
  44.         {
  45.                 *ct++=128+(val>>8);
  46.                 *ct++=val;
  47.                 return(ct);
  48.         }
  49.         if(val<2097152)
  50.         {
  51.                 *ct++=128+(val>>16);
  52.                 *ct++=val>>8;
  53.                 *ct++=val;
  54.                 return(ct);
  55.         }
  56.         if(val<1677216)
  57.         {
  58.                 *ct++=240;
  59.                 *ct++=val>>16;
  60.                 *ct++=val>>8;
  61.                 *ct++=val;
  62.                 return(ct);
  63.         }
  64.         *ct++=241;
  65.         *ct++=val>>24;  *ct++=val>>16;
  66.         *ct++=val>>8;   *ct++=val;
  67.         return(ct);
  68. }
  69.  
  70. byte *BGBBTJ_PackBCn_EmitRun(byte *ct, int idx, int len)
  71. {
  72.         if(idx==0)
  73.         {
  74.                 if(len<2)
  75.                 {
  76.                         *ct++=0;
  77.                         return(ct);
  78.                 }
  79.                 if(len<7)
  80.                 {
  81.                         *ct++=242+(len-2);
  82.                         return(ct);
  83.                 }
  84.  
  85.                 *ct++=247;
  86.                 ct=BGBBTJ_PackBCn_EmitValue(ct, len);
  87.                 return(ct);
  88.         }
  89.  
  90.         if(len<2)
  91.         {
  92.                 ct=BGBBTJ_PackBCn_EmitValue(ct, idx);
  93.                 return(ct);
  94.         }
  95.  
  96.         if(len<=16)
  97.         {
  98.                 *ct++=224+(len-2);
  99.                 ct=BGBBTJ_PackBCn_EmitValue(ct, idx);
  100.                 return(ct);
  101.         }
  102.  
  103.         *ct++=239;
  104.         ct=BGBBTJ_PackBCn_EmitValue(ct, len);
  105.         ct=BGBBTJ_PackBCn_EmitValue(ct, idx);
  106.         return(ct);
  107. }
  108.  
  109. byte *BGBBTJ_PackBCn_EmitBlockValue(byte *ct, u64 block)
  110. {
  111.         *ct++=block;            *ct++=block>>8;
  112.         *ct++=block>>16;        *ct++=block>>24;
  113.         *ct++=block>>32;        *ct++=block>>40;
  114.         *ct++=block>>48;        *ct++=block>>56;
  115.         return(ct);
  116. }
  117.  
  118. u64 BGBBTJ_PackBCn_GetBlockValue(byte *cs)
  119. {
  120.         u32 t1, t2;
  121.         u64 tmp;
  122.         t1=cs[0] | (cs[1]<<8) | (cs[2]<<16) | (cs[3]<<24);
  123.         t2=cs[4] | (cs[5]<<8) | (cs[6]<<16) | (cs[7]<<24);
  124.         tmp=t1+(((u64)t2)<<32);
  125.         return(tmp);
  126. }
  127.  
  128. int BGBBTJ_PackBCn_LookupBlockSpan(
  129.         byte *css, byte *cs, byte *cse, int stride,
  130.         int *ridx, int *rlen, int max)
  131. {
  132.         u64 li, lj, lk;
  133.         int bi, bl, ci, cl;
  134.         byte *csi, *csj, *csk;
  135.        
  136.         li=BGBBTJ_PackBCn_GetBlockValue(cs);
  137.         csi=cs-stride; bi=0; bl=0;
  138.         while(csi>=css)
  139.         {
  140.                 lj=BGBBTJ_PackBCn_GetBlockValue(csi);
  141.                 if(li!=lj)
  142.                         { csi-=stride; continue; }
  143.                 csj=csi+stride;
  144.                 csk=cs+stride;
  145.                 while(csk<cse)
  146.                 {
  147.                         lj=BGBBTJ_PackBCn_GetBlockValue(csj);
  148.                         lk=BGBBTJ_PackBCn_GetBlockValue(csk);
  149.                         if(lj!=lk)break;
  150.                         csj+=stride; csk+=stride;
  151.                 }
  152.                
  153.                 ci=(cs-csi)/stride;
  154.                 cl=(csk-cs)/stride;
  155.                 if(cl>bl) { bi=ci; bl=cl; }
  156.                 if(bl>=max)break;
  157.                 csi-=stride;
  158.         }
  159.        
  160.         *ridx=bi;
  161.         *rlen=bl;
  162.         return(0);
  163. }
  164.  
  165. byte *BGBBTJ_PackBCn_EncodeBlockArray(byte *obuf, byte *blks,
  166.         int count, int stride)
  167. {
  168.         byte *cs, *cse, *ct, *cs1;
  169.         u64 li;
  170.         int i, bi, bl, bi1, bl1;
  171.        
  172.         ct=obuf;
  173.         cs=blks; cse=blks+count*stride;
  174.         while(cs<cse)
  175.         {
  176.                 BGBBTJ_PackBCn_LookupBlockSpan(blks, cs, cse, stride,
  177.                         &bi, &bl, 65536);
  178.  
  179. #if 1
  180.                 if(bi==0)
  181.                 {
  182.                         bl=1; cs1=cs+stride;
  183.                         while(cs1<cse)
  184.                         {
  185.                                 BGBBTJ_PackBCn_LookupBlockSpan(blks, cs1, cse,
  186.                                         stride, &bi1, &bl1, 1);
  187.                                 if(bi1>0)break;
  188.                                 bl++;
  189.                                 cs1=cs+bl*stride;
  190.                         }
  191.                 }
  192. #endif
  193.  
  194.                 if(bi<1)
  195.                 {
  196.                         if(bl<2)
  197.                         {
  198.                                 *ct++=0;
  199.                                 li=BGBBTJ_PackBCn_GetBlockValue(cs);
  200.                                 ct=BGBBTJ_PackBCn_EmitBlockValue(ct, li);
  201.                                 cs+=stride;
  202.                                 continue;
  203.                         }
  204.                         ct=BGBBTJ_PackBCn_EmitRun(ct, 0, bl);
  205.                         for(i=0; i<bl; i++)
  206.                         {
  207.                                 li=BGBBTJ_PackBCn_GetBlockValue(cs);
  208.                                 ct=BGBBTJ_PackBCn_EmitBlockValue(ct, li);
  209.                                 cs+=stride;
  210.                         }
  211.                         continue;
  212.                 }
  213.                 ct=BGBBTJ_PackBCn_EmitRun(ct, bi, bl);
  214.                 cs+=bl*stride;
  215.         }
  216.         return(ct);
  217. }
  218.  
  219. BGBBTJ_API int BGBBTJ_PackBCn_EncodeBlocksDXT5(
  220.         byte *obuf, byte *blks, int count)
  221. {
  222.         byte *ct;
  223.         ct=BGBBTJ_PackBCn_EncodeBlockArray(obuf, blks, count, 16);
  224.         ct=BGBBTJ_PackBCn_EncodeBlockArray(ct, blks+8, count, 16);
  225.         return(ct-obuf);
  226. }
clone this paste RAW Paste Data