diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gif.c | 77 | ||||
-rw-r--r-- | src/jpeg.c | 2 | ||||
-rw-r--r-- | src/main.c | 99 | ||||
-rw-r--r-- | src/meh.h | 4 | ||||
-rw-r--r-- | src/png.c | 103 |
5 files changed, 167 insertions, 118 deletions
@@ -1,6 +1,9 @@ #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <unistd.h> +#include <sys/types.h> #include <assert.h> @@ -8,38 +11,64 @@ #include "meh.h" +struct gif_t{ + struct image img; + FILE *f; + GifFileType *gif; +}; -unsigned char *loadgif(FILE *f, int *bufwidth, int *bufheight){ +static struct image *gif_open(FILE *f){ + struct gif_t *g; GifFileType *gif; - SavedImage *img; - GifColorType *colormap; - unsigned char *buf; + lseek(fileno(f), 0L, SEEK_SET); if(!(gif = DGifOpenFileHandle(fileno(f)))){ return NULL; } - if(DGifSlurp(gif) == GIF_ERROR){ - return NULL; - } - img = &gif->SavedImages[0]; - *bufwidth = img->ImageDesc.Width; - *bufheight = img->ImageDesc.Height; - buf = malloc(img->ImageDesc.Width * img->ImageDesc.Height * 3); - - if(img->ImageDesc.ColorMap) - colormap = img->ImageDesc.ColorMap->Colors; - else if(gif->SColorMap) - colormap = gif->SColorMap->Colors; - else - return NULL; + g = malloc(sizeof(struct gif_t)); + g->f = f; + g->gif = gif; + g->img.width = gif->SWidth; + g->img.height = gif->SHeight; + + return (struct image *)g; +} + +static int gif_read(struct image *img){ int i, j = 0; - for(i = 0; i < img->ImageDesc.Width * img->ImageDesc.Height; i++){ - unsigned char idx = img->RasterBits[i]; - buf[j++] = colormap[idx].Red; - buf[j++] = colormap[idx].Green; - buf[j++] = colormap[idx].Blue; + struct gif_t *g = (struct gif_t *)img; + GifColorType *colormap; + SavedImage *s; + + if(DGifSlurp(g->gif) == GIF_ERROR){ + PrintGifError(); + return 1; + } + + s = &g->gif->SavedImages[0]; + + if(s->ImageDesc.ColorMap) + colormap = s->ImageDesc.ColorMap->Colors; + else if(g->gif->SColorMap) + colormap = g->gif->SColorMap->Colors; + else{ + PrintGifError(); + return 1; } - return buf; + + for(i = 0; i < img->width * img->height; i++){ + unsigned char idx = s->RasterBits[i]; + img->buf[j++] = colormap[idx].Red; + img->buf[j++] = colormap[idx].Green; + img->buf[j++] = colormap[idx].Blue; + } + + return 0; } +struct imageformat giflib = { + gif_open, + gif_read +}; + @@ -99,7 +99,7 @@ static int jpeg_read(struct image *img){ return 0; } -struct imageformat jpeg = { +struct imageformat libjpeg = { jpeg_open, jpeg_read }; @@ -13,9 +13,13 @@ #include "meh.h" /* Supported Formats */ -extern struct imageformat jpeg; +extern struct imageformat libjpeg; +extern struct imageformat giflib; +extern struct imageformat libpng; struct imageformat *formats[] = { - &jpeg, + &libjpeg, + &giflib, + &libpng, NULL }; @@ -53,12 +57,13 @@ void setaspect(int w, int h){ hints->min_aspect.x = hints->max_aspect.x = w; hints->min_aspect.y = hints->max_aspect.y = h; XSetWMNormalHints(display, window, hints); + XFlush(display); XFree(hints); } -XImage *create_image_from_buffer(unsigned char *buf, int width, int height, int bufwidth, int bufheight) { +XImage *ximage(struct image *img, int width, int height) { int depth; - XImage *img = NULL; + XImage *ximg = NULL; Visual *vis; unsigned int rshift, gshift, bshift; int i; @@ -78,16 +83,16 @@ XImage *create_image_from_buffer(unsigned char *buf, int width, int height, int for(y = 0; y < height; y++){ for(x = 0; x < width; x++){ unsigned int r, g, b; - i = (y * bufheight / height * bufwidth + x * bufwidth / width) * 3; - r = (buf[i++] << rshift) & vis->red_mask; - g = (buf[i++] << gshift) & vis->green_mask; - b = (buf[i++] << bshift) & vis->blue_mask; + i = ((y * img->height / height + x) * img->width / width) * 3; + r = (img->buf[i++] << rshift) & vis->red_mask; + g = (img->buf[i++] << gshift) & vis->green_mask; + b = (img->buf[i++] << bshift) & vis->blue_mask; newBuf[y * width + x] = r | g | b; } } - img = XCreateImage (display, + ximg = XCreateImage (display, CopyFromParent, depth, ZPixmap, 0, (char *) newBuf, @@ -95,22 +100,22 @@ XImage *create_image_from_buffer(unsigned char *buf, int width, int height, int 32, 0 ); }else if(depth >= 15){ - size_t numNewBufBytes = (2 * (width * height)); + size_t numNewBufBytes = (2 * width * height); u_int16_t *newBuf = malloc (numNewBufBytes); for(y = 0; y < height; y++){ for(x = 0; x < width; x++){ unsigned int r, g, b; - i = (y * bufheight / height * bufwidth + x * bufwidth / width) * 3; - r = (buf[i++] << rshift) & vis->red_mask; - g = (buf[i++] << gshift) & vis->green_mask; - b = (buf[i++] << bshift) & vis->blue_mask; + i = ((y * img->height / height + x) * img->width / width) * 3; + r = (img->buf[i++] << rshift) & vis->red_mask; + g = (img->buf[i++] << gshift) & vis->green_mask; + b = (img->buf[i++] << bshift) & vis->blue_mask; newBuf[y * width + x] = r | g | b; } } - img = XCreateImage(display, + ximg = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0, (char *) newBuf, @@ -118,14 +123,14 @@ XImage *create_image_from_buffer(unsigned char *buf, int width, int height, int 16, 0 ); }else{ - fprintf (stderr, "This program does not support displays with a depth less than 15."); + fprintf(stderr, "This program does not support displays with a depth less than 15.\n"); exit(1); return NULL; } - XInitImage (img); + XInitImage(ximg); - return img; + return ximg; } struct image *imgopen(const char *filename){ @@ -146,16 +151,6 @@ struct image *imgopen(const char *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{ struct imagenode *next, *prev; char *filename; @@ -199,22 +194,19 @@ void init(){ void run(struct imagenode *image){ int direction = 1; - int bufwidth = 0, bufheight = 0; int xoffset = 0, yoffset = 0; int imagewidth = 0, imageheight = 0; int width = 0, height = 0; int fillw = 0, fillh = 0; XImage *ximg = NULL; struct image *img = NULL; - unsigned char *buf = NULL; int redraw = 0; for(;;){ XEvent event; for(;;){ - if(redraw && !XPending(display)){ + if(redraw && !XPending(display)) break; - } XNextEvent(display, &event); switch(event.type){ case MapNotify: @@ -229,6 +221,8 @@ void run(struct imagenode *image){ width = event.xconfigure.width; height = event.xconfigure.height; redraw = 1; + if(img) + setaspect(img->width, img->height); /* Some window managers need reminding */ } break; case Expose: @@ -255,28 +249,29 @@ void run(struct imagenode *image){ free(ximg->data); XFree(ximg); } - if(buf) - free(buf); + if(img){ + if(img->buf) + free(img->buf); + free(img); + } ximg = NULL; - buf = NULL; + img = NULL; redraw = 1; break; case XK_Return: - printf("%s\n", image->filename); break; } break; } } if(redraw){ - while(!buf){ - buf = loadbuf(image->filename, &bufwidth, &bufheight); - if(!buf){ + if(!img){ + while(!(img = imgopen(image->filename))){ + struct imagenode *tmp = image; if(image->next == image){ fprintf(stderr, "No valid images to view\n"); exit(1); } - struct imagenode *tmp = image; if(direction < 0){ image = image->prev; }else{ @@ -286,20 +281,26 @@ void run(struct imagenode *image){ tmp->next->prev = tmp->prev; free(tmp); } - setaspect(bufwidth, bufheight); - continue; + img->buf = NULL; + setaspect(img->width, img->height); + continue; /* make sure setaspect can do its thing */ + } + if(!img->buf){ + img->buf = malloc(3 * img->width * img->height); + img->fmt->read(img); + continue; /* Allow for some events to be read, read is slow */ } if(!ximg){ - if(width * bufheight > height * bufwidth){ - imagewidth = bufwidth * height / bufheight; + if(width * img->height > height * img->width){ + imagewidth = img->width * height / img->height; imageheight = height; xoffset = (width - imagewidth) / 2; yoffset = 0; fillw = xoffset; fillh = height; - }else if(width * bufheight < height * bufwidth){ + }else if(width * img->height < height * img->width){ imagewidth = width; - imageheight = bufheight * width / bufwidth; + imageheight = img->height * width / img->width; xoffset = 0; yoffset = (height - imageheight) / 2; fillw = width; @@ -312,7 +313,7 @@ void run(struct imagenode *image){ imagewidth = width; imageheight = height; } - ximg = create_image_from_buffer(buf, imagewidth, imageheight, bufwidth, bufheight); + ximg = ximage(img, imagewidth, imageheight); assert(ximg); } XFillRectangle(display, window, gc, 0, 0, fillw, fillh); @@ -325,11 +326,13 @@ void run(struct imagenode *image){ } int main(int argc, char *argv[]){ + struct imagenode *list; + if(argc < 2) usage(); init(); - struct imagenode *list = buildlist(argc - 1, &argv[1]); + list = buildlist(argc - 1, &argv[1]); run(list); return 0; @@ -15,7 +15,3 @@ struct image{ struct imageformat *fmt; }; -unsigned char *loadgif(FILE *, int *, int *); -unsigned char *loadjpeg(FILE *, int *, int *); -unsigned char *loadpng(FILE *, int *, int *); - @@ -1,65 +1,86 @@ +#include <stdlib.h> #include <png.h> #include "meh.h" -unsigned char *loadpng(FILE *infile, int *bufwidth, int *bufheight){ + +struct png_t{ + struct image img; + FILE *f; png_structp png_ptr; png_infop info_ptr; png_infop end_info; - int numpasses = 1; - unsigned char *buf; - - if((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) + int numpasses; +}; + +struct image *png_open(FILE *f){ + struct png_t *p = malloc(sizeof(struct png_t)); + if((p->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL){ + free(p); return NULL; - if((info_ptr = png_create_info_struct(png_ptr)) == NULL){ - png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); + } + if((p->info_ptr = png_create_info_struct(p->png_ptr)) == NULL){ + png_destroy_read_struct(&p->png_ptr, (png_infopp)NULL, (png_infopp)NULL); + free(p); return NULL; } - if((end_info = png_create_info_struct(png_ptr)) == NULL){ - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + if((p->end_info = png_create_info_struct(p->png_ptr)) == NULL){ + png_destroy_read_struct(&p->png_ptr, &p->info_ptr, (png_infopp)NULL); + free(p); return NULL; } - if(setjmp(png_jmpbuf(png_ptr))){ - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + if(setjmp(png_jmpbuf(p->png_ptr))){ + png_destroy_read_struct(&p->png_ptr, &p->info_ptr, &p->end_info); + free(p); return NULL; } - png_init_io(png_ptr, infile); + p->f = f; + rewind(f); + png_init_io(p->png_ptr, f); - /* Start reading */ - png_read_info(png_ptr, info_ptr); - buf = malloc(100); + png_read_info(p->png_ptr, p->info_ptr); { - png_byte color_type = png_get_color_type(png_ptr, info_ptr); + png_byte color_type = png_get_color_type(p->png_ptr, p->info_ptr); if(color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb(png_ptr); - if(color_type == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(png_ptr, info_ptr) < 8) - png_set_gray_1_2_4_to_8(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_tRNS_to_alpha(png_ptr); - if (png_get_bit_depth(png_ptr, info_ptr) == 16) - png_set_strip_16(png_ptr); + png_set_palette_to_rgb(p->png_ptr); + if(color_type == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(p->png_ptr, p->info_ptr) < 8) + png_set_gray_1_2_4_to_8(p->png_ptr); + if (png_get_valid(p->png_ptr, p->info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(p->png_ptr); + if (png_get_bit_depth(p->png_ptr, p->info_ptr) == 16) + png_set_strip_16(p->png_ptr); if(color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png_ptr); + png_set_strip_alpha(p->png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); - if(png_get_interlace_type(png_ptr, info_ptr) == PNG_INTERLACE_ADAM7) - numpasses = png_set_interlace_handling(png_ptr); - png_read_update_info(png_ptr, info_ptr); - } - { - int y; - *bufwidth = png_get_image_width(png_ptr, info_ptr); - *bufheight = png_get_image_height(png_ptr, info_ptr); - buf = malloc((*bufwidth) * (*bufheight) * 3); - printf("%ix%i\n", *bufwidth, *bufheight); - while(numpasses--){ - for(y = 0; y < *bufheight; y++) - png_read_row(png_ptr, &buf[y * (*bufwidth) * 3], NULL); - } + png_set_gray_to_rgb(p->png_ptr); + if(png_get_interlace_type(p->png_ptr, p->info_ptr) == PNG_INTERLACE_ADAM7) + p->numpasses = png_set_interlace_handling(p->png_ptr); + else + p->numpasses = 1; + png_read_update_info(p->png_ptr, p->info_ptr); } - printf("reached end\n"); - return buf; + p->img.width = png_get_image_width(p->png_ptr, p->info_ptr); + p->img.height = png_get_image_height(p->png_ptr, p->info_ptr); + + return (struct image *)p; } +int png_read(struct image *img){ + struct png_t *p = (struct png_t *)img; + int y; + while(p->numpasses--){ + for(y = 0; y < img->height; y++) + png_read_row(p->png_ptr, &img->buf[y * (img->width) * 3], NULL); + } + png_destroy_read_struct(&p->png_ptr, &p->info_ptr, &p->end_info); + return 0; +} + +struct imageformat libpng = { + png_open, + png_read +}; + + |