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 *); |