lel

Fork of Hiltjo's Farbfeld image viewer. (It was just for fun, not much use)
Log | Files | Refs | README | LICENSE

commit f94bedd2ab6233d4bcc8b1e34954481d6cc81f81
parent 86dbf8bb491650f298810f6bb309b9c9ba005ac8
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date:   Sun, 18 Apr 2021 02:22:30 -0700

Rework image storage

A single image buffer is now used which simplifies setup at the
minor loss of caching file handles and sharing img.view.

Diffstat:
Mlel.c | 175++++++++++++++++++++++++++++++++++---------------------------------------------
1 file changed, 76 insertions(+), 99 deletions(-)

diff --git a/lel.c b/lel.c @@ -25,8 +25,7 @@ enum { NONE = 0, LOADED = 1, SCALED = 2, DRAWN = 4 }; enum { ASPECT = 0, FULL_ASPECT, FULL_STRETCH }; struct img { - char *filename; - FILE *fp; + int index; int state; int width; int height; @@ -38,9 +37,9 @@ struct img { } view; }; -static struct img *imgs; -static struct img *cimg; -static size_t nimgs; +static struct img img; +static char **imgs; +static int nimgs; static int viewmode = ASPECT; static char *bgcolor = "#000000"; static XImage *ximg = NULL; @@ -79,14 +78,14 @@ usage(void) } static int -ff_open(struct img *img) +ff_open(struct img *img, FILE *fp) { uint32_t hdr[4]; if (img->state & LOADED) return 0; - if (fread(hdr, sizeof(*hdr), 4, img->fp) != 4) + if (fread(hdr, sizeof(*hdr), 4, fp) != 4) return -1; if (memcmp(hdr, "farbfeld", 8)) @@ -104,7 +103,7 @@ ff_open(struct img *img) } static int -ff_read(struct img *img) +ff_read(struct img *img, FILE *fp) { int i, j, off, row_len; uint16_t *row; @@ -117,7 +116,7 @@ ff_read(struct img *img) return -1; for (off = 0, i = 0; i < img->height; ++i) { - if (fread(row, 1, (size_t)row_len, img->fp) != (size_t)row_len) { + if (fread(row, 1, (size_t)row_len, fp) != (size_t)row_len) { free(row); die("unexpected EOF or row-skew at %d\n", i); } @@ -139,7 +138,6 @@ static void ff_close(struct img *img) { img->state &= ~LOADED; - rewind(img->fp); free(img->buf); } @@ -150,12 +148,12 @@ normalsize(char *newbuf) { unsigned int x, y, soff = 0, doff = 0; - for (y = 0; y < cimg->height; y++) { - for (x = 0; x < cimg->width; x++, soff += 4, doff += 4) { - newbuf[doff+0] = cimg->buf[soff+2]; - newbuf[doff+1] = cimg->buf[soff+1]; - newbuf[doff+2] = cimg->buf[soff+0]; - newbuf[doff+3] = cimg->buf[soff+3]; + for (y = 0; y < img.height; y++) { + for (x = 0; x < img.width; x++, soff += 4, doff += 4) { + newbuf[doff+0] = img.buf[soff+2]; + newbuf[doff+1] = img.buf[soff+1]; + newbuf[doff+2] = img.buf[soff+0]; + newbuf[doff+3] = img.buf[soff+3]; } } } @@ -164,12 +162,20 @@ normalsize(char *newbuf) static void loadimg(void) { - if (ff_open(cimg)) + FILE *fp; + + fp = fopen(imgs[img.index], "rb"); + if (fp == NULL) + die("open %s\n", imgs[img.index]); + if (ff_open(&img, fp)) die("can't open image (invalid format?)\n"); - if (ff_read(cimg)) + if (ff_read(&img, fp)) die("can't read image\n"); - reqwinwidth = cimg->width; - reqwinheight = cimg->height; + if (fclose(fp) != 0) + die("close %s\n", imgs[img.index]); + + reqwinwidth = img.width; + reqwinheight = img.height; } static void @@ -177,36 +183,28 @@ reloadimg(void) { loadimg(); XResizeWindow(dpy, win, reqwinwidth, reqwinheight); - XStoreName(dpy, win, cimg->filename); + XStoreName(dpy, win, imgs[img.index]); XFlush(dpy); } static void nextimg(void) { - struct img *tmp = cimg; - - cimg++; - if (cimg >= &imgs[nimgs]) - cimg = &imgs[0]; - if (tmp != cimg) { - ff_close(tmp); - reloadimg(); - } + if (img.index >= nimgs - 1) + return; + ff_close(&img); + ++img.index; + reloadimg(); } static void previmg(void) { - struct img *tmp = cimg; - - cimg--; - if (cimg < &imgs[0]) - cimg = &imgs[nimgs - 1]; - if (tmp != cimg) { - ff_close(tmp); - reloadimg(); - } + if (img.index <= 0) + return; + ff_close(&img); + --img.index; + reloadimg(); } /* scales imgbuf data to newbuf (ximg->data), nearest neighbour. */ @@ -219,10 +217,10 @@ scale(unsigned int width, unsigned int height, unsigned int bytesperline, float a = 0.0f; jdy = bytesperline / 4 - width; - dx = (cimg->width << 10) / width; + dx = (img.width << 10) / width; for (y = 0; y < height; y++) { - bufx = cimg->width / width; - ibuf = &cimg->buf[y * cimg->height / height * cimg->width * 4]; + bufx = img.width / width; + ibuf = &img.buf[y * img.height / height * img.width * 4]; for (x = 0; x < width; x++) { a = (ibuf[(bufx >> 10)*4+3]) / 255.0f; @@ -269,17 +267,17 @@ scaleview(void) ximage(winwidth, winheight); break; case FULL_ASPECT: - if (winwidth * cimg->height > winheight * cimg->width) - ximage(cimg->width * winheight / cimg->height, winheight); + if (winwidth * img.height > winheight * img.width) + ximage(img.width * winheight / img.height, winheight); else - ximage(winwidth, cimg->height * winwidth / cimg->width); + ximage(winwidth, img.height * winwidth / img.width); break; case ASPECT: default: - ximage(cimg->width * cimg->view.zoomfact, cimg->height * cimg->view.zoomfact); + ximage(img.width * img.view.zoomfact, img.height * img.view.zoomfact); break; } - cimg->state |= SCALED; + img.state |= SCALED; } static void @@ -292,8 +290,8 @@ draw(void) xoffset = (winwidth - ximg->width) / 2; yoffset = (winheight - ximg->height) / 2; /* pan offset */ - xoffset -= cimg->view.panxoffset; - yoffset -= cimg->view.panyoffset; + xoffset -= img.view.panxoffset; + yoffset -= img.view.panyoffset; } XSetForeground(dpy, gc, bg.pixel); XFillRectangle(dpy, xpix, gc, 0, 0, winwidth, winheight); @@ -301,17 +299,17 @@ draw(void) XCopyArea(dpy, xpix, win, gc, 0, 0, winwidth, winheight, 0, 0); XFlush(dpy); - cimg->state |= DRAWN; + img.state |= DRAWN; } static void update(void) { - if (!(cimg->state & LOADED)) + if (!(img.state & LOADED)) return; - if (!(cimg->state & SCALED)) + if (!(img.state & SCALED)) scaleview(); - if (!(cimg->state & DRAWN)) + if (!(img.state & DRAWN)) draw(); } @@ -321,36 +319,36 @@ setview(int mode) if (viewmode == mode) return; viewmode = mode; - cimg->state &= ~(DRAWN | SCALED); + img.state &= ~(DRAWN | SCALED); update(); } static void pan(int x, int y) { - cimg->view.panxoffset -= x; - cimg->view.panyoffset -= y; - cimg->state &= ~(DRAWN | SCALED); + img.view.panxoffset -= x; + img.view.panyoffset -= y; + img.state &= ~(DRAWN | SCALED); update(); } static void inczoom(float f) { - if ((cimg->view.zoomfact + f) <= 0) + if ((img.view.zoomfact + f) <= 0) return; - cimg->view.zoomfact += f; - cimg->state &= ~(DRAWN | SCALED); + img.view.zoomfact += f; + img.state &= ~(DRAWN | SCALED); update(); } static void zoom(float f) { - if (f == cimg->view.zoomfact) + if (f == img.view.zoomfact) return; - cimg->view.zoomfact = f; - cimg->state &= ~(DRAWN | SCALED); + img.view.zoomfact = f; + img.state &= ~(DRAWN | SCALED); update(); } @@ -370,7 +368,7 @@ buttonpress(XEvent *ev) static void printname(void) { - printf("%s\n", cimg->filename); + printf("%s\n", imgs[img.index]); } static void @@ -435,19 +433,19 @@ keypress(XEvent *ev) zoom(1.0); setview(ASPECT); /* fallthrough */ case XK_r: - cimg->view.panxoffset = 0; - cimg->view.panyoffset = 0; - cimg->state &= ~(DRAWN | SCALED); + img.view.panxoffset = 0; + img.view.panyoffset = 0; + img.state &= ~(DRAWN | SCALED); update(); break; case XK_n: nextimg(); - cimg->state &= ~(DRAWN | SCALED); + img.state &= ~(DRAWN | SCALED); update(); break; case XK_p: previmg(); - cimg->state &= ~(DRAWN | SCALED); + img.state &= ~(DRAWN | SCALED); update(); break; } @@ -470,11 +468,11 @@ handleevent(XEvent *ev) if (winwidth != ev->xconfigure.width || winheight != ev->xconfigure.height) { winwidth = ev->xconfigure.width; winheight = ev->xconfigure.height; - cimg->state &= ~(SCALED); + img.state &= ~(SCALED); } break; case Expose: - cimg->state &= ~(DRAWN); + img.state &= ~(DRAWN); update(); break; case KeyPress: @@ -503,7 +501,7 @@ setup(void) cmap = DefaultColormap(dpy, screen); if (!XAllocNamedColor(dpy, cmap, bgcolor, &bg, &bg)) die("cannot allocate color\n"); - XStoreName(dpy, win, cimg->filename); + XStoreName(dpy, win, imgs[img.index]); XSelectInput(dpy, win, StructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask); XMapRaised(dpy, win); @@ -538,35 +536,14 @@ main(int argc, char *argv[]) break; } ARGEND; + img.view.zoomfact = 1.0; + + imgs = argv; + nimgs = argc; if (!argc) { - imgs = calloc(1, sizeof(*imgs)); - if (!imgs) - die("calloc:"); - nimgs = 1; - imgs[0].filename = "/dev/stdin"; - imgs[0].fp = stdin; - imgs[0].view.zoomfact = 1.0; - } else { - imgs = calloc(argc, sizeof(*imgs)); - if (!imgs) - die("calloc:"); - for (i = 0, j = 0; j < argc; j++) { - fp = fopen(argv[j], "rb"); - if (!fp) { - fprintf(stderr, "can't open %s: %s\n", argv[j], - strerror(errno)); - continue; - } - imgs[i].filename = argv[j]; - imgs[i].fp = fp; - imgs[i].view.zoomfact = 1.0; - i++; - } - if (!i) - return 1; - nimgs = i; + ++nimgs; + *imgs = "/dev/stdin"; } - cimg = imgs; loadimg(); setup();