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:
M | lel.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();