📄 rgbvaryw.c
字号:
/* 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();}#endifBOOL 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -