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

📄 filter.c

📁 [Game.Programming].Academic - Graphics Gems (6 books source code)
💻 C
字号:
/* *		Filtered Image Rescaling * *		  by Dale Schumacher */#include <stdio.h>#include <string.h>#include <malloc.h>#include <math.h>#include "GraphicsGems.h"static char	_Program[] = "fzoom";static char	_Version[] = "0.20";static char	_Copyright[] = "Public Domain 1991 by Dale Schumacher";#ifndef EXIT_SUCCESS#define	EXIT_SUCCESS	(0)#define	EXIT_FAILURE	(1)#endiftypedef	unsigned char	Pixel;typedef struct {	int	xsize;		/* horizontal size of the image in Pixels */	int	ysize;		/* vertical size of the image in Pixels */	Pixel *	data;		/* pointer to first scanline of image */	int	span;		/* byte offset between two scanlines */} Image;#define	WHITE_PIXEL	(255)#define	BLACK_PIXEL	(0)/* *	generic image access and i/o support routines */static char *next_token(f)FILE *f;{	static char delim[] = " \t\r\n";	static char *t = NULL;	static char lnbuf[256];	char *p;	while(t == NULL) {			/* nothing in the buffer */		if(fgets(lnbuf, sizeof(lnbuf), f)) {	/* read a line */			if(p = strchr(lnbuf, '#')) {	/* clip any comment */				*p = '\0';			}			t = strtok(lnbuf, delim);	/* get first token */		} else {			return(NULL);		}	}	p = t;	t = strtok((char *)NULL, delim);		/* get next token */	return(p);}Image *new_image(xsize, ysize)	/* create a blank image */int xsize, ysize;{	Image *image;	if((image = (Image *)malloc(sizeof(Image)))	&& (image->data = (Pixel *)calloc(ysize, xsize))) {		image->xsize = xsize;		image->ysize = ysize;		image->span = xsize;	}	return(image);}voidfree_image(image)Image *image;{	free(image->data);	free(image);}Image *load_image(f)		/* read image from file */FILE *f;{	char *p;	int width, height;	Image *image;	if(((p = next_token(f)) && (strcmp(p, "Bm") == 0))	&& ((p = next_token(f)) && ((width = atoi(p)) > 0))	&& ((p = next_token(f)) && ((height = atoi(p)) > 0))	&& ((p = next_token(f)) && (strcmp(p, "8") == 0))	&& (image = new_image(width, height))	&& (fread(image->data, width, height, f) == height)) {		return(image);		/* load successful */	} else {		return(NULL);		/* load failed */	}}intsave_image(f, image)	/* write image to file */FILE *f;Image *image;{	fprintf(f, "Bm # PXM 8-bit greyscale image\n");	fprintf(f, "%d %d 8 # width height depth\n",		image->xsize, image->ysize);	if(fwrite(image->data, image->xsize, image->ysize, f) == image->ysize) {		return(0);		/* save successful */	} else {		return(-1);		/* save failed */	}}Pixelget_pixel(image, x, y)Image *image;int x, y;{	static Image *im = NULL;	static int yy = -1;	static Pixel *p = NULL;	if((x < 0) || (x >= image->xsize) || (y < 0) || (y >= image->ysize)) {		return(0);	}	if((im != image) || (yy != y)) {		im = image;		yy = y;		p = image->data + (y * image->span);	}	return(p[x]);}voidget_row(row, image, y)Pixel *row;Image *image;int y;{	if((y < 0) || (y >= image->ysize)) {		return;	}	memcpy(row,		image->data + (y * image->span),		(sizeof(Pixel) * image->xsize));}voidget_column(column, image, x)Pixel *column;Image *image;int x;{	int i, d;	Pixel *p;	if((x < 0) || (x >= image->xsize)) {		return;	}	d = image->span;	for(i = image->ysize, p = image->data + x; i-- > 0; p += d) {		*column++ = *p;	}}Pixelput_pixel(image, x, y, data)Image *image;int x, y;Pixel data;{	static Image *im = NULL;	static int yy = -1;	static Pixel *p = NULL;	if((x < 0) || (x >= image->xsize) || (y < 0) || (y >= image->ysize)) {		return(0);	}	if((im != image) || (yy != y)) {		im = image;		yy = y;		p = image->data + (y * image->span);	}	return(p[x] = data);}/* *	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 */voidzoom(dst, src, filterf, fwidth)Image *dst;				/* destination image structure */Image *src;				/* source image structure */double (*filterf)();			/* filter function */double fwidth;				/* filter width (support) */{	Image *tmp;			/* intermediate image */	double xscale, yscale;		/* zoom scale factors */	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 *raster;			/* a row or column of pixels */	/* create intermediate image to hold horizontal zoom */	tmp = new_image(dst->xsize, src->ysize);	xscale = (double) dst->xsize / (double) src->xsize;	yscale = (double) dst->ysize / (double) src->ysize;	/* pre-calculate filter contributions for a row */	contrib = (CLIST *)calloc(dst->xsize, sizeof(CLIST));	if(xscale < 1.0) {		width = fwidth / xscale;		fscale = 1.0 / xscale;		for(i = 0; i < dst->xsize; ++i) {			contrib[i].n = 0;			contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1),					sizeof(CONTRIB));			center = (double) i / xscale;			left = ceil(center - width);			right = floor(center + width);			for(j = left; j <= right; ++j) {				weight = center - (double) j;				weight = (*filterf)(weight / fscale) / fscale;				if(j < 0) {					n = -j;				} else if(j >= src->xsize) {					n = (src->xsize - j) + src->xsize - 1;				} else {					n = j;				}				k = contrib[i].n++;				contrib[i].p[k].pixel = n;				contrib[i].p[k].weight = weight;			}		}	} else {		for(i = 0; i < dst->xsize; ++i) {			contrib[i].n = 0;			contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),					sizeof(CONTRIB));			center = (double) i / xscale;			left = ceil(center - fwidth);			right = floor(center + fwidth);			for(j = left; j <= right; ++j) {				weight = center - (double) j;				weight = (*filterf)(weight);				if(j < 0) {					n = -j;				} else if(j >= src->xsize) {					n = (src->xsize - j) + src->xsize - 1;				} else {					n = j;				}				k = contrib[i].n++;				contrib[i].p[k].pixel = n;				contrib[i].p[k].weight = weight;			}		}	}	/* apply filter to zoom horizontally from src to tmp */	raster = (Pixel *)calloc(src->xsize, sizeof(Pixel));	for(k = 0; k < tmp->ysize; ++k) {		get_row(raster, src, k);		for(i = 0; i < tmp->xsize; ++i) {			weight = 0.0;			for(j = 0; j < contrib[i].n; ++j) {				weight += raster[contrib[i].p[j].pixel]					* contrib[i].p[j].weight;			}			put_pixel(tmp, i, k,				(Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL));		}	}	free(raster);	/* free the memory allocated for horizontal filter weights */	for(i = 0; i < tmp->xsize; ++i) {		free(contrib[i].p);	}	free(contrib);	/* pre-calculate filter contributions for a column */	contrib = (CLIST *)calloc(dst->ysize, sizeof(CLIST));	if(yscale < 1.0) {		width = fwidth / yscale;		fscale = 1.0 / yscale;		for(i = 0; i < dst->ysize; ++i) {			contrib[i].n = 0;			contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1),					sizeof(CONTRIB));			center = (double) i / yscale;			left = ceil(center - width);			right = floor(center + width);			for(j = left; j <= right; ++j) {				weight = center - (double) j;				weight = (*filterf)(weight / fscale) / fscale;				if(j < 0) {					n = -j;				} else if(j >= tmp->ysize) {					n = (tmp->ysize - j) + tmp->ysize - 1;				} else {					n = j;				}				k = contrib[i].n++;				contrib[i].p[k].pixel = n;				contrib[i].p[k].weight = weight;			}		}	} else {		for(i = 0; i < dst->ysize; ++i) {			contrib[i].n = 0;			contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),					sizeof(CONTRIB));			center = (double) i / yscale;			left = ceil(center - fwidth);			right = floor(center + fwidth);			for(j = left; j <= right; ++j) {				weight = center - (double) j;				weight = (*filterf)(weight);				if(j < 0) {					n = -j;				} else if(j >= tmp->ysize) {					n = (tmp->ysize - j) + tmp->ysize - 1;				} else {					n = j;				}				k = contrib[i].n++;				contrib[i].p[k].pixel = n;				contrib[i].p[k].weight = weight;			}		}	}	/* apply filter to zoom vertically from tmp to dst */	raster = (Pixel *)calloc(tmp->ysize, sizeof(Pixel));	for(k = 0; k < dst->xsize; ++k) {		get_column(raster, tmp, k);		for(i = 0; i < dst->ysize; ++i) {			weight = 0.0;			for(j = 0; j < contrib[i].n; ++j) {				weight += raster[contrib[i].p[j].pixel]					* contrib[i].p[j].weight;			}			put_pixel(dst, k, i,				(Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL));		}	}	free(raster);	/* free the memory allocated for vertical filter weights */	for(i = 0; i < dst->ysize; ++i) {		free(contrib[i].p);	}	free(contrib);	free_image(tmp);}/* *	command line interface */voidusage(){	fprintf(stderr, "usage: %s [-options] input.bm output.bm\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\");	exit(1);}voidbanner(){	printf("%s v%s -- %s\n", _Program, _Version, _Copyright);}main(argc, argv)int argc;char *argv[];{	register int c;	extern int optind;	extern char *optarg;	int xsize = 0, ysize = 0;	double (*f)() = filter;	double s = filter_support;	char *dstfile, *srcfile;	Image *dst, *src;	FILE *fp;	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(((fp = fopen(srcfile, "r")) == NULL)	|| ((src = load_image(fp)) == NULL)) {		fprintf(stderr, "%s: can't load source image '%s'\n",			_Program, srcfile);		exit(EXIT_FAILURE);	}	fclose(fp);	if(xsize <= 0) xsize = src->xsize;	if(ysize <= 0) ysize = src->ysize;	dst = new_image(xsize, ysize);	zoom(dst, src, f, s);	if(((fp = fopen(dstfile, "w")) == NULL)	|| (save_image(fp, dst) != 0)) {		fprintf(stderr, "%s: can't save destination image '%s'\n",			_Program, dstfile);		exit(EXIT_FAILURE);	}	fclose(fp);	exit(EXIT_SUCCESS);}

⌨️ 快捷键说明

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