aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gif.c77
-rw-r--r--src/jpeg.c2
-rw-r--r--src/main.c99
-rw-r--r--src/meh.h4
-rw-r--r--src/png.c103
5 files changed, 167 insertions, 118 deletions
diff --git a/src/gif.c b/src/gif.c
index 93a4517..a6a13d6 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -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
+};
+
diff --git a/src/jpeg.c b/src/jpeg.c
index 68efa39..db36a8b 100644
--- a/src/jpeg.c
+++ b/src/jpeg.c
@@ -99,7 +99,7 @@ static int jpeg_read(struct image *img){
return 0;
}
-struct imageformat jpeg = {
+struct imageformat libjpeg = {
jpeg_open,
jpeg_read
};
diff --git a/src/main.c b/src/main.c
index 74cb4ca..cad5085 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
diff --git a/src/meh.h b/src/meh.h
index 0e1a410..bd91910 100644
--- a/src/meh.h
+++ b/src/meh.h
@@ -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 *);
-
diff --git a/src/png.c b/src/png.c
index 0dac9b5..6631708 100644
--- a/src/png.c
+++ b/src/png.c
@@ -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
+};
+
+