aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/jpeg.c107
-rw-r--r--src/main.c73
-rw-r--r--src/meh.h14
3 files changed, 122 insertions, 72 deletions
diff --git a/src/jpeg.c b/src/jpeg.c
index 749d448..68efa39 100644
--- a/src/jpeg.c
+++ b/src/jpeg.c
@@ -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
+};
diff --git a/src/main.c b/src/main.c
index cbb0fdc..74cb4ca 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
diff --git a/src/meh.h b/src/meh.h
index 719b717..0e1a410 100644
--- a/src/meh.h
+++ b/src/meh.h
@@ -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 *);