commit 91ab93986209afac9be673cd51f627f306b93f9d
parent 4969a4dbe94f7f47aa6054cd28d9cc41fd2df655
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date: Sun, 18 Apr 2021 18:46:22 -0700
Add image pre-processing
Process images using programs such as bunzip2(1) when their filename
matches a fnmatch(3) pattern.
The ff_read function again reads row by row. This implementation
is more efficient with both memory and, in my environment, speed.
Diffstat:
M | lel.c | | | 119 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- |
1 file changed, 107 insertions(+), 12 deletions(-)
diff --git a/lel.c b/lel.c
@@ -2,6 +2,9 @@
#include <arpa/inet.h>
#include <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <signal.h>
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
@@ -15,6 +18,8 @@
#include <X11/Xutil.h>
#include <X11/keysym.h>
+#define LEN(X) (sizeof(X) / sizeof(*X))
+
/* Image status flags. */
enum { NONE = 0, LOADED = 1, SCALED = 2, DRAWN = 4 };
@@ -34,6 +39,15 @@ struct img {
} view;
};
+struct filter {
+ char *pat;
+ char *bin;
+} filters[] = {
+ { "*.ff.bz2", "bunzip" },
+ { "*.jpg", "jpg2ff" },
+ { "*.png", "png2ff" }
+};
+
/* X11 */
static Colormap cmap;
static Display *dpy;
@@ -102,21 +116,23 @@ ff_open(struct img *img, FILE *fp)
static int
ff_read(struct img *img, FILE *fp)
{
- uint16_t *tmp;
- unsigned int i, size;
+ uint16_t *row;
+ unsigned int i, j, size;
- size = img->width * img->height * 4;
- tmp = malloc(size * sizeof(*tmp));
- if (tmp == NULL)
+ size = img->width * 4;
+ row = malloc(size * sizeof(*row));
+ if (row == NULL)
return -1;
- if (fread(tmp, sizeof(*tmp), size, fp) != size) {
- errno = EFTYPE;
- return -1;
+ for (i = 0; i < img->height; ++i) {
+ if (fread(row, sizeof(*row), size, fp) != size) {
+ errno = EFTYPE;
+ return -1;
+ }
+ for (j = 0; j < size; ++j)
+ img->buf[size * i + j] = row[j];
}
-
- for (i = 0; i < size; ++i)
- img->buf[i] = tmp[i];
+ free(row);
img->state |= LOADED;
@@ -130,12 +146,89 @@ ff_close(struct img *img)
free(img->buf);
}
+static int
+efork(void)
+{
+ pid_t pid;
+
+ if ((pid = fork()) == -1)
+ die("fork");
+ return pid;
+}
+
+static int
+filter(int d, char **argv)
+{
+ char buf[BUFSIZ];
+ int fds[4];
+ ssize_t len;
+
+ if (pipe(fds) || pipe(fds + 2))
+ return -1;
+
+ if (efork() == 0) {
+ if (dup2(fds[0], 0) == -1 || dup2(fds[3], 1) == -1)
+ die("dup2");
+ if (close(fds[1]) || close(fds[2]))
+ die("close");
+ execvp(*argv, argv);
+ die(*argv);
+ }
+
+ if (close(fds[0]) || close(fds[3])) {
+ close(fds[1]);
+ close(fds[2]);
+ return -1;
+ }
+
+ if (efork() == 0) {
+ while ((len = read(d, buf, sizeof(buf))) > 0) {
+ if (write(fds[1], buf, len) != len)
+ die("write");
+ }
+ if (len == -1)
+ die("read");
+ _exit(0);
+ }
+
+ close(fds[1]);
+ return fds[2];
+}
+
+static char *
+getbin(char *s)
+{
+ int i;
+
+ for (i = 0; i < LEN(filters); ++i) {
+ if (fnmatch(filters[i].pat, s, 0) == 0)
+ return filters[i].bin;
+ }
+ return NULL;
+}
+
static void
loadimg(void)
{
+ int d;
+ int tmp;
FILE *fp;
+ char *argv[2];
- fp = fopen(imgs[img.index], "rb");
+ d = open(imgs[img.index], O_RDONLY);
+ if (d == -1)
+ die(imgs[img.index]);
+
+ *argv = getbin(imgs[img.index]);
+ if (*argv) {
+ argv[1] = NULL;
+ tmp = filter(d, argv);
+ if (close(d) || tmp == -1)
+ die("proc");
+ d = tmp;
+ }
+
+ fp = fdopen(d, "r");
if (fp == NULL || ff_open(&img, fp) || ff_read(&img, fp) || fclose(fp))
die(imgs[img.index]);
}
@@ -484,6 +577,8 @@ setup(void)
XMapRaised(dpy, win);
XSetWMProperties(dpy, win, NULL, NULL, NULL, 0, NULL, NULL, &class);
XFlush(dpy);
+
+ signal(SIGCHLD, SIG_IGN);
}
static void