Advertisement
cr88192

Lossy Block Reduction Filter 0

Mar 4th, 2013
187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.62 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. Lossy Block Reduction Filter.
  9.  
  10. Goal: Reduce the number of distinct pixel blocks such that subsequent compression of DXT output will compress better.
  11.  
  12. This is done as an image pre-filter rather than as part of the block-encoding process mostly to generalize over some of the subsequent encoding steps.
  13.  
  14. Note: May write over the edges or past the end of the image if it is not evenly divisible by the block size.
  15.  
  16. This estimates the block similarily mostly via MSE (Mean Square Error).
  17. Tests show that this will introduce blocky artifacts with gradients.
  18.  */
  19.  
  20. #include <bgbbtj.h>
  21.  
  22. // #define BLKSZ    8
  23. // #define BLKSZ    2
  24. #define BLKSZ   4
  25. #define BLKSZ2  (BLKSZ*BLKSZ)
  26.  
  27. int *filtlbr_block_vals;
  28. int *filtlbr_block_yval;
  29. byte *filtlbr_block_cvals;
  30. short *filtlbr_block_cyval;
  31. int *filtlbr_block_cnt;
  32. int filtlbr_n_blocks;
  33.  
  34. void BGBBTJ_FiltLBR_GetIndexBlock(int idx, byte *buf)
  35. {
  36.     int i, n;
  37.  
  38.     memcpy(buf, filtlbr_block_cvals+(idx*(BLKSZ2*4)), BLKSZ2*4);
  39. }
  40.  
  41. int BGBBTJ_FiltLBR_GetIndexBlockY(int idx)
  42. {
  43.     return(filtlbr_block_cyval[idx]);
  44. }
  45.  
  46. void BGBBTJ_FiltLBR_AddIndexBlock(int idx, byte *buf)
  47. {
  48.     int i, j, n;
  49.  
  50.     i=BGBBTJ_FiltLBR_CalcBlockY(buf);
  51.     filtlbr_block_yval[idx]+=i;
  52.  
  53.     for(i=0; i<(BLKSZ2*4); i++)
  54.     {
  55.         filtlbr_block_vals[idx*(BLKSZ2*4)+i]+=buf[i];
  56.     }
  57.     filtlbr_block_cnt[idx]++;
  58.  
  59.     n=filtlbr_block_cnt[idx];
  60.     j=filtlbr_block_yval[idx]/n;
  61.     filtlbr_block_cyval[idx]=j;
  62.  
  63.     for(i=0; i<(BLKSZ2*4); i++)
  64.     {
  65.         j=filtlbr_block_vals[idx*(BLKSZ2*4)+i]/n;
  66.         if(j<0)j=0;
  67.         if(j>255)j=255;
  68.         filtlbr_block_cvals[idx*(BLKSZ2*4)+i]=j;
  69.     }
  70.  
  71. #if 0
  72.     j=BGBBTJ_FiltLBR_CalcBlockY(filtlbr_block_cvals+(idx*(BLKSZ2*4)));
  73.     filtlbr_block_cyval[idx]=j;
  74. #endif
  75. }
  76.  
  77. int BGBBTJ_FiltLBR_CalcBlockY(byte *buf)
  78. {
  79.     int i, j, k;
  80.    
  81.     k=0;
  82.     for(i=0; i<BLKSZ2; i++)
  83.     {
  84.         j=buf[i*4+0]+2*buf[i*4+1]+buf[i*4+2]+(buf[i*4+3]>>1);
  85.         k+=j;
  86.     }
  87.     return(k/BLKSZ2);
  88. }
  89.  
  90. int BGBBTJ_FiltLBR_CompareBlock(byte *blka, byte *blkb)
  91. {
  92.     int i, j, n;
  93.    
  94.     n=0;
  95.     for(i=0; i<(BLKSZ2*4); i++)
  96.     {
  97.         j=blka[i]-blkb[i];
  98.         n+=j*j;
  99.     }
  100.     return(n/(BLKSZ2*4));
  101. }
  102.  
  103. int BGBBTJ_FiltLBR_GetImageBlock(
  104.     byte *img, int xstride, int ystride,
  105.     byte *block)
  106. {
  107.     int i, j;
  108.    
  109.     for(i=0; i<BLKSZ; i++)
  110.         for(j=0; j<BLKSZ; j++)
  111.     {
  112.         block[(i*BLKSZ+j)*4+0]=img[(i*ystride)+(j*xstride)+0];
  113.         block[(i*BLKSZ+j)*4+1]=img[(i*ystride)+(j*xstride)+1];
  114.         block[(i*BLKSZ+j)*4+2]=img[(i*ystride)+(j*xstride)+2];
  115.         block[(i*BLKSZ+j)*4+3]=img[(i*ystride)+(j*xstride)+3];
  116.     }
  117. }
  118.  
  119. int BGBBTJ_FiltLBR_SetImageBlock(
  120.     byte *img, int xstride, int ystride,
  121.     byte *block)
  122. {
  123.     int i, j;
  124.    
  125.     for(i=0; i<BLKSZ; i++)
  126.         for(j=0; j<BLKSZ; j++)
  127.     {
  128.         img[(i*ystride)+(j*xstride)+0]=block[(i*BLKSZ+j)*4+0];
  129.         img[(i*ystride)+(j*xstride)+1]=block[(i*BLKSZ+j)*4+1];
  130.         img[(i*ystride)+(j*xstride)+2]=block[(i*BLKSZ+j)*4+2];
  131.         img[(i*ystride)+(j*xstride)+3]=block[(i*BLKSZ+j)*4+3];
  132.     }
  133. }
  134.  
  135. int BGBBTJ_FiltLBR_LookupMatchIndexBlock(byte *blk, int mmse)
  136. {
  137.     byte tblk[BLKSZ2*4];
  138.     int bi, be;
  139.     int i, j, yv;
  140.    
  141.     yv=BGBBTJ_FiltLBR_CalcBlockY(blk);
  142.    
  143.     bi=-1; be=mmse;
  144.     for(i=0; i<filtlbr_n_blocks; i++)
  145.     {
  146.         j=BGBBTJ_FiltLBR_GetIndexBlockY(i);
  147.         j=j-yv; j=j*j;
  148.         if(j>be)continue;
  149.    
  150.         BGBBTJ_FiltLBR_GetIndexBlock(i, tblk);
  151.         j=BGBBTJ_FiltLBR_CompareBlock(tblk, blk);
  152.         if(j<be) { bi=i; be=j; }
  153.     }
  154.    
  155.     return(bi);
  156. }
  157.  
  158. int BGBBTJ_FiltLBR_GetMatchIndexBlock(byte *blk, int mmse)
  159. {
  160.     int i;
  161.    
  162.     i=BGBBTJ_FiltLBR_LookupMatchIndexBlock(blk, mmse);
  163.     if(i>=0)return(i);
  164.     i=filtlbr_n_blocks++;
  165.     BGBBTJ_FiltLBR_AddIndexBlock(i, blk);
  166.     return(i);
  167. }
  168.  
  169. /**
  170.  * Filter image, where irgba and orgba give the input and output images.
  171.  * xs and ys give the size, and qf gives the quality (low 8 bits, 0-100).
  172.  */
  173. BGBBTJ_API void BGBBTJ_FiltLBR_FilterImage(
  174.     byte *orgba, byte *irgba, int xs, int ys, int qf)
  175. {
  176.     byte tblk[BLKSZ2*4];
  177.     int *bidx;
  178.     int x, y, xs2, ys2, xstr, ystr;
  179.     int idx, idx1, mmse;
  180.    
  181.     if((qf&255)>=100)
  182.     {
  183.         memcpy(orgba, irgba, xs*ys*4);
  184.         return;
  185.     }
  186.  
  187.     printf("BGBBTJ_FiltLBR_FilterImage: Begin\n");
  188.  
  189.     xs2=(xs+BLKSZ-1)/BLKSZ;
  190.     ys2=(ys+BLKSZ-1)/BLKSZ;
  191.  
  192.     filtlbr_block_vals=malloc(xs2*ys2*(BLKSZ2*4)*sizeof(int));
  193.     filtlbr_block_yval=malloc(xs2*ys2*sizeof(int));
  194.     filtlbr_block_cnt=malloc(xs2*ys2*sizeof(int));
  195.     filtlbr_n_blocks=0;
  196.  
  197.     filtlbr_block_cvals=malloc(xs2*ys2*(BLKSZ2*4));
  198.     filtlbr_block_cyval=malloc(xs2*ys2*sizeof(short));
  199.  
  200.     memset(filtlbr_block_vals, 0, xs2*ys2*(BLKSZ2*4)*sizeof(int));
  201.     memset(filtlbr_block_yval, 0, xs2*ys2*sizeof(int));
  202.     memset(filtlbr_block_cnt, 0, xs2*ys2*sizeof(int));
  203.  
  204.     bidx=malloc(xs2*ys2*sizeof(int));
  205.  
  206.     xstr=4; ystr=xs*4;
  207. //  mmse=95-(qf&255);
  208. //  mmse=90-(qf&255);
  209. //  mmse=100-(qf&255);
  210. //  mmse=256-(qf&255);
  211.  
  212. //  mmse=1.0+10.0*(pow(100.0/(qf&255), 2)-1.0);
  213.     mmse=1.0+10.0*((100.0/(qf&255))-1.0);
  214.  
  215.     if(mmse<0)mmse=0;
  216.     mmse=mmse*mmse;
  217.  
  218.     for(y=0; y<ys2; y++)
  219.     {
  220.         printf("BGBBTJ_FiltLBR_FilterImage: %d/%d %d/%d\r",
  221.             y, ys2, filtlbr_n_blocks, y*xs2);
  222.         for(x=0; x<xs2; x++)
  223.         {
  224.             BGBBTJ_FiltLBR_GetImageBlock(irgba+(y*BLKSZ*ystr)+(x*BLKSZ*xstr),
  225.                 xstr, ystr, tblk);
  226.             idx=BGBBTJ_FiltLBR_GetMatchIndexBlock(tblk, mmse);
  227. //          BGBBTJ_FiltLBR_AddIndexBlock(idx, tblk);
  228.             bidx[y*xs2+x]=idx;
  229.         }
  230.  
  231.         printf("BGBBTJ_FiltLBR_FilterImage: %d/%d %d/%d\r",
  232.             y, ys2, filtlbr_n_blocks, y*xs2);
  233.     }
  234.     printf("\n");
  235.  
  236. #if 1
  237.     for(y=0; y<ys2; y++)
  238.     {
  239. //      printf("BGBBTJ_FiltLBR_FilterImage: %d/%d %d/%d\r",
  240. //          y, ys2, filtlbr_n_blocks, y*xs2);
  241.         for(x=0; x<xs2; x++)
  242.         {
  243.             BGBBTJ_FiltLBR_GetImageBlock(irgba+(y*BLKSZ*ystr)+(x*BLKSZ*xstr),
  244.                 xstr, ystr, tblk);
  245. //          idx=BGBBTJ_FiltLBR_GetMatchIndexBlock(tblk, mmse);
  246.             idx=bidx[y*xs2+x];
  247.             BGBBTJ_FiltLBR_AddIndexBlock(idx, tblk);
  248. //          bidx[y*xs2+x]=idx;
  249.         }
  250.  
  251. //      printf("BGBBTJ_FiltLBR_FilterImage: %d/%d %d/%d\r",
  252. //          y, ys2, filtlbr_n_blocks, y*xs2);
  253.     }
  254. //  printf("\n");
  255. #endif
  256.  
  257.     for(y=0; y<ys2; y++)
  258.         for(x=0; x<xs2; x++)
  259.     {
  260.         idx=bidx[y*xs2+x];
  261.  
  262. #if 0
  263.         printf("BGBBTJ_FiltLBR_FilterImage: %d/%d %d/%d\r",
  264.             y, ys2, filtlbr_n_blocks, y*xs2);
  265.  
  266.         BGBBTJ_FiltLBR_GetImageBlock(irgba+(y*BLKSZ*ystr)+(x*BLKSZ*xstr),
  267.             xstr, ystr, tblk);
  268. //      idx1=BGBBTJ_FiltLBR_LookupMatchIndexBlock(tblk, mmse);
  269.         idx1=BGBBTJ_FiltLBR_GetMatchIndexBlock(tblk, mmse);
  270.         if(idx1>=0)idx=idx1;
  271. #endif
  272.  
  273.         BGBBTJ_FiltLBR_GetIndexBlock(idx, tblk);
  274.         BGBBTJ_FiltLBR_SetImageBlock(orgba+(y*BLKSZ*ystr)+(x*BLKSZ*xstr),
  275.             xstr, ystr, tblk);
  276.     }
  277. //  printf("\n");
  278.    
  279.     free(bidx);
  280.     free(filtlbr_block_vals);
  281.     free(filtlbr_block_yval);
  282.     free(filtlbr_block_cvals);
  283.     free(filtlbr_block_cyval);
  284.     free(filtlbr_block_cnt);
  285.  
  286.     printf("BGBBTJ_FiltLBR_FilterImage: Done\n");
  287. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement