aboutsummaryrefslogtreecommitdiffstats
path: root/src/vu-from-image.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2017-01-10 02:31:16 +0100
committerMattias Andrée <maandree@kth.se>2017-01-10 02:31:16 +0100
commite5f405e03c8f786395ab88b8fbce5c53973cad1d (patch)
treee94debeca31fc6de32ba61ab7d367c9d61220fd7 /src/vu-from-image.c
parentvu-image-to-frame: add -h: headless frame (diff)
downloadblind-e5f405e03c8f786395ab88b8fbce5c53973cad1d.tar.gz
blind-e5f405e03c8f786395ab88b8fbce5c53973cad1d.tar.bz2
blind-e5f405e03c8f786395ab88b8fbce5c53973cad1d.tar.xz
Rename vu-image-to-frame to vu-from-image and vu-frame-to-image to vu-to-image
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src/vu-from-image.c')
-rw-r--r--src/vu-from-image.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/vu-from-image.c b/src/vu-from-image.c
new file mode 100644
index 0000000..7e70999
--- /dev/null
+++ b/src/vu-from-image.c
@@ -0,0 +1,159 @@
+/* See LICENSE file for copyright and license details. */
+#include "arg.h"
+#include "util.h"
+
+#include <sys/wait.h>
+#include <string.h>
+#include <unistd.h>
+
+static double
+get_value(void *buffer)
+{
+ unsigned char *buf = buffer;
+ unsigned long int value;
+ double ret;
+ value = (unsigned long int)(buf[0]) << 12;
+ value += (unsigned long int)(buf[1]) << 8;
+ value += (unsigned long int)(buf[2]) << 4;
+ value += (unsigned long int)(buf[3]);
+ ret = value;
+ value = 1UL << 15;
+ value |= value - 1;
+ ret /= value;
+ return ret;
+}
+
+static void
+usage(void)
+{
+ eprintf("usage: [-h] %s\n", argv0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int pipe_rw[2];
+ int i, old_fd;
+ pid_t pid;
+ int status;
+ char buf[8096];
+ size_t ptr, ptw, n;
+ char *p;
+ ssize_t r;
+ double red, green, blue, pixel[4];
+ char width[3 * sizeof(size_t) + 1] = {0};
+ char height[3 * sizeof(size_t) + 1] = {0};
+ int headless = 0;
+
+ ARGBEGIN {
+ case 'h':
+ headless = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+ if (argc)
+ usage();
+
+ if (pipe(pipe_rw))
+ eprintf("pipe:");
+
+ if (pipe_rw[0] == STDIN_FILENO || pipe_rw[1] == STDIN_FILENO)
+ eprintf("no stdin open\n");
+ if (pipe_rw[0] == STDOUT_FILENO || pipe_rw[1] == STDOUT_FILENO)
+ eprintf("no stdout open\n");
+ for (i = 0; i < 2; i++) {
+ if (pipe_rw[i] == STDERR_FILENO) {
+ pipe_rw[i] = dup(old_fd = pipe_rw[i]);
+ if (pipe_rw[i] < 0)
+ eprintf("dup:");
+ close(old_fd);
+ }
+ }
+
+ pid = fork();
+ if (pid < 0)
+ eprintf("fork:");
+
+ if (!pid) {
+ close(pipe_rw[0]);
+ if (dup2(pipe_rw[1], STDOUT_FILENO) < 0)
+ eprintf("dup2:");
+ close(pipe_rw[1]);
+ /* XXX Is there a way to convert directly to raw XYZ? (Would avoid gamut truncation) */
+ execlp("convert", "convert", "-", "-depth", "32", "-alpha", "activate", "pam:-", NULL);
+ eprintf("exec convert:");
+ }
+
+ close(pipe_rw[1]);
+
+ for (ptr = 0;;) {
+ r = read(pipe_rw[0], buf + ptr, sizeof(buf) - ptr);
+ if (r < 0)
+ eprintf("read <subprocess>:");
+ if (r == 0)
+ eprintf("convertion failed\n");
+ ptr += (size_t)r;
+
+ for (;;) {
+ p = memchr(buf, '\n', ptr);
+ if (!p) {
+ if (ptr == sizeof(buf))
+ eprintf("convertion failed\n");
+ break;
+ }
+ *p++ = '\0';
+ if (strstr(buf, "WIDTH ") == buf) {
+ if (*width || !buf[6] || strlen(buf + 6) >= sizeof(width))
+ eprintf("convertion failed\n");
+ strcpy(width, buf + 6);
+ } else if (strstr(buf, "HEIGHT ") == buf) {
+ if (*height || !buf[7] || strlen(buf + 7) >= sizeof(height))
+ eprintf("convertion failed\n");
+ strcpy(height, buf + 7);
+ } else if (!strcmp(buf, "ENDHDR")) {
+ memmove(buf, p, ptr -= (size_t)(p - buf));
+ goto header_done;
+ }
+ memmove(buf, p, ptr -= (size_t)(p - buf));
+ }
+ }
+header_done:
+ n = ptr;
+
+ if (!*width || !*height)
+ eprintf("convertion failed\n");
+
+ if (!headless) {
+ printf("%s %s xyza\n%cuivf", width, height, 0);
+ fflush(stdout);
+ if (ferror(stdout))
+ eprintf("<stdout>:");
+ }
+
+ for (;;) {
+ for (ptr = 0; ptr + 15 < n; ptr += 16) {
+ red = get_value(buf + ptr + 0);
+ green = get_value(buf + ptr + 4);
+ blue = get_value(buf + ptr + 8);
+ pixel[3] = get_value(buf + ptr + 12);
+
+ srgb_to_ciexyz(red, green, blue, pixel + 0, pixel + 1, pixel + 2);
+
+ for (ptw = 0; ptw < sizeof(pixel); ptw += (size_t)r) {
+ r = write(STDOUT_FILENO, (char *)pixel + ptw, sizeof(pixel) - ptw);
+ if (r < 0)
+ eprintf("write <stdout>:");
+ }
+ }
+ r = read(pipe_rw[0], buf, sizeof(buf));
+ if (r < 0)
+ eprintf("read <subprocess>:");
+ if (r == 0)
+ break;
+ n = (size_t)r;
+ }
+
+ while (waitpid(pid, &status, 0) != pid);
+ return !!status;
+}