lel

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

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:
Mlel.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