home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
RISC DISC 3
/
RISC_DISC_3.iso
/
resources
/
etexts
/
gems
/
gemsiii
/
rgbvaryw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-26
|
5KB
|
208 lines
/*
rgbvaryW.c - an improved rgbvary.c, currently runs on Microsoft Windows
The color reduction filter (rgbvary.c) uses floating point but none
of the computations exceed a 16bit integer. I've rewritten the code to
use 16 bit integers (with no loss of precision), updated jitter_init to
precompute the scaled values used in the inner loop, and allowed the
code to output a C include file with the table values filled in. The
combined savings reduced the filter time on a 1024x768x24bit image from
24 seconds to 3 seconds, reduced the table size by 12K (1/3 the
original size), and removed 18K of runtime support for floating point
emulation, the rand() library, etc.
From: Ken Sykes <kensy@microsoft.com>
*/
/****************************************************************************
rgbvaryI.c - a color quantization pre-processor
****************************************************************************/
/* remove the next line after the first run */
#define GENTABLE 1
#ifndef GENTABLE
#include "rgbvtab.h"
#endif
#define JITTER_TABLE_BITS 10
#define JITTER_TABLE_SIZE (1<<JITTER_TABLE_BITS)
#define JITTER_MASK (JITTER_TABLE_SIZE-1)
/* jitter macros */
#define jitterx(x,y,s) \
(uranx[((x+(y<<2))+irand[(x+s)&JITTER_MASK])&JITTER_MASK])
#define jittery(x,y,s) \
(urany[((y+(x<<2))+irand[(y+s)&JITTER_MASK])&JITTER_MASK])
#ifdef GENTABLE
/* global varables */
int irand[JITTER_TABLE_SIZE]; /* jitter look-up table */
int uranx[JITTER_TABLE_SIZE]; /* jitter look-up table */
int urany[JITTER_TABLE_SIZE]; /* jitter look-up table */
#include <stdio.h>
void print_tables(void)
{
FILE *fp;
int i;
fp = fopen("rgbvtab.h","w");
fprintf(fp, "int irand[%d] = {", JITTER_TABLE_SIZE);
for (i = 0; i < JITTER_TABLE_SIZE; ++i)
{
if (!(i % 8)) fprintf(fp, "\n\t");
fprintf(fp, "%d,", irand[i]);
}
fprintf(fp, "\n};\n");
fprintf(fp, "int uranx[%d] = {", JITTER_TABLE_SIZE);
for (i = 0; i < JITTER_TABLE_SIZE; ++i)
{
if (!(i % 8)) fprintf(fp, "\n\t");
fprintf(fp, "%d,", uranx[i]);
}
fprintf(fp, "\n};\n");
fprintf(fp, "int urany[%d] = {", JITTER_TABLE_SIZE);
for (i = 0; i < JITTER_TABLE_SIZE; ++i)
{
if (!(i % 8)) fprintf(fp, "\n\t");
fprintf(fp, "%d,", urany[i]);
}
fprintf(fp, "\n};\n");
fclose(fp);
}
/* function declarations */
void jitter_init();
/*
*
* name jitter_init - initialize jitter look-up tables
*
* Adapted from Graphic Gems I (Cyshosz, page 64).
*
* notes This function should be called once before any call to
* rgbvary()
*
*/
void jitter_init()
{
int i,urand;
/* magnitude of noise generated (0,1,2 allowed values) */
#define NOISE_LEVEL 2
/* determine order to fill table in */
for (i = 0; i < JITTER_TABLE_SIZE; ++i)
irand[i] = rand() % JITTER_TABLE_SIZE;
/* fill in the X table */
for (i = 0; i < JITTER_TABLE_SIZE; ++i)
{
uranx[i] = urand = rand() % JITTER_TABLE_SIZE;
uranx[i] = ((urand << 3) + urand) >> JITTER_TABLE_BITS;
}
/* fill in the Y table */
for (i = 0; i < JITTER_TABLE_SIZE; ++i)
{
urany[i] = urand = rand() % JITTER_TABLE_SIZE;
urany[i] = ((((urand * NOISE_LEVEL * 2) + JITTER_TABLE_SIZE/2)
>> JITTER_TABLE_BITS) - NOISE_LEVEL) << 3;
}
print_tables();
}
#endif
BOOL VaryDIB24(HANDLE hdib)
{
LPBITMAPINFOHEADER lpbi;
HPBYTE hpbyBits;
WORD wNextScan;
int x,y;
/* Get pointer to bits */
if (!hdib) return FALSE;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
GlobalUnlock(hdib);
if (lpbi->biBitCount != 24)
{
ErrMsg("Jitter only applies to 24bpp images.");
return FALSE;
}
/* Make sure it is not compressed */
if (lpbi->biCompression != BI_RGB)
{
ErrMsg("Jitter only works on uncompressed images.");
return FALSE;
}
#ifdef GENTABLE
jitter_init();
#endif
hpbyBits = (HPBYTE)DibXY(lpbi,0,0);
/* DIBs are DWORD-aligned. Determine amount of padding for each
scanline */
wNextScan = (WORD)(((lpbi->biWidth << 1)+lpbi->biWidth) & 3);
if (wNextScan) wNextScan = (WORD)(4-wNextScan);
/* Loop through the image & apply the jitter */
for (y = 0; y < lpbi->biHeight; ++y)
{
for (x = 0; x < lpbi->biWidth; ++x)
{
int i, p, q;
for (i = 0; i < 3; ++i)
{
int rgb;
rgb = (int)*hpbyBits;
if (rgb < 248)
{
/* bump up to next intensity if there is enough jitter */
p = rgb & 7;
q = jitterx(x, y, i);
if (p <= q)
rgb += 8;
/* add some noise */
q = rgb + jittery(x, y, i);
/* make sure resulting intensity is within allowable
range */
if (q >= 0 && q <= 255)
rgb = q;
/* mask off lower 3 bits & store */
*hpbyBits = rgb & 0xf8;
}
/* update pointer */
++hpbyBits;
}
}
/* move pointer to next scan */
hpbyBits += wNextScan;
}
return TRUE;
}