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

📄 filter_rcg.c

📁 [Game.Programming].Academic - Graphics Gems (6 books source code)
💻 C
📖 第 1 页 / 共 2 页
字号:
Image* image;{	FILE* fp;	ImageHandler* handler;	int nRet = -1; /* assume failure */	ASSERT(f && image);			fp = fopen(f, "wb");	if(fp != NULL)	{		if(handler = find_imagehandler(f))			nRet = handler->writer(fp, image);		fclose(fp);	}	return nRet;}/* *	filter function definitions */#define	filter_support		(1.0)doublefilter(t)double t;{	/* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */	if(t < 0.0) t = -t;	if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0);	return(0.0);}#define	box_support		(0.5)doublebox_filter(t)double t;{	if((t > -0.5) && (t <= 0.5)) return(1.0);	return(0.0);}#define	triangle_support	(1.0)doubletriangle_filter(t)double t;{	if(t < 0.0) t = -t;	if(t < 1.0) return(1.0 - t);	return(0.0);}#define	bell_support		(1.5)doublebell_filter(t)		/* box (*) box (*) box */double t;{	if(t < 0) t = -t;	if(t < .5) return(.75 - (t * t));	if(t < 1.5) {		t = (t - 1.5);		return(.5 * (t * t));	}	return(0.0);}#define	B_spline_support	(2.0)doubleB_spline_filter(t)	/* box (*) box (*) box (*) box */double t;{	double tt;	if(t < 0) t = -t;	if(t < 1) {		tt = t * t;		return((.5 * tt * t) - tt + (2.0 / 3.0));	} else if(t < 2) {		t = 2 - t;		return((1.0 / 6.0) * (t * t * t));	}	return(0.0);}doublesinc(x)double x;{	x *= M_PI;	if(x != 0) return(sin(x) / x);	return(1.0);}#define	Lanczos3_support	(3.0)doubleLanczos3_filter(t)double t;{	if(t < 0) t = -t;	if(t < 3.0) return(sinc(t) * sinc(t/3.0));	return(0.0);}#define	Mitchell_support	(2.0)#define	B	(1.0 / 3.0)#define	C	(1.0 / 3.0)doubleMitchell_filter(t)double t;{	double tt;	tt = t * t;	if(t < 0) t = -t;	if(t < 1.0) {		t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt))		   + ((-18.0 + 12.0 * B + 6.0 * C) * tt)		   + (6.0 - 2 * B));		return(t / 6.0);	} else if(t < 2.0) {		t = (((-1.0 * B - 6.0 * C) * (t * tt))		   + ((6.0 * B + 30.0 * C) * tt)		   + ((-12.0 * B - 48.0 * C) * t)		   + (8.0 * B + 24 * C));		return(t / 6.0);	}	return(0.0);}/* *	image rescaling routine */typedef struct {	int	pixel;	double	weight;} CONTRIB;typedef struct {	int	n;		/* number of contributors */	CONTRIB	*p;		/* pointer to list of contributions */} CLIST;CLIST	*contrib;		/* array of contribution lists *//*	roundcloser()	Round an FP value to its closest int representation.	General routine; ideally belongs in general math lib file.*/	int roundcloser(double d){	/* Untested potential one-liner, but smacks of call overhead */	/* return fabs(ceil(d)-d) <= 0.5 ? ceil(d) : floor(d); */	/* Untested potential optimized ceil() usage *//*	double cd = ceil(d);	int ncd = (int)cd;	if(fabs(cd - d) > 0.5)		ncd--;	return ncd;*/	/* Version that uses no function calls at all. */	int n = (int) d;	double diff = d - (double)n;	if(diff < 0)		diff = -diff;	if(diff >= 0.5)	{		if(d < 0)			n--;		else			n++;	}	return n;} /* roundcloser *//* 	calc_x_contrib()		Calculates the filter weights for a single target column.	contribX->p must be freed afterwards.	Returns -1 if error, 0 otherwise.*/int calc_x_contrib(contribX, xscale, fwidth, dstwidth, srcwidth, filterf, i)CLIST* contribX;			/* Receiver of contrib info */double xscale;				/* Horizontal zooming scale */double fwidth;				/* Filter sampling width */int dstwidth;				/* Target bitmap width */int srcwidth;				/* Source bitmap width */double (*filterf)(double);	/* Filter proc */int i;						/* Pixel column in source bitmap being processed */{	double width;	double fscale;	double center, left, right;	double weight;	int j, k, n;	if(xscale < 1.0)	{		/* Shrinking image */		width = fwidth / xscale;		fscale = 1.0 / xscale;		contribX->n = 0;		contribX->p = (CONTRIB *)calloc((int) (width * 2 + 1),				sizeof(CONTRIB));		if(contribX->p == NULL)			return -1;		center = (double) i / xscale;		left = ceil(center - width);		right = floor(center + width);		for(j = (int)left; j <= right; ++j)		{			weight = center - (double) j;			weight = (*filterf)(weight / fscale) / fscale;			if(j < 0)				n = -j;			else if(j >= srcwidth)				n = (srcwidth - j) + srcwidth - 1;			else				n = j;						k = contribX->n++;			contribX->p[k].pixel = n;			contribX->p[k].weight = weight;		}		}	else	{		/* Expanding image */		contribX->n = 0;		contribX->p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),				sizeof(CONTRIB));		if(contribX->p == NULL)			return -1;		center = (double) i / xscale;		left = ceil(center - fwidth);		right = floor(center + fwidth);		for(j = (int)left; j <= right; ++j)		{			weight = center - (double) j;			weight = (*filterf)(weight);			if(j < 0) {				n = -j;			} else if(j >= srcwidth) {				n = (srcwidth - j) + srcwidth - 1;			} else {				n = j;			}			k = contribX->n++;			contribX->p[k].pixel = n;			contribX->p[k].weight = weight;		}	}	return 0;} /* calc_x_contrib *//*	zoom()	Resizes bitmaps while resampling them.	Returns -1 if error, 0 if success.*/intzoom(dst, src, filterf, fwidth)Image* dst;Image* src;double (*filterf)(double);double fwidth;{	Pixel* tmp;	double xscale, yscale;		/* zoom scale factors */	int xx;	int i, j, k;			/* loop variables */	int n;				/* pixel number */	double center, left, right;	/* filter calculation variables */	double width, fscale, weight;	/* filter calculation variables */	Pixel pel, pel2;	int bPelDelta;	CLIST	*contribY;		/* array of contribution lists */	CLIST	contribX;	int		nRet = -1;	/* create intermediate column to hold horizontal dst column zoom */	tmp = (Pixel*)malloc(src->ysize * sizeof(Pixel));	if(tmp == NULL)		return 0;	xscale = (double) dst->xsize / (double) src->xsize;	/* Build y weights */	/* pre-calculate filter contributions for a column */	contribY = (CLIST *)calloc(dst->ysize, sizeof(CLIST));	if(contribY == NULL)	{		free(tmp);		return -1;	}	yscale = (double) dst->ysize / (double) src->ysize;	if(yscale < 1.0)	{		width = fwidth / yscale;		fscale = 1.0 / yscale;		for(i = 0; i < dst->ysize; ++i)		{			contribY[i].n = 0;			contribY[i].p = (CONTRIB *)calloc((int) (width * 2 + 1),					sizeof(CONTRIB));			if(contribY[i].p == NULL)			{				free(tmp);				free(contribY);				return -1;			}			center = (double) i / yscale;			left = ceil(center - width);			right = floor(center + width);			for(j = (int)left; j <= right; ++j) {				weight = center - (double) j;				weight = (*filterf)(weight / fscale) / fscale;				if(j < 0) {					n = -j;				} else if(j >= src->ysize) {					n = (src->ysize - j) + src->ysize - 1;				} else {					n = j;				}				k = contribY[i].n++;				contribY[i].p[k].pixel = n;				contribY[i].p[k].weight = weight;			}		}	} else {		for(i = 0; i < dst->ysize; ++i) {			contribY[i].n = 0;			contribY[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),					sizeof(CONTRIB));			if(contribY[i].p == NULL)			{				free(tmp);				free(contribY);				return -1;			}			center = (double) i / yscale;			left = ceil(center - fwidth);			right = floor(center + fwidth);			for(j = (int)left; j <= right; ++j) {				weight = center - (double) j;				weight = (*filterf)(weight);				if(j < 0) {					n = -j;				} else if(j >= src->ysize) {					n = (src->ysize - j) + src->ysize - 1;				} else {					n = j;				}				k = contribY[i].n++;				contribY[i].p[k].pixel = n;				contribY[i].p[k].weight = weight;			}		}	}	for(xx = 0; xx < dst->xsize; xx++)	{		if(0 != calc_x_contrib(&contribX, xscale, fwidth, 								dst->xsize, src->xsize, filterf, xx))		{			goto __zoom_cleanup;		}		/* Apply horz filter to make dst column in tmp. */		for(k = 0; k < src->ysize; ++k)		{			weight = 0.0;			bPelDelta = FALSE;			pel = get_pixel(src, contribX.p[0].pixel, k);			for(j = 0; j < contribX.n; ++j)			{				pel2 = get_pixel(src, contribX.p[j].pixel, k);				if(pel2 != pel)					bPelDelta = TRUE;				weight += pel2 * contribX.p[j].weight;			}			weight = bPelDelta ? roundcloser(weight) : pel;			tmp[k] = (Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL);		} /* next row in temp column */		free(contribX.p);		/* The temp column has been built. Now stretch it 		 vertically into dst column. */		for(i = 0; i < dst->ysize; ++i)		{			weight = 0.0;			bPelDelta = FALSE;			pel = tmp[contribY[i].p[0].pixel];			for(j = 0; j < contribY[i].n; ++j)			{				pel2 = tmp[contribY[i].p[j].pixel];				if(pel2 != pel)					bPelDelta = TRUE;				weight += pel2 * contribY[i].p[j].weight;			}			weight = bPelDelta ? roundcloser(weight) : pel;			put_pixel(dst, xx, i,				(Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL));		} /* next dst row */	} /* next dst column */	nRet = 0; /* success */__zoom_cleanup:	free(tmp);	/* free the memory allocated for vertical filter weights */	for(i = 0; i < dst->ysize; ++i)		free(contribY[i].p);	free(contribY);	return nRet;} /* zoom *//* *	command line interface */voidusage(){	fprintf(stderr, "usage: %s [-options] input output\n", _Program);	fprintf(stderr, "\options:\n\	-x xsize		output x size\n\	-y ysize		output y size\n\	-f filter		filter type\n\{b=box, t=triangle, q=bell, B=B-spline, h=hermite, l=Lanczos3, m=Mitchell}\n\	input, output	files to read/write. Use BM or TGA extension.\n\");	exit(1);}voidbanner(){	printf("%s v%s -- %s\n", _Program, _Version, _Copyright);}intmain(argc, argv)int argc;char *argv[];{	register int c;#ifndef WIN32	extern int optind;	extern char *optarg;#endif	int xsize = 0, ysize = 0;	double (*f)() = filter;	double s = filter_support;	char *dstfile, *srcfile;	Image *dst, *src;	while((c = getopt(argc, argv, "x:y:f:V")) != EOF) {		switch(c) {		case 'x': xsize = atoi(optarg); break;		case 'y': ysize = atoi(optarg); break;		case 'f':			switch(*optarg) {			case 'b': f=box_filter; s=box_support; break;			case 't': f=triangle_filter; s=triangle_support; break;			case 'q': f=bell_filter; s=bell_support; break;			case 'B': f=B_spline_filter; s=B_spline_support; break;			case 'h': f=filter; s=filter_support; break;			case 'l': f=Lanczos3_filter; s=Lanczos3_support; break;			case 'm': f=Mitchell_filter; s=Mitchell_support; break;			default: usage();			}			break;		case 'V': banner(); exit(EXIT_SUCCESS);		case '?': usage();		default:  usage();		}	}	if((argc - optind) != 2) usage();	srcfile = argv[optind];	dstfile = argv[optind + 1];	if((src = load_image(srcfile)) == NULL)	{		fprintf(stderr, "%s: can't load source image '%s'\n",			_Program, srcfile);		exit(EXIT_FAILURE);	}	if(xsize <= 0) xsize = src->xsize;	if(ysize <= 0) ysize = src->ysize;	dst = new_image(xsize, ysize);	if(zoom(dst, src, f, s) != 0)	{		fprintf(stderr, "%s: can't process image '%s'\n", 			_Program, srcfile);		exit(EXIT_FAILURE);	}	else	{		if(save_image(dstfile, dst) != 0)		{			fprintf(stderr, "%s: can't save destination image '%s'\n",				_Program, dstfile);			exit(EXIT_FAILURE);		}	}	exit(EXIT_SUCCESS);	return 0;}

⌨️ 快捷键说明

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