cr88192

Updated Packed DXTn Encoder

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