diff options
| -rw-r--r-- | src/jpeg.c | 107 | ||||
| -rw-r--r-- | src/main.c | 73 | ||||
| -rw-r--r-- | src/meh.h | 14 | 
3 files changed, 122 insertions, 72 deletions
@@ -15,67 +15,92 @@ struct error_mgr{  };  static void error_exit(j_common_ptr cinfo){ +	(void) cinfo;  	printf("\nerror!\n");  	exit(1);  } -unsigned char *loadjpeg(FILE *infile, int *width, int *height){ +struct jpeg_t{ +	struct image img; +	FILE *f;  	struct jpeg_decompress_struct cinfo;  	struct error_mgr jerr; +}; + +static struct image *jpeg_open(FILE *f){ +	struct jpeg_t *j; + +	rewind(f); +	if(getc(f) != 0xff || getc(f) != 0xd8) +		return NULL; + +	j = malloc(sizeof(struct jpeg_t)); +	j->f = f; +	rewind(f); + +	j->cinfo.err = jpeg_std_error(&j->jerr.pub); +	j->jerr.pub.error_exit = error_exit; + +	jpeg_create_decompress(&j->cinfo); +	jpeg_stdio_src(&j->cinfo, f); +	jpeg_read_header(&j->cinfo, TRUE); + +	/* parameters */ +	j->cinfo.do_fancy_upsampling = 0; +	j->cinfo.do_block_smoothing = 0; +	j->cinfo.quantize_colors = 0; +	j->cinfo.dct_method = JDCT_IFAST; +	jpeg_calc_output_dimensions(&j->cinfo); + +	j->img.width = j->cinfo.output_width; +	j->img.height = j->cinfo.output_height; + +	return (struct image *)j; +} + +static int jpeg_read(struct image *img){ +	struct jpeg_t *j = (struct jpeg_t *)img;  	JSAMPARRAY buffer;  	int row_stride; -	int i = 0; -	int j, y, x; -	unsigned char *retbuf; +	int a = 0, b; +	unsigned int x, y; -	cinfo.err = jpeg_std_error(&jerr.pub); -	jerr.pub.error_exit = error_exit; +	row_stride = j->cinfo.output_width * j->cinfo.output_components; +	buffer = (*j->cinfo.mem->alloc_sarray)((j_common_ptr)&j->cinfo, JPOOL_IMAGE, row_stride, 4); -	jpeg_create_decompress(&cinfo); -	jpeg_stdio_src(&cinfo, infile); -	jpeg_read_header(&cinfo, TRUE); +	jpeg_start_decompress(&j->cinfo); -	/* parameters */ -	cinfo.do_fancy_upsampling = 0; -	cinfo.do_block_smoothing = 0; -	cinfo.quantize_colors = 0; -	cinfo.dct_method = JDCT_IFAST; -	 -	jpeg_calc_output_dimensions(&cinfo); -	row_stride = cinfo.output_width * cinfo.output_components; -	buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 4); -	 -	jpeg_start_decompress(&cinfo); -	*width = cinfo.output_width; -	*height = cinfo.output_height; -	retbuf = malloc(3 * (cinfo.output_width * cinfo.output_height)); - -	if(cinfo.output_components == 3){ -		for(y = 0; y < cinfo.output_height; ){ -			int n = jpeg_read_scanlines(&cinfo, buffer, 4); -			for(j = 0; j < n; j++){ -				memcpy(&retbuf[i], buffer[j], row_stride); -				i += row_stride; +	if(j->cinfo.output_components == 3){ +		for(y = 0; y < j->cinfo.output_height; ){ +			int n = jpeg_read_scanlines(&j->cinfo, buffer, 4); +			for(b = 0; b < n; b++){ +				memcpy(&img->buf[a], buffer[b], row_stride); +				a += row_stride;  			}  			y += n;  		} -	}else if(cinfo.output_components == 1){ -		for(y = 0; y < cinfo.output_height; ){ -			int n = jpeg_read_scanlines(&cinfo, buffer, 4); -			for(j = 0; j < n; j++){ -				for(x = 0; x < cinfo.output_width; x++){ -					retbuf[i++] = buffer[j][x]; -					retbuf[i++] = buffer[j][x]; -					retbuf[i++] = buffer[j][x]; +	}else if(j->cinfo.output_components == 1){ +		for(y = 0; y < j->cinfo.output_height; ){ +			int n = jpeg_read_scanlines(&j->cinfo, buffer, 4); +			for(b = 0; b < n; b++){ +				for(x = 0; x < j->cinfo.output_width; x++){ +					img->buf[a++] = buffer[b][x]; +					img->buf[a++] = buffer[b][x]; +					img->buf[a++] = buffer[b][x];  				}  			}  			y += n;  		}  	} -	jpeg_finish_decompress(&cinfo); -	jpeg_destroy_decompress(&cinfo); -	return retbuf; +	jpeg_finish_decompress(&j->cinfo); +	jpeg_destroy_decompress(&j->cinfo); + +	return 0;  } +struct imageformat jpeg = { +	jpeg_open, +	jpeg_read +}; @@ -12,6 +12,14 @@  #include "meh.h" +/* Supported Formats */ +extern struct imageformat jpeg; +struct imageformat *formats[] = { +	&jpeg, +	NULL +}; + +/* Globals */  Display *display;  int screen;  Window window; @@ -120,30 +128,32 @@ XImage *create_image_from_buffer(unsigned char *buf, int width, int height, int  	return img;  } -unsigned char *loadbuf(const char *filename, int *bufwidth, int *bufheight){ +struct image *imgopen(const char *filename){ +	struct image *img = NULL; +	struct imageformat **fmt = formats;  	FILE *f; -	unsigned char head[4]; -	unsigned char *buf; -  	if((f = fopen(filename, "rb")) == NULL){  		fprintf(stderr, "Cannot open '%s'\n", filename);  		return NULL;  	} -	memset(head, 0, 4); -	fread(head, 1, 4, f); -	rewind(f); -	if(head[0] == 0xff && head[1] == 0xd8){ -		buf = loadjpeg(f, bufwidth, bufheight); -	}else if(!memcmp("\x89PNG", head, 4)){ -		buf = loadpng(f, bufwidth, bufheight); -	}else if(!memcmp("GIF", head, 3)){ -		buf = loadgif(f, bufwidth, bufheight); -	}else{ -		fprintf(stderr, "Unknown file type: '%s'\n", filename); -		buf = NULL; +	for(fmt = formats; *fmt; fmt++){ +		if((img = (*fmt)->open(f))){ +			img->fmt = *fmt; +			return img; +		}  	} -	fclose(f); -	return buf; +	fprintf(stderr, "Unknown file type: '%s'\n", filename); +	return NULL; +} + +unsigned char *loadbuf(const char *filename, int *bufwidth, int *bufheight){ +	struct image *img; +	img = imgopen(filename); +	img->buf = malloc(3 * img->width * img->height); +	*bufwidth = img->width; +	*bufheight = img->height; +	img->fmt->read(img); +	return img->buf;  }  struct imagenode{ @@ -194,7 +204,8 @@ void run(struct imagenode *image){  	int imagewidth = 0, imageheight = 0;  	int width = 0, height = 0;  	int fillw = 0, fillh = 0; -	XImage *img = NULL; +	XImage *ximg = NULL; +	struct image *img = NULL;  	unsigned char *buf = NULL;  	int redraw = 0; @@ -210,11 +221,11 @@ void run(struct imagenode *image){  					break;  				case ConfigureNotify:  					if(width != event.xconfigure.width || height != event.xconfigure.height){ -						if(img){ -							free(img->data); -							XFree(img); +						if(ximg){ +							free(ximg->data); +							XFree(ximg);  						} -						img = NULL; +						ximg = NULL;  						width = event.xconfigure.width;  						height = event.xconfigure.height;  						redraw = 1; @@ -240,13 +251,13 @@ void run(struct imagenode *image){  								image = image->prev;  								direction = -1;  							} -							if(img){ -								free(img->data); -								XFree(img); +							if(ximg){ +								free(ximg->data); +								XFree(ximg);  							}  							if(buf)  								free(buf); -							img = NULL; +							ximg = NULL;  							buf = NULL;  							redraw = 1;  							break; @@ -278,7 +289,7 @@ void run(struct imagenode *image){  				setaspect(bufwidth, bufheight);  				continue;  			} -			if(!img){ +			if(!ximg){  				if(width * bufheight > height * bufwidth){  					imagewidth = bufwidth * height / bufheight;  					imageheight = height; @@ -301,11 +312,11 @@ void run(struct imagenode *image){  					imagewidth = width;  					imageheight = height;  				} -				img = create_image_from_buffer(buf, imagewidth, imageheight, bufwidth, bufheight); -				assert(img); +				ximg = create_image_from_buffer(buf, imagewidth, imageheight, bufwidth, bufheight); +				assert(ximg);  			}  			XFillRectangle(display, window, gc, 0, 0, fillw, fillh); -			XPutImage(display, window, gc, img, 0, 0, xoffset, yoffset, width, height); +			XPutImage(display, window, gc, ximg, 0, 0, xoffset, yoffset, width, height);  			XFillRectangle(display, window, gc, width - fillw, height - fillh, fillw, fillh);  			XFlush(display);  			redraw = 0; @@ -1,6 +1,20 @@  #include <stdio.h> +struct image; + +struct imageformat{ +	struct image *(*open)(FILE *); +	int (*read)(struct image *); +}; + +struct image{ +	unsigned char *buf; +	int width, height; +	FILE *f; +	struct imageformat *fmt; +}; +  unsigned char *loadgif(FILE *, int *, int *);  unsigned char *loadjpeg(FILE *, int *, int *);  unsigned char *loadpng(FILE *, int *, int *);  | 
