home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 3 / RISC_DISC_3.iso / resources / etexts / gems / gemsiii / rgbvaryw.c < prev    next >
C/C++ Source or Header  |  1993-05-26  |  5KB  |  208 lines

  1. /*
  2.     rgbvaryW.c - an improved rgbvary.c, currently runs on Microsoft Windows
  3.  
  4.     The color reduction filter (rgbvary.c) uses floating point but none 
  5.     of the computations exceed a 16bit integer.  I've rewritten the code to 
  6.     use 16 bit integers (with no loss of precision), updated jitter_init to 
  7.     precompute the scaled values used in the inner loop, and allowed the 
  8.     code to output a C include file with the table values filled in.  The 
  9.     combined savings reduced the filter time on a 1024x768x24bit image from 
  10.     24 seconds to 3 seconds, reduced the table size by 12K (1/3 the 
  11.     original size), and removed 18K of runtime support for floating point 
  12.     emulation, the rand() library, etc.
  13.  
  14.     From: Ken Sykes <kensy@microsoft.com>
  15. */
  16.  
  17. /****************************************************************************
  18.      rgbvaryI.c - a color quantization pre-processor
  19.  
  20. ****************************************************************************/
  21.  
  22. /* remove the next line after the first run */
  23. #define GENTABLE 1
  24.  
  25. #ifndef GENTABLE
  26. #include "rgbvtab.h"
  27. #endif
  28.  
  29. #define JITTER_TABLE_BITS   10
  30. #define JITTER_TABLE_SIZE   (1<<JITTER_TABLE_BITS)
  31. #define JITTER_MASK         (JITTER_TABLE_SIZE-1)
  32.  
  33. /* jitter macros */
  34. #define jitterx(x,y,s) \
  35. (uranx[((x+(y<<2))+irand[(x+s)&JITTER_MASK])&JITTER_MASK])
  36. #define jittery(x,y,s) \
  37. (urany[((y+(x<<2))+irand[(y+s)&JITTER_MASK])&JITTER_MASK])
  38.  
  39. #ifdef GENTABLE
  40.  
  41. /* global varables */
  42. int irand[JITTER_TABLE_SIZE];    /* jitter look-up table */
  43. int uranx[JITTER_TABLE_SIZE];    /* jitter look-up table */
  44. int urany[JITTER_TABLE_SIZE];    /* jitter look-up table */
  45.  
  46. #include <stdio.h>
  47.  
  48.  
  49. void print_tables(void)
  50. {
  51.     FILE *fp;
  52.     int i;
  53.  
  54.     fp = fopen("rgbvtab.h","w");
  55.  
  56.     fprintf(fp, "int irand[%d] = {", JITTER_TABLE_SIZE);
  57.     for (i = 0; i < JITTER_TABLE_SIZE; ++i)
  58.     {
  59.         if (!(i % 8)) fprintf(fp, "\n\t");
  60.         fprintf(fp, "%d,", irand[i]);
  61.     }
  62.     fprintf(fp, "\n};\n");
  63.  
  64.     fprintf(fp, "int uranx[%d] = {", JITTER_TABLE_SIZE);
  65.     for (i = 0; i < JITTER_TABLE_SIZE; ++i)
  66.     {
  67.         if (!(i % 8)) fprintf(fp, "\n\t");
  68.         fprintf(fp, "%d,", uranx[i]);
  69.     }
  70.     fprintf(fp, "\n};\n");
  71.  
  72.     fprintf(fp, "int urany[%d] = {", JITTER_TABLE_SIZE);
  73.     for (i = 0; i < JITTER_TABLE_SIZE; ++i)
  74.     {
  75.         if (!(i % 8)) fprintf(fp, "\n\t");
  76.         fprintf(fp, "%d,", urany[i]);
  77.     }
  78.     fprintf(fp, "\n};\n");
  79.  
  80.     fclose(fp);
  81. }
  82.  
  83.  
  84. /* function declarations */
  85. void jitter_init();
  86.  
  87. /*
  88. *
  89. * name        jitter_init - initialize jitter look-up tables
  90. *
  91. *             Adapted from Graphic Gems I (Cyshosz, page 64).
  92. *
  93. * notes       This function should be called once before any call to
  94. *             rgbvary()
  95. *
  96. */
  97.  
  98. void jitter_init()
  99. {
  100.     int i,urand;
  101.  
  102. /* magnitude of noise generated (0,1,2 allowed values) */
  103. #define NOISE_LEVEL 2
  104.  
  105.     /* determine order to fill table in */
  106.     for (i = 0; i < JITTER_TABLE_SIZE; ++i)
  107.         irand[i] = rand() % JITTER_TABLE_SIZE;
  108.  
  109.     /* fill in the X table */
  110.     for (i = 0; i < JITTER_TABLE_SIZE; ++i)
  111.     {
  112.         uranx[i] = urand = rand() % JITTER_TABLE_SIZE;
  113.         uranx[i] = ((urand << 3) + urand) >> JITTER_TABLE_BITS;
  114.     }
  115.  
  116.     /* fill in the Y table */
  117.     for (i = 0; i < JITTER_TABLE_SIZE; ++i)
  118.     {
  119.         urany[i] = urand = rand() % JITTER_TABLE_SIZE;
  120.         urany[i] = ((((urand * NOISE_LEVEL * 2) + JITTER_TABLE_SIZE/2)
  121.                      >> JITTER_TABLE_BITS) - NOISE_LEVEL) << 3;
  122.     }
  123.  
  124.     print_tables();
  125. }
  126. #endif
  127.  
  128. BOOL VaryDIB24(HANDLE hdib)
  129. {
  130.     LPBITMAPINFOHEADER lpbi;
  131.     HPBYTE hpbyBits;
  132.     WORD wNextScan;
  133.     int x,y;
  134.  
  135.     /* Get pointer to bits */
  136.     if (!hdib) return FALSE;
  137.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
  138.     GlobalUnlock(hdib);
  139.  
  140.     if (lpbi->biBitCount != 24)
  141.     {
  142.        ErrMsg("Jitter only applies to 24bpp images.");
  143.        return FALSE;
  144.     }
  145.  
  146.     /* Make sure it is not compressed */
  147.     if (lpbi->biCompression != BI_RGB)
  148.     {
  149.        ErrMsg("Jitter only works on uncompressed images.");
  150.        return FALSE;
  151.     }
  152.  
  153. #ifdef GENTABLE
  154.     jitter_init();
  155. #endif
  156.  
  157.     hpbyBits = (HPBYTE)DibXY(lpbi,0,0);
  158.  
  159.     /* DIBs are DWORD-aligned.  Determine amount of padding for each 
  160. scanline */
  161.     wNextScan = (WORD)(((lpbi->biWidth << 1)+lpbi->biWidth) & 3);
  162.     if (wNextScan) wNextScan = (WORD)(4-wNextScan);
  163.  
  164.     /* Loop through the image & apply the jitter */
  165.     for (y = 0; y < lpbi->biHeight; ++y)
  166.     {
  167.         for (x = 0; x < lpbi->biWidth; ++x)
  168.         {
  169.             int i, p, q;
  170.  
  171.             for (i = 0; i < 3; ++i)
  172.             {
  173.                 int rgb;
  174.  
  175.                 rgb = (int)*hpbyBits;
  176.  
  177.                 if (rgb < 248)
  178.                 {
  179.                    /* bump up to next intensity if there is enough jitter */
  180.                    p = rgb & 7;
  181.                    q = jitterx(x, y, i);
  182.                    if (p <= q)
  183.                       rgb += 8;
  184.  
  185.                    /* add some noise */
  186.                    q = rgb + jittery(x, y, i);
  187.  
  188.                    /* make sure resulting intensity is within allowable 
  189. range */
  190.                    if (q >= 0 && q <= 255)
  191.                       rgb = q;
  192.  
  193.                    /* mask off lower 3 bits & store */
  194.                    *hpbyBits = rgb & 0xf8;
  195.                 }
  196.  
  197.                 /* update pointer */
  198.                 ++hpbyBits;
  199.             }
  200.         }
  201.  
  202.         /* move pointer to next scan */
  203.         hpbyBits += wNextScan;
  204.     }
  205.  
  206.     return TRUE;
  207. }
  208.