Advertisement
cr88192

Packed DXTn Encoder

Feb 20th, 2013
520
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.84 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. 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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement