diff options
Diffstat (limited to 'src/vu-image-to-frame.c')
| -rw-r--r-- | src/vu-image-to-frame.c | 98 |
1 files changed, 67 insertions, 31 deletions
diff --git a/src/vu-image-to-frame.c b/src/vu-image-to-frame.c index 693ddf7..c4bc69b 100644 --- a/src/vu-image-to-frame.c +++ b/src/vu-image-to-frame.c @@ -6,21 +6,21 @@ #include <string.h> #include <unistd.h> -static char * -xmemmem(char *h, const char *n, size_t hn, size_t nn) +static double +get_value(void *buffer) { - char *p, *end; - if (nn > hn) - return NULL; - end = h + (hn - nn + 1); - for (p = h; p != end; p++) { - p = memchr(p, *n, (size_t)(end - p)); - if (!p) - return NULL; - if (!memcmp(p, n, nn)) - return p; - } - return NULL; + 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 @@ -37,9 +37,12 @@ main(int argc, char *argv[]) pid_t pid; int status; char buf[8096]; - size_t ptr, n; + 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}; ARGBEGIN { default: @@ -73,10 +76,11 @@ main(int argc, char *argv[]) if (dup2(pipe_rw[1], STDOUT_FILENO) < 0) eprintf("dup2:"); close(pipe_rw[1]); - execlp("convert", "convert", "-", "-depth", "8", "-alpha", "activate", "pam:-", NULL); + /* 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;;) { @@ -84,24 +88,56 @@ main(int argc, char *argv[]) if (r < 0) eprintf("read <subprocess>:"); if (r == 0) - break; + eprintf("convertion failed\n"); ptr += (size_t)r; - p = xmemmem(buf, "\nENDHDR\n", ptr, sizeof("\nENDHDR\n") - 1); - if (!p) - continue; - p += sizeof("\nENDHDR\n") - 1; - n = (size_t)(p - buf); - memmove(buf, buf + n, ptr - n); - n = ptr - n; - break; + + 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: + + if (!*width || !*height) + eprintf("convertion failed\n"); + + printf("%s %s xyza\n%cuivf", width, height, 0); + fflush(stdout); + if (ferror(stdout)) + eprintf("<stdout>:"); for (;;) { - for (ptr = 0; ptr < n;) { - r = write(STDOUT_FILENO, buf + ptr, n - ptr); - if (r < 0) - eprintf("write <stdout>:"); - ptr += (size_t)r; + 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) |
