⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hot.c

📁 [Game.Programming].Academic - Graphics Gems (6 books source code)
💻 C
字号:
/* * hot.c - Scan an image for pixels with RGB values that will give *	"unsafe" values of chrominance signal or composite signal *	amplitude when encoded into an NTSC or PAL colour signal. *	(This happens for certain high-intensity high-saturation colours *	that are rare in real scenes, but can easily be present *	in synthetic images.) * * 	Such pixels can be flagged so the user may then choose other *	colours.  Or, the offending pixels can be made "safe" *	in a manner that preserves hue. * *	There are two reasonable ways to make a pixel "safe": *	We can reduce its intensity (luminance) while leaving *	hue and saturation the same.  Or, we can reduce saturation *	while leaving hue and luminance the same.  A #define selects *	which strategy to use. * * Note to the user: You must add your own read_pixel() and write_pixel() *	routines.  You may have to modify pix_decode() and pix_encode(). *	MAXPIX, WID, and HGT are likely to need modification. *//* * Originally written as "ikNTSC.c" by Alan Wm Paeth, *	University of Waterloo, August, 1985 * Updated by Dave Martindale, Imax Systems Corp., December 1990 *//* * Compile-time options. * * Define either NTSC or PAL as 1 to select the colour system. * Define the other one as zero, or leave it undefined. * * Define FLAG_HOT as 1 if you want "hot" pixels set to black *	to identify them.  Otherwise they will be made safe. * * Define REDUCE_SAT as 1 if you want hot pixels to be repaired by *	reducing their saturation.  By default, luminance is reduced. * * CHROMA_LIM is the limit (in IRE units) of the overall *	chrominance amplitude; it should be 50 or perhaps *	very slightly higher. *  * COMPOS_LIM is the maximum amplitude (in IRE units) allowed for *	the composite signal.  A value of 100 is the maximum *	monochrome white, and is always safe.  120 is the absolute *	limit for NTSC broadcasting, since the transmitter's carrier *	goes to zero with 120 IRE input signal.  Generally, 110 *	is a good compromise - it allows somewhat brighter colours *	than 100, while staying safely away from the hard limit. */#define	NTSC        1#define	PAL         0#define	FLAG_HOT    0#define	REDUCE_SAT  0#define	CHROMA_LIM      50.0		/* chroma amplitude limit */#define	COMPOS_LIM      110.0		/* max IRE amplitude */#if NTSC/* * RGB to YIQ encoding matrix. */double code_matrix[3][3] = {	 0.2989,	 0.5866,	 0.1144,	 0.5959,	-0.2741,	-0.3218,	 0.2113,	-0.5227,	 0.3113,};#define	PEDESTAL	7.5		/* 7.5 IRE black pedestal */#define	GAMMA		2.2#endif /* NTSC */#if PAL/* * RGB to YUV encoding matrix. */double code_matrix[3][3] = {	 0.2989,	 0.5866,	 0.1144,	-0.1473,	-0.2891,	 0.4364,	 0.6149,	-0.5145,	-0.1004,};#define	PEDESTAL	0.0		/* no pedestal in PAL */#define	GAMMA		2.8#endif /* PAL */#define SCALE	8192            /* scale factor: do floats with int math */#define MAXPIX	 255            /* white value */#define WID	 1024           /* FB dimensions */#define HGT	 768typedef struct {	unsigned char	r, g, b;} Pixel;int	tab[3][3][MAXPIX+1];    /* multiply lookup table */double	chroma_lim;             /* chroma limit */double	compos_lim;             /* composite amplitude limit */long	ichroma_lim2;           /* chroma limit squared (scaled integer) */int	icompos_lim;            /* composite amplitude limit (scaled integer) */double	pix_decode(), gc(), inv_gc();int	pix_encode(), hot();main(){	Pixel	p;	int	row, col;	build_tab();	for (col=0; col<WID; col++) {		for(row=0; row<HGT; row++) {			read_pixel(row, col, &p);			if (hot(&p)) {				write_pixel(row, col, &p);			}		}	}}/* * build_tab: Build multiply lookup table. * * For each possible pixel value, decode value into floating-point * intensity.  Then do gamma correction required by the video * standard.  Scale the result by our fixed-point scale factor. * Then calculate 9 lookup table entries for this pixel value. * * We also calculate floating-point and scaled integer versions * of our limits here.  This prevents evaluating expressions every pixel * when the compiler is too stupid to evaluate constant-valued * floating-point expressions at compile time. * * For convenience, the limits are #defined using IRE units. * We must convert them here into the units in which YIQ * are measured.  The conversion from IRE to internal units * depends on the pedestal level in use, since as Y goes from * 0 to 1, the signal goes from the pedestal level to 100 IRE. * Chroma is always scaled to remain consistent with Y. */build_tab(){	register double	f;	register int	pv;	for (pv = 0; pv <= MAXPIX; pv++) {		f = SCALE * gc(pix_decode(pv));		tab[0][0][pv] = (int)(f * code_matrix[0][0] + 0.5);		tab[0][1][pv] = (int)(f * code_matrix[0][1] + 0.5);		tab[0][2][pv] = (int)(f * code_matrix[0][2] + 0.5);		tab[1][0][pv] = (int)(f * code_matrix[1][0] + 0.5);		tab[1][1][pv] = (int)(f * code_matrix[1][1] + 0.5);		tab[1][2][pv] = (int)(f * code_matrix[1][2] + 0.5);		tab[2][0][pv] = (int)(f * code_matrix[2][0] + 0.5);		tab[2][1][pv] = (int)(f * code_matrix[2][1] + 0.5);		tab[2][2][pv] = (int)(f * code_matrix[2][2] + 0.5);	}	chroma_lim = (double)CHROMA_LIM / (100.0 - PEDESTAL);	compos_lim = ((double)COMPOS_LIM - PEDESTAL) / (100.0 - PEDESTAL);	ichroma_lim2 = (int)(chroma_lim * SCALE + 0.5);	ichroma_lim2 *= ichroma_lim2;	icompos_lim = (int)(compos_lim * SCALE + 0.5);}inthot(p)Pixel	*p;{	register int	r, g, b;	register int	y, i, q;	register long	y2, c2;	double		pr, pg, pb;#if REDUCE_SAT	double		py;#endif	register double	fy, fc, t, scale;#if !FLAG_HOT	static int	prev_r = 0, prev_g = 0, prev_b = 0;	static int	new_r, new_g, new_b;#endif	extern double	pow(), hypot();	r = p->r;	g = p->g;	b = p->b;	/*	 * Pixel decoding, gamma correction, and matrix multiplication	 * all done by lookup table.	 *	 * "i" and "q" are the two chrominance components;	 * they are I and Q for NTSC.	 * For PAL, "i" is U (scaled B-Y) and "q" is V (scaled R-Y).	 * Since we only care about the length of the chroma vector,	 * not its angle, we don't care which is which.	 */	y = tab[0][0][r] + tab[0][1][g] + tab[0][2][b];	i = tab[1][0][r] + tab[1][1][g] + tab[1][2][b];	q = tab[2][0][r] + tab[2][1][g] + tab[2][2][b];	/*	 * Check to see if the chrominance vector is too long or the	 * composite waveform amplitude is too large.	 *	 * Chrominance is too large if	 *	 *	sqrt(i^2, q^2)  >  chroma_lim.	 *	 * The composite signal amplitude is too large if	 *	 *	y + sqrt(i^2, q^2)  >  compos_lim.	 *	 * We avoid doing the sqrt by checking	 *	 *	i^2 + q^2  >  chroma_lim^2	 * and	 *	y + sqrt(i^2 + q^2)  >  compos_lim	 *	sqrt(i^2 + q^2)  >  compos_lim - y	 *	i^2 + q^2  >  (compos_lim - y)^2	 *	 */	c2 = (long)i * i + (long)q * q;	y2 = (long)icompos_lim - y;	y2 *= y2;	if (c2 <= ichroma_lim2 && c2 <= y2)	/* no problems */		return 0;	/*	 * Pixel is hot, choose desired (compilation time controlled) strategy	 */#if FLAG_HOT	/*	 * Set the hot pixel to black to identify it.	 */	p->r = p->g = p->b = 0;#else /* FLAG_HOT */	/*	 * Optimization: cache the last-computed hot pixel.	 */	if (r == prev_r && g == prev_g && b == prev_b) {		p->r = new_r;		p->g = new_g;		p->b = new_b;		return 1;	}	prev_r = r;	prev_g = g;	prev_b = b;	/*	 * Get Y and chroma amplitudes in floating point.	 *	 * If your C library doesn't have hypot(), just use	 * hypot(a,b) = sqrt(a*a, b*b);	 *	 * Then extract linear (un-gamma-corrected) floating-point	 * pixel RGB values.	 */	fy = (double)y / SCALE;	fc = hypot((double)i / SCALE, (double)q / SCALE);	pr = pix_decode(r);	pg = pix_decode(g);	pb = pix_decode(b);	/*	 * Reducing overall pixel intensity by scaling	 * R, G, and B reduces Y, I, and Q by the same factor.	 * This changes luminance but not saturation, since saturation	 * is determined by the chroma/luminance ratio.	 *	 * On the other hand, by linearly interpolating between the	 * original pixel value and a grey pixel with the same	 * luminance (R=G=B=Y), we change saturation without	 * affecting luminance.	 */#if !REDUCE_SAT	/*	 * Calculate a scale factor that will bring the pixel	 * within both chroma and composite limits, if we scale	 * luminance and chroma simultaneously.	 *	 * The calculated chrominance reduction applies to the	 * gamma-corrected RGB values that are the input to	 * the RGB-to-YIQ operation.  Multiplying the	 * original un-gamma-corrected pixel values by	 * the scaling factor raised to the "gamma" power	 * is equivalent, and avoids calling gc() and inv_gc()	 * three times each.	 */	scale = chroma_lim / fc;	t = compos_lim / (fy + fc);	if (t < scale)		scale = t;	scale = pow(scale, GAMMA);	r = pix_encode(scale * pr);	g = pix_encode(scale * pg);	b = pix_encode(scale * pb);#else /* REDUCE_SAT */	/*	 * Calculate a scale factor that will bring the pixel	 * within both chroma and composite limits, if we scale	 * chroma while leaving luminance unchanged.	 *	 * We have to interpolate gamma-corrected RGB values,	 * so we must convert from linear to gamma-corrected	 * before interpolation and then back to linear afterwards.	 */	scale = chroma_lim / fc;	t = (compos_lim - fy) / fc;	if (t < scale)		scale = t;	pr = gc(pr);	pg = gc(pg);	pb = gc(pb);	py = pr * code_matrix[0][0] + pg * code_matrix[0][1]		+ pb * code_matrix[0][2];	r = pix_encode(inv_gc(py + scale * (pr - py)));	g = pix_encode(inv_gc(py + scale * (pg - py)));	b = pix_encode(inv_gc(py + scale * (pb - py)));#endif /* REDUCE_SAT */	p->r = new_r = r;	p->g = new_g = g;	p->b = new_b = b;#endif /* FLAG_HOT */	return 1;}/* * gc: apply the gamma correction specified for this video standard. * inv_gc: inverse function of gc. * * These are generally just a call to pow(), but be careful! * Future standards may use more complex functions. * (e.g. SMPTE 240M's "electro-optic transfer characteristic"). */doublegc(x)double	x;{	extern double	pow();	return pow(x, 1.0 / GAMMA);}doubleinv_gc(x)double	x;{	extern double	pow();	return pow(x, GAMMA);}/* * pix_decode: decode an integer pixel value into a floating-point *	intensity in the range [0, 1]. * * pix_encode: encode a floating-point intensity into an integer *	pixel value. * * The code given here assumes simple linear encoding; you must change * these routines if you use a different pixel encoding technique. */doublepix_decode(v)int	v;{	return (double)v / MAXPIX;}intpix_encode(v)double	v;{	return (int)(v * MAXPIX + 0.5);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -