From a55738cf6d32e1d18a3c793df3c6c2797c25ebfa Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Tue, 17 Feb 2009 00:30:07 -0800 Subject: load jpegs scaled 1/8 first --- src/bmp.c | 4 ++++ src/gif.c | 3 +++ src/jpeg.c | 20 ++++++++++++++------ src/main.c | 53 +++++++++++++++++++++++++++++++++++------------------ src/meh.h | 4 ++-- src/png.c | 4 ++++ src/xlib.c | 10 +++++----- 7 files changed, 67 insertions(+), 31 deletions(-) diff --git a/src/bmp.c b/src/bmp.c index 4024521..33ba589 100644 --- a/src/bmp.c +++ b/src/bmp.c @@ -169,6 +169,9 @@ int bmp_read(struct image *img){ } free(row); + + img->state = LOADED; + return 0; } @@ -180,6 +183,7 @@ void bmp_close(struct image *img){ struct imageformat bmp = { bmp_open, + NULL, bmp_read, bmp_close }; diff --git a/src/gif.c b/src/gif.c index 8da6554..17e5d4d 100644 --- a/src/gif.c +++ b/src/gif.c @@ -77,6 +77,8 @@ static int gif_read(struct image *img){ img->buf[j++] = colormap[idx].Blue; } + img->state = LOADED; + return 0; } @@ -88,6 +90,7 @@ void gif_close(struct image *img){ struct imageformat giflib = { gif_open, + NULL, gif_read, gif_close }; diff --git a/src/jpeg.c b/src/jpeg.c index 0406c00..4271975 100644 --- a/src/jpeg.c +++ b/src/jpeg.c @@ -43,7 +43,6 @@ static struct image *jpeg_open(FILE *f){ 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_longjmp; @@ -51,8 +50,16 @@ static struct image *jpeg_open(FILE *f){ return NULL; } + j->jerr.pub.error_exit = error_exit; + return (struct image *)j; +} + +void jpeg_prep(struct image *img){ + struct jpeg_t *j = (struct jpeg_t *)img; + jpeg_create_decompress(&j->cinfo); - jpeg_stdio_src(&j->cinfo, f); + rewind(j->f); + jpeg_stdio_src(&j->cinfo, j->f); jpeg_read_header(&j->cinfo, TRUE); /* parameters */ @@ -60,17 +67,15 @@ static struct image *jpeg_open(FILE *f){ j->cinfo.do_block_smoothing = 0; j->cinfo.quantize_colors = 0; j->cinfo.dct_method = JDCT_FASTEST; - //j->cinfo.scale_denom = 1; /* TODO: This should be changed for initial display of really large jpegs */ + j->cinfo.scale_denom = img->state < FASTLOADED ? 8 : 1; /* TODO: This should be changed done only for large jpegs */ jpeg_calc_output_dimensions(&j->cinfo); j->img.bufwidth = j->cinfo.output_width; j->img.bufheight = j->cinfo.output_height; - - j->jerr.pub.error_exit = error_exit; - return (struct image *)j; } + static int jpeg_read(struct image *img){ struct jpeg_t *j = (struct jpeg_t *)img; unsigned int row_stride; @@ -110,6 +115,8 @@ static int jpeg_read(struct image *img){ } jpeg_finish_decompress(&j->cinfo); + img->state = j->cinfo.scale_denom == 1 ? LOADED : FASTLOADED; + return 0; } @@ -121,6 +128,7 @@ void jpeg_close(struct image *img){ struct imageformat libjpeg = { jpeg_open, + jpeg_prep, jpeg_read, jpeg_close }; diff --git a/src/main.c b/src/main.c index 49b4cef..cddb436 100644 --- a/src/main.c +++ b/src/main.c @@ -197,25 +197,42 @@ int doredraw(struct image **i){ } } - setaspect((*i)->bufwidth, (*i)->bufheight); + (*i)->buf = NULL; + (*i)->state = NONE; + }else{ + imgstate dstate = (*i)->state + 1; + if(dstate == LOADED || dstate == FASTLOADED){ + if((*i)->fmt->prep){ + (*i)->fmt->prep(*i); + } + setaspect((*i)->bufwidth, (*i)->bufheight); - (*i)->buf = malloc(3 * (*i)->bufwidth * (*i)->bufheight); - TDEBUG_START - if((*i)->fmt->read(*i)){ - fprintf(stderr, "read error!\n"); - } - TDEBUG_END("read") - (*i)->fmt->close(*i); - (*i)->state = LOADED; - }else if(width && height){ - imgstate state = (*i)->state; - if(state == LOADED){ - (*i)->ximg = getimage(*i, width, height); - (*i)->state = SCALED; - }else if(state == SCALED){ - assert((*i)->ximg); - drawimage((*i)->ximg, width, height); - (*i)->state = DRAWN; + if((*i)->buf) + free((*i)->buf); + (*i)->buf = malloc(3 * (*i)->bufwidth * (*i)->bufheight); + + TDEBUG_START + if((*i)->fmt->read(*i)){ + fprintf(stderr, "read error!\n"); + } + TDEBUG_END("read"); + + if((*i)->state == LOADED){ + /* We are done with the format's methods */ + (*i)->fmt->close(*i); + } + + /* state should be set by format */ + assert((*i)->state == LOADED || (*i)->state == FASTLOADED); + }else if(width && height){ + if(dstate == SCALED || dstate == FASTSCALED){ + (*i)->ximg = getimage(*i, width, height, dstate == FASTSCALED); + (*i)->state = dstate; + }else if(dstate == DRAWN || dstate == FASTDRAWN){ + assert((*i)->ximg); + drawimage((*i)->ximg, width, height); + (*i)->state = dstate; + } } } return (*i)->state != DRAWN; diff --git a/src/meh.h b/src/meh.h index a17d730..8465887 100644 --- a/src/meh.h +++ b/src/meh.h @@ -7,6 +7,7 @@ struct image; struct imageformat{ struct image *(*open)(FILE *); + void (*prep)(struct image *); int (*read)(struct image *); void (*close)(struct image *); }; @@ -30,11 +31,10 @@ struct image{ XImage *ximg; }; -XImage *ximage(struct image *img, unsigned int width, unsigned int height); void setaspect(unsigned int w, unsigned int h); void xinit(); void drawimage(XImage *ximg, unsigned int width, unsigned int height); -XImage *getimage(struct image *img, unsigned int width, unsigned int height); +XImage *getimage(struct image *img, unsigned int width, unsigned int height, int fast); #ifdef TDEBUG #define TDEBUG_START \ diff --git a/src/png.c b/src/png.c index 6f567b1..9aab2f8 100644 --- a/src/png.c +++ b/src/png.c @@ -97,6 +97,9 @@ int png_read(struct image *img){ png_read_image(p->png_ptr, row_pointers); free(row_pointers); + + img->state = LOADED; + return 0; } @@ -108,6 +111,7 @@ void png_close(struct image *img){ struct imageformat libpng = { png_open, + NULL, png_read, png_close }; diff --git a/src/xlib.c b/src/xlib.c index 7dfa69b..ca0a1b5 100644 --- a/src/xlib.c +++ b/src/xlib.c @@ -25,7 +25,7 @@ void scale(struct image *img, XImage *ximg); void linearscale(struct image *img, XImage *ximg); XShmSegmentInfo *shminfo; -XImage *ximage(struct image *img, unsigned int width, unsigned int height) { +XImage *ximage(struct image *img, unsigned int width, unsigned int height, int fast){ int depth; XImage *ximg = NULL; Visual *vis; @@ -71,7 +71,7 @@ XImage *ximage(struct image *img, unsigned int width, unsigned int height) { ximg->data = malloc(ximg->bytes_per_line * ximg->height); XInitImage(ximg); } - scale(img, ximg); + (fast ? linearscale : scale)(img, ximg); }else{ /* TODO other depths */ fprintf(stderr, "This program does not yet support display depths <24.\n"); @@ -82,11 +82,11 @@ XImage *ximage(struct image *img, unsigned int width, unsigned int height) { return ximg; } -XImage *getimage(struct image *img, unsigned int width, unsigned int height){ +XImage *getimage(struct image *img, unsigned int width, unsigned int height, int fast){ if(width * img->bufheight > height * img->bufwidth){ - return ximage(img, img->bufwidth * height / img->bufheight, height); + return ximage(img, img->bufwidth * height / img->bufheight, height, fast); }else{ - return ximage(img, width, img->bufheight * width / img->bufwidth); + return ximage(img, width, img->bufheight * width / img->bufwidth, fast); } } -- cgit v1.2.3