Advertisement
cr88192

Updated Packed DXTn Encoder

Mar 4th, 2013
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.34 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. #include <bgbbtj.h>
  37.  
  38. byte *BGBBTJ_PackBCn_EmitValue(byte *ct, int val)
  39. {
  40.     if(val<128)
  41.     {
  42.         *ct++=val;
  43.         return(ct);
  44.     }
  45.     if(val<16384)
  46.     {
  47.         *ct++=128+(val>>8);
  48.         *ct++=val;
  49.         return(ct);
  50.     }
  51.     if(val<2097152)
  52.     {
  53.         *ct++=192+(val>>16);
  54.         *ct++=val>>8;
  55.         *ct++=val;
  56.         return(ct);
  57.     }
  58.     if(val<1677216)
  59.     {
  60.         *ct++=240;
  61.         *ct++=val>>16;
  62.         *ct++=val>>8;
  63.         *ct++=val;
  64.         return(ct);
  65.     }
  66.     *ct++=241;
  67.     *ct++=val>>24;  *ct++=val>>16;
  68.     *ct++=val>>8;   *ct++=val;
  69.     return(ct);
  70. }
  71.  
  72. byte *BGBBTJ_PackBCn_EmitRun(byte *ct, int idx, int len)
  73. {
  74.     if(idx==0)
  75.     {
  76.         if(len<2)
  77.         {
  78.             *ct++=0;
  79.             return(ct);
  80.         }
  81.         if(len<7)
  82.         {
  83.             *ct++=242+(len-2);
  84.             return(ct);
  85.         }
  86.  
  87.         *ct++=247;
  88.         ct=BGBBTJ_PackBCn_EmitValue(ct, len);
  89.         return(ct);
  90.     }
  91.  
  92.     if(len<2)
  93.     {
  94.         ct=BGBBTJ_PackBCn_EmitValue(ct, idx);
  95.         return(ct);
  96.     }
  97.  
  98.     if(len<=16)
  99.     {
  100.         *ct++=224+(len-2);
  101.         ct=BGBBTJ_PackBCn_EmitValue(ct, idx);
  102.         return(ct);
  103.     }
  104.  
  105.     *ct++=239;
  106.     ct=BGBBTJ_PackBCn_EmitValue(ct, len);
  107.     ct=BGBBTJ_PackBCn_EmitValue(ct, idx);
  108.     return(ct);
  109. }
  110.  
  111. byte *BGBBTJ_PackBCn_EmitBlockValue(byte *ct, u64 block)
  112. {
  113.     *ct++=block;        *ct++=block>>8;
  114.     *ct++=block>>16;    *ct++=block>>24;
  115.     *ct++=block>>32;    *ct++=block>>40;
  116.     *ct++=block>>48;    *ct++=block>>56;
  117.     return(ct);
  118. }
  119.  
  120. u64 BGBBTJ_PackBCn_GetBlockValue(byte *cs)
  121. {
  122.     u32 t1, t2;
  123.     u64 tmp;
  124. #if defined(X86) || defined(X86_64)
  125.     return(*(u64 *)cs);
  126. #else
  127.     t1=cs[0] | (cs[1]<<8) | (cs[2]<<16) | (cs[3]<<24);
  128.     t2=cs[4] | (cs[5]<<8) | (cs[6]<<16) | (cs[7]<<24);
  129.     tmp=t1+(((u64)t2)<<32);
  130. #endif
  131.     return(tmp);
  132. }
  133.  
  134. int BGBBTJ_PackBCn_LookupBlockSpan(
  135.     byte *css, byte *cs, byte *cse, int stride,
  136.     int *blkchn, int *blkhash,
  137.     int *ridx, int *rlen, int max)
  138. {
  139.     u64 li, lj, lk;
  140.     int bi, bl, ci, cl, shr;
  141.     byte *csi, *csj, *csk;
  142.     int i;
  143.  
  144.     switch(stride)
  145.     {
  146.     case 4: shr=2; break;
  147.     case 8: shr=3; break;
  148.     case 16: shr=4; break;
  149.     case 32: shr=5; break;
  150.     case 64: shr=6; break;
  151.     }
  152.  
  153.     li=BGBBTJ_PackBCn_GetBlockValue(cs);
  154.    
  155. //  lj=li*2147483647*127*127;
  156.     lj=li*187284906682965LL;
  157. //  ci=(lj>>48)&4095;
  158.     ci=(lj>>48)&65535;
  159.     i=blkhash[ci];
  160.  
  161.     if(i<=0) {  *ridx=0; *rlen=0; return(0); }
  162.  
  163.     csi=css+i*stride;
  164.    
  165. //  csi=cs-stride;
  166.     bi=0; bl=0;
  167.  
  168.     while(csi>=css)
  169.     {
  170.         lj=BGBBTJ_PackBCn_GetBlockValue(csi);
  171.         if(li!=lj)
  172.             { csi-=stride; continue; }
  173.         csj=csi+stride;
  174.         csk=cs+stride;
  175.         while(csk<cse)
  176.         {
  177.             lj=BGBBTJ_PackBCn_GetBlockValue(csj);
  178.             lk=BGBBTJ_PackBCn_GetBlockValue(csk);
  179.             if(lj!=lk)break;
  180.             csj+=stride; csk+=stride;
  181.         }
  182.        
  183. //      ci=(cs-csi)/stride;
  184. //      cl=(csk-cs)/stride;
  185.         ci=(cs-csi)>>shr;
  186.         cl=(csk-cs)>>shr;
  187.         if(cl>bl) { bi=ci; bl=cl; }
  188.         if(bl>=max)break;
  189. //      csi-=stride;
  190.  
  191. //      if((ci>1024) && (bl>=256))
  192. //          break;
  193. //      if((ci>4096) && (bl>=64))
  194. //          break;
  195.  
  196. //      if((ci*bl)>65536)
  197. //          break;
  198.  
  199. //      i=blkchn[(cs-css)/stride];
  200.         i=blkchn[(cs-css)>>shr];
  201.         if(i<=0)break;
  202.         csi-=i*stride;
  203.     }
  204.    
  205.     *ridx=bi;
  206.     *rlen=bl;
  207.     return(0);
  208. }
  209.  
  210. int BGBBTJ_PackBCn_UpdateBlockSpan(
  211.     byte *css, byte *cs, byte *cse, int stride,
  212.     int *blkchn, int *blkhash, int len)
  213. {
  214.     u64 li, lj;
  215.     byte *cs1;
  216.     int ci, cj;
  217.     int i, j, k;
  218.  
  219.     for(i=0; i<len; i++)
  220.     {
  221.         cs1=cs+i*stride;
  222.         li=BGBBTJ_PackBCn_GetBlockValue(cs1);
  223.         lj=li*187284906682965LL;
  224. //      ci=(lj>>48)&4095;
  225.         ci=(lj>>48)&65535;
  226.        
  227.         cj=(cs1-css)/stride;
  228.         k=cj-blkhash[ci];
  229.         blkchn[cj]=k;
  230.         blkhash[ci]=cj;
  231.     }
  232. }
  233.  
  234. byte *BGBBTJ_PackBCn_EncodeBlockArray(byte *obuf, byte *blks,
  235.     int count, int stride)
  236. {
  237.     byte *cs, *cse, *ct, *cs1;
  238.     int *blkchn, *blkhash;
  239.     u64 li;
  240.     int i, bi, bl, bi1, bl1;
  241.    
  242.     blkchn=malloc(count*sizeof(int));
  243.     blkhash=malloc(65536*sizeof(int));
  244.     memset(blkchn, 0, count*sizeof(int));
  245.     memset(blkhash, 0, 65536*sizeof(int));
  246.    
  247.     ct=obuf;
  248.     cs=blks; cse=blks+count*stride;
  249.     while(cs<cse)
  250.     {
  251.         BGBBTJ_PackBCn_LookupBlockSpan(blks, cs, cse, stride,
  252.             blkchn, blkhash,
  253.             &bi, &bl, 65536);
  254.  
  255. #if 1
  256.         if(bi==0)
  257.         {
  258.             bl=1; cs1=cs+stride;
  259. //          while((cs1<cse) && (bl<6))
  260. //          while(cs1<cse)
  261.             while((cs1<cse) && (bl<256))
  262.             {
  263.                 BGBBTJ_PackBCn_LookupBlockSpan(
  264.                     blks, cs1, cse, stride,
  265.                     blkchn, blkhash,
  266.                     &bi1, &bl1, 1);
  267.                 if(bi1>0)break;
  268.                 bl++;
  269.                 cs1=cs+bl*stride;
  270.             }
  271.         }
  272. #endif
  273.  
  274.         BGBBTJ_PackBCn_UpdateBlockSpan(blks, cs, cse, stride,
  275.             blkchn, blkhash, bl);
  276.  
  277.         if(bi<1)
  278.         {
  279.             if(bl<2)
  280.             {
  281.                 *ct++=0;
  282.                 li=BGBBTJ_PackBCn_GetBlockValue(cs);
  283.                 ct=BGBBTJ_PackBCn_EmitBlockValue(ct, li);
  284.                 cs+=stride;
  285.                 continue;
  286.             }
  287.             ct=BGBBTJ_PackBCn_EmitRun(ct, 0, bl);
  288.             for(i=0; i<bl; i++)
  289.             {
  290.                 li=BGBBTJ_PackBCn_GetBlockValue(cs);
  291.                 ct=BGBBTJ_PackBCn_EmitBlockValue(ct, li);
  292.                 cs+=stride;
  293.             }
  294.             continue;
  295.         }
  296.         ct=BGBBTJ_PackBCn_EmitRun(ct, bi, bl);
  297.         cs+=bl*stride;
  298.     }
  299.    
  300.     free(blkchn);
  301.     free(blkhash);
  302.    
  303.     return(ct);
  304. }
  305.  
  306. BGBBTJ_API int BGBBTJ_PackBCn_EncodeBlocksDXT1(
  307.     byte *obuf, byte *blks, int count)
  308. {
  309.     byte *ct;
  310.     ct=BGBBTJ_PackBCn_EncodeBlockArray(obuf, blks, count, 8);
  311.     return(ct-obuf);
  312. }
  313.  
  314. BGBBTJ_API int BGBBTJ_PackBCn_EncodeBlocksDXT5(
  315.     byte *obuf, byte *blks, int count)
  316. {
  317.     byte *ct;
  318.     ct=BGBBTJ_PackBCn_EncodeBlockArray(obuf, blks, count, 16);
  319.     ct=BGBBTJ_PackBCn_EncodeBlockArray(ct, blks+8, count, 16);
  320.     return(ct-obuf);
  321. }
  322.  
  323. byte *BGBBTJ_PackBCn_DecodeValue(byte *cs, int *rval)
  324. {
  325.     int op, i;
  326.    
  327.     op=*cs++;
  328.     if(op<128)
  329.         { *rval=op; return(cs); }
  330.     if(op<192)
  331.     {
  332.         *rval=((op-128)<<8)|(*cs++);
  333.         return(cs);
  334.     }
  335.     if(op<224)
  336.     {
  337.         i=((op-192)<<8)|(*cs++);
  338.         i=(i<<8)|(*cs++);
  339.         *rval=i;
  340.         return(cs);
  341.     }
  342.  
  343.     if(op==240)
  344.     {
  345.         i=*cs++;
  346.         i=(i<<8)|(*cs++);
  347.         i=(i<<8)|(*cs++);
  348.         *rval=i;
  349.         return(cs);
  350.     }
  351.     if(op==241)
  352.     {
  353.         i=*cs++;            i=(i<<8)|(*cs++);
  354.         i=(i<<8)|(*cs++);   i=(i<<8)|(*cs++);
  355.         *rval=i;
  356.         return(cs);
  357.     }
  358.  
  359.     return(cs);
  360. }
  361.  
  362. byte *BGBBTJ_PackBCn_DecodeRun(byte *cs, int *ridx, int *rlen)
  363. {
  364.     int op, i;
  365.    
  366.     op=*cs++;
  367.     if(!op)
  368.         { *ridx=0; *rlen=0; return(cs); }
  369.     if(op<128)
  370.         { *ridx=op; *rlen=1; return(cs); }
  371.     if(op<192)
  372.     {
  373.         *ridx=((op-128)<<8)|(*cs++);
  374.         *rlen=1;
  375.         return(cs);
  376.     }
  377.     if(op<224)
  378.     {
  379.         i=((op-192)<<8)|(*cs++);
  380.         i=(i<<8)|(*cs++);
  381.         *ridx=i;
  382.         *rlen=1;
  383.         return(cs);
  384.     }
  385.     if(op<239)
  386.     {
  387.         cs=BGBBTJ_PackBCn_DecodeValue(cs, ridx);
  388.         *rlen=(op-224)+2;
  389.         return(cs);
  390.     }
  391.     if(op==239)
  392.     {
  393.         cs=BGBBTJ_PackBCn_DecodeValue(cs, rlen);
  394.         cs=BGBBTJ_PackBCn_DecodeValue(cs, ridx);
  395.         return(cs);
  396.     }
  397.     if(op==240)
  398.     {
  399.         i=*cs++;
  400.         i=(i<<8)|(*cs++);
  401.         i=(i<<8)|(*cs++);
  402.         *ridx=i;
  403.         *rlen=1;
  404.         return(cs);
  405.     }
  406.     if(op==241)
  407.     {
  408.         i=*cs++;            i=(i<<8)|(*cs++);
  409.         i=(i<<8)|(*cs++);   i=(i<<8)|(*cs++);
  410.         *ridx=i;
  411.         *rlen=1;
  412.         return(cs);
  413.     }
  414.  
  415.     if(op<247)
  416.     {
  417.         *ridx=0;
  418.         *rlen=(op-242)+2;
  419.         return(cs);
  420.     }
  421.     if(op==247)
  422.     {
  423.         *ridx=0;
  424.         cs=BGBBTJ_PackBCn_DecodeValue(cs, rlen);
  425.         return(cs);
  426.     }
  427.  
  428.     *ridx=0; *rlen=0;
  429.     return(cs);
  430. }
  431.  
  432. byte *BGBBTJ_PackBCn_DecodeBlockArray(byte *ibuf, byte *blks,
  433.     int count, int stride)
  434. {
  435.     byte *cs, *ct, *cte, *cs1, *ct1, *cs1e;
  436.     byte *cs0, *cs0a, *cs0b, *cs0c, *cs0d;
  437.     int bi, bl;
  438.     int i, j;
  439.  
  440.     cs=ibuf; ct=blks; cte=ct+count*stride;
  441.     while(ct<cte)
  442.     {
  443.         cs0d=cs0c; cs0c=cs0b; cs0b=cs0a; cs0a=cs0; cs0=cs;
  444.         cs=BGBBTJ_PackBCn_DecodeRun(cs, &bi, &bl);
  445.         if(bi==0)
  446.         {
  447.             if(bl>1)
  448.             {
  449. #if defined(X86) || defined(X86_64)
  450.                 cs1e=cs+bl*8;
  451.                 while(cs<cs1e)
  452.                 {
  453.                     *(u64 *)ct=*(u64 *)(cs);
  454.                     cs+=8; ct+=stride;
  455.                 }
  456. #else
  457.                 for(i=0; i<bl; i++)
  458.                     { memcpy(ct+i*stride, cs+i*8, 8); }
  459.                 cs+=bl*8;
  460.                 ct+=bl*stride;
  461. #endif
  462.                 continue;
  463.             }
  464. #if defined(X86) || defined(X86_64)
  465.             *(u64 *)ct=*(u64 *)cs;
  466. #else
  467.             memcpy(ct, cs, 8);
  468. #endif
  469.             ct+=stride; cs+=8;
  470.             continue;
  471.         }
  472.  
  473. #if defined(X86) || defined(X86_64)
  474.         cs1=ct-bi*stride;
  475.         cs1e=cs1+bl*stride;
  476.         while(cs1<cs1e)
  477.         {
  478.             *(u64 *)ct=*(u64 *)(cs1);
  479.             cs1+=stride; ct+=stride;
  480.         }
  481. #else
  482.         for(i=0; i<bl; i++)
  483.             { memcpy(ct+i*stride, ct+(i-bi)*stride, 8); }
  484.         ct+=bl*stride;
  485. #endif
  486.     }
  487.     return(cs);
  488. }
  489.  
  490. BGBBTJ_API int BGBBTJ_PackBCn_DecodeBlocksDXT1(
  491.     byte *ibuf, byte *blks, int count)
  492. {
  493.     byte *cs;
  494.     cs=BGBBTJ_PackBCn_DecodeBlockArray(ibuf, blks, count, 8);
  495.     return(cs-ibuf);
  496. }
  497.  
  498. BGBBTJ_API int BGBBTJ_PackBCn_DecodeBlocksDXT5(
  499.     byte *ibuf, byte *blks, int count)
  500. {
  501.     byte *cs;
  502.     cs=BGBBTJ_PackBCn_DecodeBlockArray(ibuf, blks, count, 16);
  503.     cs=BGBBTJ_PackBCn_DecodeBlockArray(cs, blks+8, count, 16);
  504.     return(cs-ibuf);
  505. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement