From 4674ec0e4b833ab0d0365225ba99228df14abe87 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Fri, 13 Jan 2017 09:05:08 +0100 Subject: Rename to blind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- .gitignore | 2 +- Makefile | 60 +++++----- src/blind-arithm.c | 80 +++++++++++++ src/blind-colour-srgb.c | 43 +++++++ src/blind-concat.c | 114 ++++++++++++++++++ src/blind-crop.c | 86 ++++++++++++++ src/blind-cut.c | 70 +++++++++++ src/blind-dissolve.c | 70 +++++++++++ src/blind-extend.c | 103 ++++++++++++++++ src/blind-flip.c | 36 ++++++ src/blind-flop.c | 44 +++++++ src/blind-from-image.c | 273 +++++++++++++++++++++++++++++++++++++++++++ src/blind-from-text.c | 71 +++++++++++ src/blind-from-video.c | 285 +++++++++++++++++++++++++++++++++++++++++++++ src/blind-gauss-blur.c | 189 ++++++++++++++++++++++++++++++ src/blind-invert-luma.c | 73 ++++++++++++ src/blind-next-frame.c | 63 ++++++++++ src/blind-read-head.c | 63 ++++++++++ src/blind-repeat.c | 59 ++++++++++ src/blind-reverse.c | 47 ++++++++ src/blind-rewrite-head.c | 129 ++++++++++++++++++++ src/blind-set-alpha.c | 69 +++++++++++ src/blind-set-luma.c | 47 ++++++++ src/blind-set-saturation.c | 79 +++++++++++++ src/blind-single-colour.c | 88 ++++++++++++++ src/blind-split.c | 72 ++++++++++++ src/blind-stack.c | 80 +++++++++++++ src/blind-to-image.c | 150 ++++++++++++++++++++++++ src/blind-to-text.c | 51 ++++++++ src/blind-to-video.c | 146 +++++++++++++++++++++++ src/blind-transpose.c | 45 +++++++ src/blind-write-head.c | 18 +++ src/vu-arithm.c | 80 ------------- src/vu-colour-srgb.c | 43 ------- src/vu-concat.c | 114 ------------------ src/vu-crop.c | 86 -------------- src/vu-cut.c | 70 ----------- src/vu-dissolve.c | 70 ----------- src/vu-extend.c | 103 ---------------- src/vu-flip.c | 36 ------ src/vu-flop.c | 44 ------- src/vu-from-image.c | 273 ------------------------------------------- src/vu-from-text.c | 71 ----------- src/vu-from-video.c | 285 --------------------------------------------- src/vu-gauss-blur.c | 189 ------------------------------ src/vu-invert-luma.c | 73 ------------ src/vu-next-frame.c | 63 ---------- src/vu-read-head.c | 63 ---------- src/vu-repeat.c | 59 ---------- src/vu-reverse.c | 47 -------- src/vu-rewrite-head.c | 129 -------------------- src/vu-set-alpha.c | 69 ----------- src/vu-set-luma.c | 47 -------- src/vu-set-saturation.c | 79 ------------- src/vu-single-colour.c | 88 -------------- src/vu-split.c | 72 ------------ src/vu-stack.c | 80 ------------- src/vu-to-image.c | 150 ------------------------ src/vu-to-text.c | 51 -------- src/vu-to-video.c | 146 ----------------------- src/vu-transpose.c | 45 ------- src/vu-write-head.c | 18 --- 62 files changed, 2774 insertions(+), 2774 deletions(-) create mode 100644 src/blind-arithm.c create mode 100644 src/blind-colour-srgb.c create mode 100644 src/blind-concat.c create mode 100644 src/blind-crop.c create mode 100644 src/blind-cut.c create mode 100644 src/blind-dissolve.c create mode 100644 src/blind-extend.c create mode 100644 src/blind-flip.c create mode 100644 src/blind-flop.c create mode 100644 src/blind-from-image.c create mode 100644 src/blind-from-text.c create mode 100644 src/blind-from-video.c create mode 100644 src/blind-gauss-blur.c create mode 100644 src/blind-invert-luma.c create mode 100644 src/blind-next-frame.c create mode 100644 src/blind-read-head.c create mode 100644 src/blind-repeat.c create mode 100644 src/blind-reverse.c create mode 100644 src/blind-rewrite-head.c create mode 100644 src/blind-set-alpha.c create mode 100644 src/blind-set-luma.c create mode 100644 src/blind-set-saturation.c create mode 100644 src/blind-single-colour.c create mode 100644 src/blind-split.c create mode 100644 src/blind-stack.c create mode 100644 src/blind-to-image.c create mode 100644 src/blind-to-text.c create mode 100644 src/blind-to-video.c create mode 100644 src/blind-transpose.c create mode 100644 src/blind-write-head.c delete mode 100644 src/vu-arithm.c delete mode 100644 src/vu-colour-srgb.c delete mode 100644 src/vu-concat.c delete mode 100644 src/vu-crop.c delete mode 100644 src/vu-cut.c delete mode 100644 src/vu-dissolve.c delete mode 100644 src/vu-extend.c delete mode 100644 src/vu-flip.c delete mode 100644 src/vu-flop.c delete mode 100644 src/vu-from-image.c delete mode 100644 src/vu-from-text.c delete mode 100644 src/vu-from-video.c delete mode 100644 src/vu-gauss-blur.c delete mode 100644 src/vu-invert-luma.c delete mode 100644 src/vu-next-frame.c delete mode 100644 src/vu-read-head.c delete mode 100644 src/vu-repeat.c delete mode 100644 src/vu-reverse.c delete mode 100644 src/vu-rewrite-head.c delete mode 100644 src/vu-set-alpha.c delete mode 100644 src/vu-set-luma.c delete mode 100644 src/vu-set-saturation.c delete mode 100644 src/vu-single-colour.c delete mode 100644 src/vu-split.c delete mode 100644 src/vu-stack.c delete mode 100644 src/vu-to-image.c delete mode 100644 src/vu-to-text.c delete mode 100644 src/vu-to-video.c delete mode 100644 src/vu-transpose.c delete mode 100644 src/vu-write-head.c diff --git a/.gitignore b/.gitignore index 3f64319..d29a89a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ *.swp *.o *.out -/vu-* +/blind-* diff --git a/Makefile b/Makefile index 0259f0d..690a3e9 100644 --- a/Makefile +++ b/Makefile @@ -2,36 +2,36 @@ CONFIGFILE = config.mk include $(CONFIGFILE) BIN =\ - vu-arithm\ - vu-colour-srgb\ - vu-concat\ - vu-crop\ - vu-cut\ - vu-dissolve\ - vu-extend\ - vu-flip\ - vu-flop\ - vu-from-image\ - vu-from-text\ - vu-from-video\ - vu-gauss-blur\ - vu-invert-luma\ - vu-next-frame\ - vu-read-head\ - vu-repeat\ - vu-reverse\ - vu-rewrite-head\ - vu-set-alpha\ - vu-set-luma\ - vu-set-saturation\ - vu-single-colour\ - vu-split\ - vu-stack\ - vu-to-image\ - vu-to-text\ - vu-to-video\ - vu-transpose\ - vu-write-head + blind-arithm\ + blind-colour-srgb\ + blind-concat\ + blind-crop\ + blind-cut\ + blind-dissolve\ + blind-extend\ + blind-flip\ + blind-flop\ + blind-from-image\ + blind-from-text\ + blind-from-video\ + blind-gauss-blur\ + blind-invert-luma\ + blind-next-frame\ + blind-read-head\ + blind-repeat\ + blind-reverse\ + blind-rewrite-head\ + blind-set-alpha\ + blind-set-luma\ + blind-set-saturation\ + blind-single-colour\ + blind-split\ + blind-stack\ + blind-to-image\ + blind-to-text\ + blind-to-video\ + blind-transpose\ + blind-write-head all: $(BIN) diff --git a/src/blind-arithm.c b/src/blind-arithm.c new file mode 100644 index 0000000..ce85287 --- /dev/null +++ b/src/blind-arithm.c @@ -0,0 +1,80 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include +#include + +USAGE("right-hand-stream") + +/* Because the syntax for a function returning a function pointer is disgusting. */ +typedef void (*process_func)(struct stream *left, struct stream *right, size_t n); + +#define LIST_OPERATORS\ + X(add, *lh += rh)\ + X(sub, *lh -= rh)\ + X(mul, *lh *= rh)\ + X(div, *lh /= rh)\ + X(exp, *lh = pow(*lh, rh))\ + X(log, *lh = log(*lh) / log(rh))\ + X(min, *lh = *lh < rh ? *lh : rh)\ + X(max, *lh = *lh > rh ? *lh : rh) + +#define X(NAME, ALGO)\ + static void\ + process_lf_##NAME(struct stream *left, struct stream *right, size_t n)\ + {\ + size_t i;\ + double *lh, rh;\ + for (i = 0; i < n; i += 4 * sizeof(double)) {\ + lh = ((double *)(left->buf + i)) + 0, rh = ((double *)(right->buf + i))[0];\ + ALGO;\ + lh = ((double *)(left->buf + i)) + 1, rh = ((double *)(right->buf + i))[1];\ + ALGO;\ + lh = ((double *)(left->buf + i)) + 2, rh = ((double *)(right->buf + i))[2];\ + ALGO;\ + lh = ((double *)(left->buf + i)) + 3, rh = ((double *)(right->buf + i))[3];\ + ALGO;\ + }\ + } +LIST_OPERATORS +#undef X + +static process_func +get_lf_process(const char *operation) +{ +#define X(NAME, ALGO)\ + if (!strcmp(operation, #NAME)) return process_lf_##NAME; +LIST_OPERATORS +#undef X + eprintf("algorithm not recognised: %s\n", operation); + return NULL; +} + +int +main(int argc, char *argv[]) +{ + struct stream left, right; + process_func process = NULL; + + ENOFLAGS(argc != 1); + + left.file = ""; + left.fd = STDIN_FILENO; + einit_stream(&left); + + right.file = argv[1]; + right.fd = eopen(right.file, O_RDONLY); + einit_stream(&right); + + if (!strcmp(left.pixfmt, "xyza")) + process = get_lf_process(argv[0]); + else + eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt); + + process_two_streams(&left, &right, STDOUT_FILENO, "", process); + return 0; +} diff --git a/src/blind-colour-srgb.c b/src/blind-colour-srgb.c new file mode 100644 index 0000000..53fb784 --- /dev/null +++ b/src/blind-colour-srgb.c @@ -0,0 +1,43 @@ +/* See LICENSE file for copyright and license details. */ +#include "util.h" + +USAGE("[-d depth] [-l] red green blue") + +int +main(int argc, char *argv[]) +{ + unsigned long long int max; + double red, green, blue, X, Y, Z; + int depth = 8, linear = 0; + + ARGBEGIN { + case 'd': + depth = etoi_flag('d', EARG(), 1, 64); + break; + case 'l': + linear = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 3) + usage(); + + max = 1ULL << (depth - 1); + max |= max - 1; + red = etolf_arg("the red value", argv[0]) / max; + green = etolf_arg("the green value", argv[1]) / max; + blue = etolf_arg("the blue value", argv[2]) / max; + if (!linear) { + red = srgb_decode(red); + green = srgb_decode(green); + blue = srgb_decode(blue); + } + + srgb_to_ciexyz(red, green, blue, &X, &Y, &Z); + printf("%lf %lf %lf\n", X, Y, Z); + + efshut(stdout, ""); + return 0; +} diff --git a/src/blind-concat.c b/src/blind-concat.c new file mode 100644 index 0000000..95676e2 --- /dev/null +++ b/src/blind-concat.c @@ -0,0 +1,114 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include +#include + +USAGE("[-o output-file] first-stream ... last-stream") + +static void +concat_to_stdout(int argc, char *argv[]) +{ + struct stream *streams; + size_t frames = 0; + int i; + + streams = emalloc((size_t)argc * sizeof(*streams)); + + for (i = 0; i < argc; i++) { + streams[i].file = argv[i]; + streams[i].fd = eopen(streams[i].file, O_RDONLY); + einit_stream(streams + i); + if (i) + echeck_compat(streams + i, streams); + if (streams[i].frames > SIZE_MAX - frames) + eprintf("resulting video is too long\n"); + frames += streams[i].frames; + } + + streams->frames = frames; + fprint_stream_head(stdout, streams); + efflush(stdout, ""); + + for (; argc--; streams++) { + for (; eread_stream(streams, SIZE_MAX); streams->ptr = 0) + ewriteall(STDOUT_FILENO, streams->buf, streams->ptr, ""); + close(streams->fd); + } + + free(streams); +} + +static void +concat_to_file(int argc, char *argv[], char *output_file) +{ + struct stream stream, refstream; + int first = 0; + int fd = eopen(output_file, O_RDWR | O_CREAT | O_TRUNC, 0666); + char head[STREAM_HEAD_MAX]; + ssize_t headlen, size = 0; + char *data; + + for (; argc--; argv++) { + stream.file = *argv; + stream.fd = eopen(stream.file, O_RDONLY); + einit_stream(&stream); + + if (first) { + stream = refstream; + } else { + if (refstream.frames > SIZE_MAX - stream.frames) + eprintf("resulting video is too long\n"); + refstream.frames += stream.frames; + echeck_compat(&stream, &refstream); + } + + for (; eread_stream(&stream, SIZE_MAX); stream.ptr = 0) { + ewriteall(STDOUT_FILENO, stream.buf, stream.ptr, ""); + size += stream.ptr; + } + close(stream.fd); + } + + sprintf(head, "%zu %zu %zu %s\n%cuivf%zn", + stream.frames, stream.width, stream.height, stream.pixfmt, 0, &headlen); + + ewriteall(fd, head, (size_t)headlen, output_file); + + data = mmap(0, size + (size_t)headlen, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (data == MAP_FAILED) + eprintf("mmap %s:", output_file); + memmove(data + headlen, data, size); + memcpy(data, head, (size_t)headlen); + munmap(data, size + (size_t)headlen); + + close(fd); +} + +int +main(int argc, char *argv[]) +{ + char *output_file = NULL; + + ARGBEGIN { + case 'o': + output_file = EARG(); + break; + default: + usage(); + } ARGEND; + + if (argc < 2) + usage(); + + if (output_file) + concat_to_file(argc, argv, output_file); + else + concat_to_stdout(argc, argv); + + return 0; +} diff --git a/src/blind-crop.c b/src/blind-crop.c new file mode 100644 index 0000000..bf5a930 --- /dev/null +++ b/src/blind-crop.c @@ -0,0 +1,86 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include + +USAGE("[-t] width height left top") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + char *buf, *image, *p; + size_t width = 0, height = 0, left = 0, top = 0; + size_t off, yoff = 0, x, y, irown, orown, ptr, n, m; + int tile = 0; + + ARGBEGIN { + case 't': + tile = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 4) + usage(); + + width = etozu_arg("the width", argv[0], 1, SIZE_MAX); + height = etozu_arg("the height", argv[1], 1, SIZE_MAX); + left = etozu_arg("the left position", argv[2], 0, SIZE_MAX); + top = etozu_arg("the top position", argv[3], 0, SIZE_MAX); + + stream.file = ""; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + if (left + width > stream.width || top + height > stream.height) + eprintf("crop area extends beyond original image\n"); + if (tile) { + fprint_stream_head(stdout, &stream); + } else { + x = stream.width, stream.width = width; + y = stream.height, stream.height = height; + fprint_stream_head(stdout, &stream); + stream.width = x; + stream.height = y; + } + efflush(stdout, ""); + + echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); + n = stream.height * (irown = stream.width * stream.pixel_size); + buf = emalloc(n); + orown = width * stream.pixel_size; + m = tile ? n : height * orown; + image = emalloc(m); + + left *= stream.pixel_size; + if (!tile) { + off = top * irown; + } else { + off = (orown - (left % orown)) % orown; + yoff = (height - (top % height)) % height; + } + + memcpy(buf, stream.buf, ptr = stream.ptr); + while (eread_frame(&stream, buf, n)) { + if (!tile) { + for (y = 0; y < height; y++) + memcpy(image + y * orown, buf + y * irown + off, orown); + } else { + for (ptr = y = 0; y < stream.height; y++) { + p = buf + ((y + yoff) % height) * irown + left; + for (x = 0; x < irown; x++, ptr++) + image[ptr++] = p[(x + off) % orown]; + } + } + ewriteall(STDOUT_FILENO, image, m, ""); + } + + free(buf); + free(image); + return 0; +} diff --git a/src/blind-cut.c b/src/blind-cut.c new file mode 100644 index 0000000..e229cf1 --- /dev/null +++ b/src/blind-cut.c @@ -0,0 +1,70 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include +#include + +USAGE("start-point (end-point | 'end') file") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + size_t frame_size, start = 0, end = 0, ptr, max; + ssize_t r; + char buf[BUFSIZ]; + int to_end = 0; + + ENOFLAGS(argc != 3); + + if (!strcmp(argv[0], "end")) + eprintf("refusing to create video with zero frames\n"); + else + start = etozu_arg("the start point", argv[1], 0, SIZE_MAX); + + if (!strcmp(argv[1], "end")) + to_end = 1; + else + end = etozu_arg("the end point", argv[1], 0, SIZE_MAX); + + stream.file = argv[2]; + stream.fd = eopen(stream.file, O_RDONLY); + einit_stream(&stream); + if (to_end) + end = stream.frames; + else if (end > stream.frames) + eprintf("end point is after end of video\n"); + stream.frames = end - start; + fprint_stream_head(stdout, &stream); + efflush(stdout, ""); + echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); + frame_size = stream.width * stream.height * stream.pixel_size; + if (stream.frames > SSIZE_MAX / frame_size) + eprintf("%s: video is too large\n", stream.file); + + if (start >= end) + eprintf("%s\n", start > end ? + "start point is after end point" : + "refusing to create video with zero frames"); + end = end * frame_size + stream.headlen; + start = start * frame_size + stream.headlen; + + posix_fadvise(stream.fd, start, end - start, POSIX_FADV_SEQUENTIAL); + for (ptr = start; ptr < end; ptr += (size_t)r) { + max = end - ptr; + max = max < sizeof(buf) ? max : sizeof(buf); + r = pread(stream.fd, buf, max, ptr); + if (r < 0) + eprintf("pread %s:", stream.file); + if (r == 0) + eprintf("%s: file is shorter than expected\n", stream.file); + ewriteall(STDOUT_FILENO, buf, (size_t)r, ""); + } + + close(stream.fd); + return 0; +} diff --git a/src/blind-dissolve.c b/src/blind-dissolve.c new file mode 100644 index 0000000..83b9091 --- /dev/null +++ b/src/blind-dissolve.c @@ -0,0 +1,70 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include + +USAGE("[-r]") + +static size_t fm; +static double fmd; + +static void +process_xyza(struct stream *stream, size_t n, size_t f) +{ + size_t i; + double a; + for (i = 0; i < n; i += stream->pixel_size) { + a = ((double *)(stream->buf + i))[3]; + a = a * (double)f / fmd; + ((double *)(stream->buf + i))[3] = a; + } +} + +static void +process_xyza_r(struct stream *stream, size_t n, size_t f) +{ + size_t i; + double a; + for (i = 0; i < n; i += stream->pixel_size) { + a = ((double *)(stream->buf + i))[3]; + a = a * (double)(fm - f) / fmd; + ((double *)(stream->buf + i))[3] = a; + } +} + +int +main(int argc, char *argv[]) +{ + struct stream stream; + int reverse = 0; + void (*process)(struct stream *stream, size_t n, size_t f) = NULL; + + ARGBEGIN { + case 'r': + reverse = 1; + break; + default: + usage(); + } ARGEND; + + if (argc) + usage(); + + stream.fd = STDIN_FILENO; + stream.file = ""; + einit_stream(&stream); + fprint_stream_head(stdout, &stream); + efflush(stdout, ""); + + if (!strcmp(stream.pixfmt, "xyza")) + process = reverse ? process_xyza_r : process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); + + fmd = fm = stream.frames - 1; + process_each_frame_segmented(&stream, STDOUT_FILENO, "", process); + + return 0; +} diff --git a/src/blind-extend.c b/src/blind-extend.c new file mode 100644 index 0000000..71be7f0 --- /dev/null +++ b/src/blind-extend.c @@ -0,0 +1,103 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include + +USAGE("[-l left] [-r right] [-a above] [-b below] [-t]") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + char *buf, *image; + size_t ptr, n, m, imgw, imgh, rown; + size_t xoff, yoff, h, x, y; + size_t left = 0, right = 0, top = 0, bottom = 0; + int tile = 0; + + ARGBEGIN { + case 'l': + left = etozu_flag('l', EARG(), 0, SIZE_MAX); + break; + case 'r': + right = etozu_flag('r', EARG(), 0, SIZE_MAX); + break; + case 'a': + top = etozu_flag('a', EARG(), 0, SIZE_MAX); + break; + case 'b': + bottom = etozu_flag('b', EARG(), 0, SIZE_MAX); + break; + case 't': + tile = 1; + break; + default: + usage(); + } ARGEND; + + if (argc) + usage(); + + stream.file = ""; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + + echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); + n = stream.height * stream.width * stream.pixel_size; + buf = emalloc(n); + + if (stream.width > SIZE_MAX - left) + eprintf(": output video is too wide\n"); + imgw = stream.width + left; + if (imgw > SIZE_MAX - right) + eprintf(": output video is too wide\n"); + imgw += right; + if (stream.height > SIZE_MAX - top) + eprintf(": output video is too tall\n"); + imgh = stream.height + top; + if (imgh > SIZE_MAX - bottom) + eprintf(": output video is too tall\n"); + imgh += bottom; + echeck_frame_size(imgw, imgh, stream.pixel_size, "output", ""); + m = imgh * (imgw *= stream.pixel_size); + image = tile ? emalloc(m) : ecalloc(1, m); + + stream.width += left + right; + h = stream.height += top + bottom; + fprint_stream_head(stdout, &stream); + efflush(stdout, ""); + stream.width -= left + right; + stream.height -= top + bottom; + + left *= stream.pixel_size; + right *= stream.pixel_size; + rown = stream.width * stream.pixel_size; + + xoff = (rown - (left % rown)) % rown; + yoff = (stream.height - (top % stream.height)) % stream.height; + + memcpy(buf, stream.buf, ptr = stream.ptr); + while (eread_frame(&stream, buf, n)) { + if (!tile) { + for (y = 0; y < stream.height; y++) + memcpy(image + left + (y + top) * imgw, buf + y * rown, rown); + } else { + for (y = 0; y < stream.height; y++) + for (x = 0; x < imgw; x++) + image[x + (y + top) * imgw] = buf[((x + xoff) % rown) + y * rown]; + for (y = 0; y < top; y++) + memcpy(image + y * imgw, image + (((y + yoff) % stream.height) + top) * imgw, imgw); + for (y = top + stream.height; y < h; y++) + memcpy(image + y * imgw, image + (((y + yoff) % stream.height) + top) * imgw, imgw); + } + ewriteall(STDOUT_FILENO, image, m, ""); + } + + free(buf); + free(image); + return 0; +} diff --git a/src/blind-flip.c b/src/blind-flip.c new file mode 100644 index 0000000..98e0d58 --- /dev/null +++ b/src/blind-flip.c @@ -0,0 +1,36 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include + +USAGE("") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + size_t n, ptr, row_size; + char *buf; + + ENOFLAGS(argc); + + stream.file = ""; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + fprint_stream_head(stdout, &stream); + efflush(stdout, ""); + + echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); + n = stream.height * (row_size = stream.width * stream.pixel_size); + buf = emalloc(n); + + memcpy(buf, stream.buf, stream.ptr); + while (eread_frame(&stream, buf, n)) + for (ptr = n; ptr;) + ewriteall(STDOUT_FILENO, buf + (ptr -= row_size), row_size, ""); + + free(buf); + return 0; +} diff --git a/src/blind-flop.c b/src/blind-flop.c new file mode 100644 index 0000000..e98771d --- /dev/null +++ b/src/blind-flop.c @@ -0,0 +1,44 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include + +USAGE("") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + char *buf, *image; + size_t i, j, n, m; + + ENOFLAGS(argc); + + stream.file = ""; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + fprint_stream_head(stdout, &stream); + efflush(stdout, ""); + + if (stream.width > SIZE_MAX / stream.pixel_size) + eprintf(": video frame is too wide\n"); + n = stream.width * stream.pixel_size; + buf = emalloc(n); + image = emalloc(n); + + m = n - stream.pixel_size; + memcpy(buf, stream.buf, stream.ptr); + while (eread_row(&stream, buf, n)) { + for (i = 0; i < stream.pixel_size; i++) + for (j = 0; j < n; j += stream.pixel_size) + image[m - j + i] = buf[i + j]; + ewriteall(STDOUT_FILENO, image, n, ""); + } + + free(buf); + free(image); + return 0; +} diff --git a/src/blind-from-image.c b/src/blind-from-image.c new file mode 100644 index 0000000..9c2d047 --- /dev/null +++ b/src/blind-from-image.c @@ -0,0 +1,273 @@ +/* See LICENSE file for copyright and license details. */ +#include "util.h" + +#include +#include +#include +#include +#include + +USAGE("[-h] [-f | -p]") + +static char buf[BUFSIZ]; +static char width[3 * sizeof(size_t) + 1] = {0}; +static char height[3 * sizeof(size_t) + 1] = {0}; +static const char *conv_fail_msg = "convertion failed, if converting a farbfeld file, try -f"; +static size_t pixel_size; +static double value_max; +static double (*get_value)(char **bufp); +static void (*convert)(size_t n); +static int with_alpha = 1; +static int with_colour = 1; + +static double +get_value_u8(char** bufp) +{ + uint8_t value = *(uint8_t *)(*bufp); + *bufp += 1; + return value / value_max; +} + +static double +get_value_u16(char** bufp) +{ + uint16_t value = ntohs(*(uint16_t *)(*bufp)); + *bufp += 2; + return value / value_max; +} + +static double +get_value_u32(char** bufp) +{ + uint32_t value = ntohl(*(uint32_t *)(*bufp)); + *bufp += 4; + return value / value_max; +} + +static double +get_value_u64(char** bufp) +{ + uint64_t value; + value = (uint64_t)(buf[0]) << 56; + value |= (uint64_t)(buf[1]) << 48; + value |= (uint64_t)(buf[2]) << 40; + value |= (uint64_t)(buf[3]) << 32; + value |= (uint64_t)(buf[4]) << 24; + value |= (uint64_t)(buf[5]) << 16; + value |= (uint64_t)(buf[6]) << 8; + value |= (uint64_t)(buf[7]); + *bufp += 8; + return value / value_max; +} + +static void +from_srgb(size_t n) +{ + double red, green, blue, pixel[4]; + size_t ptr; + char *p; + for (ptr = 0; ptr + pixel_size <= n; ptr += pixel_size) { + p = buf + ptr; + red = srgb_decode(get_value(&p)); + green = with_colour ? srgb_decode(get_value(&p)) : red; + blue = with_colour ? srgb_decode(get_value(&p)) : red; + pixel[3] = with_alpha ? get_value(&p) : 1; + srgb_to_ciexyz(red, green, blue, pixel + 0, pixel + 1, pixel + 2); + ewriteall(STDOUT_FILENO, pixel, sizeof(pixel), ""); + } +} + +static size_t +farbfeld_head(int fd, const char *fname) +{ + if (ereadall(fd, buf, 16, fname) != 16) + eprintf("%s\n", conv_fail_msg); + if (memcmp(buf, "farbfeld", 8)) + eprintf("%s\n", conv_fail_msg); + sprintf(width, "%"PRIu32, ntohl(*(uint32_t *)(buf + 8))); + sprintf(height, "%"PRIu32, ntohl(*(uint32_t *)(buf + 12))); + pixel_size = 4 * sizeof(uint16_t); + value_max = UINT16_MAX; + get_value = get_value_u16; + convert = from_srgb; + return 0; +} + +static size_t +pam_head(int fd, const char *fname) +{ + size_t ptr; + char *p; + unsigned long long int maxval = UINT8_MAX; + for (ptr = 0;;) { + ptr += ereadall(fd, buf + ptr, (size_t)buf - ptr, fname); + for (;;) { + p = memchr(buf, '\n', ptr); + if (!p) { + if (ptr == sizeof(buf)) + eprintf("%s\n", conv_fail_msg); + break; + } + *p++ = '\0'; + if (strstr(buf, "WIDTH ") == buf) { + if (*width || !buf[6] || strlen(buf + 6) >= sizeof(width)) + eprintf("%s\n", conv_fail_msg); + strcpy(width, buf + 6); + } else if (strstr(buf, "HEIGHT ") == buf) { + if (*height || !buf[7] || strlen(buf + 7) >= sizeof(height)) + eprintf("%s\n", conv_fail_msg); + strcpy(height, buf + 7); + } else if (strstr(buf, "MAXVAL ") == buf) { + if (tollu(buf + 7, 0, UINT64_MAX, &maxval)) { + if (errno != ERANGE) + eprintf("%s\n", conv_fail_msg); + eprintf("image uses greater colour resolution than supported\n"); + } else if (!maxval) { + eprintf("%s\n", conv_fail_msg); + } + } else if (strstr(buf, "TUPLTYPE ") == buf) { + if (!strcmp(buf, "TUPLTYPE BLACKANDWHITE")) + maxval = 1, with_colour = 0, with_alpha = 0; + else if (!strcmp(buf, "TUPLTYPE BLACKANDWHITE_ALPHA")) + maxval = 1, with_colour = 0, with_alpha = 1; + else if (!strcmp(buf, "TUPLTYPE GRAYSCALE")) + with_colour = 0, with_alpha = 0; + else if (!strcmp(buf, "TUPLTYPE GRAYSCALE_ALPHA")) + with_colour = 0, with_alpha = 1; + else if (!strcmp(buf, "TUPLTYPE RGB")) + with_colour = 1, with_alpha = 0; + else if (!strcmp(buf, "TUPLTYPE RGB_ALPHA")) + with_colour = 1, with_alpha = 1; + else + eprintf("image uses an unsupported tuple type: %s\n", buf + sizeof("TUPLTYPE")); + } 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 (maxval < (size_t)UINT8_MAX) { + pixel_size = sizeof(uint8_t); + get_value = get_value_u8; + } else if (maxval < (size_t)UINT16_MAX) { + pixel_size = sizeof(uint16_t); + get_value = get_value_u16; + } else if (maxval < (size_t)UINT32_MAX) { + pixel_size = sizeof(uint32_t); + get_value = get_value_u32; + } else { + pixel_size = sizeof(uint64_t); + get_value = get_value_u64; + } + value_max = maxval; + pixel_size *= (with_colour ? 3 : 1) + with_alpha; + convert = from_srgb; + return ptr; +} + +int +main(int argc, char *argv[]) +{ + int status, pipe_rw[2], i, old_fd, forked = 0; + int headless = 0, farbfeld = 0, pam = 0; + pid_t pid = 0; + size_t off, n; + ssize_t r; + const char *file = ""; + const char *conv_fail_msg = "convertion failed, if converting a farbfeld file, try -f"; + + ARGBEGIN { + case 'f': + farbfeld = 1; + break; + case 'h': + headless = 1; + break; + case 'p': + pam = 1; + break; + default: + usage(); + } ARGEND; + + if (argc || (farbfeld && pam)) + usage(); + + if (farbfeld) + conv_fail_msg = "not a valid farbfeld file, try without -f"; + else if (pam) + conv_fail_msg = "not a valid RGBA portable arbitrary map file, try without -p"; + else + forked = 1; + + if (forked) { + file = ""; + pipe_rw[0] = STDIN_FILENO; + goto after_fork; + } + + 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) == -1) + 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]); +after_fork: + + if (farbfeld) + n = farbfeld_head(pipe_rw[0], file); + else + n = pam_head(pipe_rw[0], file); + + if (!*width || !*height) + eprintf("%s\n", conv_fail_msg); + + if (!headless) { + printf("1 %s %s xyza\n%cuivf", width, height, 0); + efflush(stdout, ""); + } + + for (;;) { + convert(n); + off = n - (n % pixel_size); + memmove(buf, buf + off, n -= off); + r = read(pipe_rw[0], buf + n, sizeof(buf) - n); + if (r < 0) + eprintf("read %s:", file); + if (r == 0) + break; + n += (size_t)r; + } + + if (!forked) + return 0; + close(pipe_rw[0]); + while (waitpid(pid, &status, 0) != pid); + return !!status; +} diff --git a/src/blind-from-text.c b/src/blind-from-text.c new file mode 100644 index 0000000..88cee62 --- /dev/null +++ b/src/blind-from-text.c @@ -0,0 +1,71 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include + +USAGE("") + +static void +process_xyza(struct stream *stream) +{ + double buf[BUFSIZ / sizeof(double)]; + size_t i; + int r, done = 0; + + while (!done) { + for (i = 0; i < ELEMENTSOF(buf); i += (size_t)r) { + r = scanf("%lf", buf + i); + if (r == EOF) { + done = 1; + break; + } + } + ewriteall(STDOUT_FILENO, buf, i * sizeof(*buf), ""); + } +} + +int +main(int argc, char *argv[]) +{ + struct stream stream; + size_t size = 0; + char *line = NULL; + ssize_t len; + void (*process)(struct stream *stream) = NULL; + + ENOFLAGS(argc); + + len = getline(&line, &size, stdin); + if (len < 0) { + if (ferror(stdin)) + eprintf("getline :"); + else + eprintf(": no input\n"); + } + if (len && line[len - 1] == '\n') + line[--len] = '\n'; + if (len + 6 > sizeof(stream.buf)) + eprintf(": head is too long\n"); + stream.fd = -1; + stream.file = ""; + memcpy(stream.buf, line, (size_t)len); + memcpy(stream.buf + len, "\n\0uivf", 6); + stream.ptr = (size_t)len + 6; + free(line); + ewriteall(STDOUT_FILENO, stream.buf, stream.ptr, ""); + einit_stream(&stream); + + if (!strcmp(stream.pixfmt, "xyza")) + process = process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); + + process(&stream); + + efshut(stdin, ""); + return 0; +} diff --git a/src/blind-from-video.c b/src/blind-from-video.c new file mode 100644 index 0000000..c780b55 --- /dev/null +++ b/src/blind-from-video.c @@ -0,0 +1,285 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#if defined(HAVE_PRCTL) +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +USAGE("[-r frame-rate] [-w width -h height] [-d] input-file output-file") + +static int draft = 0; + +static void +read_metadata(FILE *fp, char *fname, size_t *width, size_t *height, size_t *frames) +{ + char *line = NULL; + size_t size = 0; + ssize_t len; + int have_width = !width, have_height = !height, have_frames = 0; + char *p; + + while ((len = getline(&line, &size, fp)) != -1) { + if (len && line[len - 1]) + line[--len] = '\0'; + p = strchr(line, '=') + 1; + if (width && strstr(line, "width=") == line) { + if (tozu(p, 1, SIZE_MAX, width)) + eprintf("invalid width: %s\n", p); + have_width = 1; + } else if (height && strstr(line, "height=") == line) { + if (tozu(p, 1, SIZE_MAX, height)) + eprintf("invalid height: %s\n", p); + have_height = 1; + } else if (strstr(line, "nb_read_frames=") == line) { + if (tozu(p, 0, SIZE_MAX, frames)) + eprintf("invalid frame count: %s\n", p); + have_frames = 1; + } + } + + if (ferror(fp)) + eprintf("getline %s:", fname); + free(line); + + if (have_width + have_height + have_frames < 3) + eprintf("could not get all required metadata\n"); +} + +static void +get_metadata(char *file, size_t *width, size_t *height, size_t *frames) +{ + FILE *fp; + int fd, pipe_rw[2]; + pid_t pid; + int status; + + if (pipe(pipe_rw)) + eprintf("pipe:"); + + pid = fork(); + if (pid == -1) + eprintf("fork:"); + + if (!pid) { +#if defined(HAVE_PRCTL) && defined(PR_SET_PDEATHSIG) + prctl(PR_SET_PDEATHSIG, SIGKILL); +#endif + fd = eopen(file, O_RDONLY); + if (dup2(fd, STDIN_FILENO) == -1) + eprintf("dup2:"); + close(fd); + close(pipe_rw[0]); + if (dup2(pipe_rw[1], STDOUT_FILENO) == -1) + eprintf("dup2:"); + close(pipe_rw[1]); + execlp("ffprobe", "ffprobe", "-v", "quiet", "-show_streams", + "-select_streams", "v", "-count_frames", "-", NULL); + eprintf("exec ffprobe:"); + } + + close(pipe_rw[1]); + fp = fdopen(pipe_rw[0], "rb"); + if (!fp) + eprintf("fdopen :"); + read_metadata(fp, file, width, height, frames); + fclose(fp); + close(pipe_rw[0]); + + if (waitpid(pid, &status, 0) == -1) + eprintf("waitpid:"); + if (status) + exit(1); +} + +static void +convert_segment(char *buf, size_t n, int fd, char *file) +{ + typedef double pixel_t[4]; + size_t i, ptr; + double y, u, v, max = (double)UINT16_MAX; + double r, g, b; + pixel_t pixels[1024]; + if (draft) { + for (ptr = i = 0; ptr < n; ptr += 8) { + pixels[i][3] = ntohs(((uint16_t *)(buf + ptr))[0]) / max; + y = (ntohs(((uint16_t *)(buf + ptr))[1]) - 16 * 256); + u = (ntohs(((uint16_t *)(buf + ptr))[2]) - 128 * 256); + v = (ntohs(((uint16_t *)(buf + ptr))[3]) - 128 * 256); + scaled_yuv_to_ciexyz(y, u, v, pixels[i] + 0, pixels[i] + 1, pixels[i] + 2); + if (++i == 1024) { + i = 0; + ewriteall(fd, pixels, sizeof(pixels), file); + } + } + } else { + for (ptr = i = 0; ptr < n; ptr += 8) { + pixels[i][3] = ntohs(((uint16_t *)(buf + ptr))[0]) / max; + y = (ntohs(((uint16_t *)(buf + ptr))[1]) - 16 * 256) / max; + u = (ntohs(((uint16_t *)(buf + ptr))[2]) - 128 * 256) / max; + v = (ntohs(((uint16_t *)(buf + ptr))[3]) - 128 * 256) / max; + yuv_to_srgb(y, u, v, &r, &g, &b); + r = srgb_decode(r); + g = srgb_decode(g); + b = srgb_decode(b); + srgb_to_ciexyz(r, g, b, pixels[i] + 0, pixels[i] + 1, pixels[i] + 2); + if (++i == 1024) { + i = 0; + ewriteall(fd, pixels, sizeof(pixels), file); + } + } + } + if (i) + ewriteall(fd, pixels, i * sizeof(*pixels), file); +} + +static void +convert(char *infile, int outfd, char *outfile, size_t width, size_t height, char *frame_rate) +{ + char geometry[2 * 3 * sizeof(size_t) + 2], *cmd[13], buf[BUFSIZ]; + int status, fd, pipe_rw[2]; + size_t i = 0, n, ptr; + ssize_t r; + pid_t pid; + + cmd[i++] = "ffmpeg"; + cmd[i++] = "-i", cmd[i++] = "-"; + cmd[i++] = "-f", cmd[i++] = "rawvideo"; + cmd[i++] = "-pix_fmt", cmd[i++] = "ayuv64le"; + if (width && height) { + sprintf(geometry, "%zux%zu", width, height); + cmd[i++] = "-s:v", cmd[i++] = geometry; + } + if (frame_rate) + cmd[i++] = "-r", cmd[i++] = frame_rate; + cmd[i++] = "-"; + cmd[i++] = NULL; + + if (pipe(pipe_rw)) + eprintf("pipe:"); + + pid = fork(); + if (pid == -1) + eprintf("fork:"); + + if (!pid) { +#if defined(HAVE_PRCTL) && defined(PR_SET_PDEATHSIG) + prctl(PR_SET_PDEATHSIG, SIGKILL); +#endif + fd = eopen(infile, O_RDONLY); + if (dup2(fd, STDIN_FILENO) == -1) + eprintf("dup2:"); + close(fd); + close(pipe_rw[0]); + if (dup2(pipe_rw[1], STDOUT_FILENO) == -1) + eprintf("dup2:"); + close(pipe_rw[1]); + execvp("ffmpeg", cmd); + eprintf("exec ffmpeg:"); + } + + close(pipe_rw[1]); + + for (ptr = 0;;) { + r = read(pipe_rw[0], buf + ptr, sizeof(buf) - ptr); + if (r < 0) + eprintf("read :"); + if (r == 0) + break; + ptr += (size_t)r; + n = ptr - (ptr % 8); + convert_segment(buf, n, outfd, outfile); + memmove(buf, buf + n, ptr -= n); + } + if (ptr) + eprintf(": incomplete frame\n"); + + close(pipe_rw[0]); + if (waitpid(pid, &status, 0) == -1) + eprintf("waitpid:"); + if (status) + exit(1); +} + +int +main(int argc, char *argv[]) +{ + size_t width = 0, height = 0, frames; + char head[STREAM_HEAD_MAX]; + char *frame_rate = NULL; + char *infile; + char *outfile; + char *data; + ssize_t headlen; + size_t length; + int outfd, status; + pid_t pid; + struct stat st; + + ARGBEGIN { + case 'd': + draft = 1; + break; + case 'r': + frame_rate = EARG(); + break; + case 'w': + width = etozu_flag('w', EARG(), 1, SIZE_MAX); + break; + case 'h': + height = etozu_flag('h', EARG(), 1, SIZE_MAX); + break; + default: + usage(); + } ARGEND; + + if (argc != 2 || !width != !height) + usage(); + + infile = argv[0]; + outfile = argv[1]; + + outfd = eopen(outfile, O_RDWR | O_CREAT | O_TRUNC, 0666); + + pid = fork(); + if (pid == -1) + eprintf("fork:"); + + if (!pid) { +#if defined(HAVE_PRCTL) && defined(PR_SET_PDEATHSIG) + prctl(PR_SET_PDEATHSIG, SIGKILL); +#endif + convert(infile, outfd, outfile, width, height, frame_rate); + exit(0); + } + + get_metadata(infile, width ? NULL : &width, height ? NULL : &height, &frames); + + if (waitpid(pid, &status, 0) == -1) + eprintf("waitpid:"); + if (status) + exit(1); + + if (fstat(outfd, &st)) + eprintf("fstat %s:", outfile); + length = (size_t)(st.st_size); + + sprintf(head, "%zu %zu %zu %s\n%cuivf%zn", frames, width, height, "xyza", 0, &headlen); + ewriteall(outfd, head, (size_t)headlen, outfile); + data = mmap(0, length + (size_t)headlen, PROT_READ | PROT_WRITE, MAP_PRIVATE, outfd, 0); + memmove(data + headlen, data, length); + memcpy(data, head, (size_t)headlen); + munmap(data, length + (size_t)headlen); + + close(outfd); + return 0; +} diff --git a/src/blind-gauss-blur.c b/src/blind-gauss-blur.c new file mode 100644 index 0000000..b64391c --- /dev/null +++ b/src/blind-gauss-blur.c @@ -0,0 +1,189 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include + +USAGE("[-j jobs] [-ac] sd-stream") + +static int chroma = 0; +static int noalpha = 0; +static size_t jobs = 1; + +static void +process_xyza(char *restrict output, char *restrict cbuf, char *restrict sbuf, + struct stream *colour, struct stream *sigma, size_t n, size_t unused) +{ + typedef double pixel_t[4]; + + pixel_t *restrict clr = (pixel_t *)cbuf; + pixel_t *restrict sig = (pixel_t *)sbuf; + pixel_t *img = (pixel_t *)output; + pixel_t c, k; + double *p; + size_t x1, y1, i1, x2, y2, i2; + double dy, d, m, dblurred; + int i, blurred, blur[3] = {0, 0, 0}; + size_t start = 0, end = colour->height; + int is_master; + + /* premultiply alpha channel */ + if (!noalpha) { + for (y1 = i1 = 0; y1 < colour->height; y1++) { + for (x1 = 0; x1 < colour->width; x1++, i1++) { + clr[i1][0] *= clr[i1][3]; + clr[i1][1] *= clr[i1][3]; + clr[i1][2] *= clr[i1][3]; + } + } + } + + is_master = efork_jobs(&start, &end, jobs); + + /* blur */ + i1 = start * colour->width; + for (y1 = i1 = start; y1 < end; y1++) { + for (x1 = 0; x1 < colour->width; x1++, i1++) { + if (sig[i1][3] == 0) + goto no_blur; + if (!chroma) { + for (i = 0; i < 3; i++) { + k[i] = sig[i1][i] * sig[i1][3], c[i] = k[i] *= k[i] * 2, c[i] *= M_PI; + k[i] = 1 / k[i], c[i] = -1 / c[i]; + blur[i] = !sig[i1][1]; + } + } else { + k[1] = sig[i1][1] * sig[i1][3], c[1] = k[1] *= k[1] * 2, c[1] *= M_PI; + k[1] = 1 / -k[1], c[1] = 1 / c[1]; + blur[1] = !sig[i1][1]; + } + if (blur[0] + blur[1] + blur[2] == 0) + goto no_blur; + + p = img[i1]; + p[0] = p[1] = p[2] = 0; + p[3] = noalpha; + if (k[0] == k[1] && k[1] == k[2]) { + for (y2 = i2 = 0; y2 < colour->height; y2++) { + dy = (ssize_t)y1 - (ssize_t)y2; + dy *= dy; + for (x2 = 0; x2 < colour->width; x2++, i2++) { + d = (ssize_t)x1 - (ssize_t)x2; + d = d * d + dy; + m = c[i1] * exp(d * k[i1]); + for (i = noalpha ? 3 : 4; i--;) + p[i] += clr[i2][i] * m; + } + } + } else { + blurred = 0; + for (i = 0; i < n; i++) { + if (!blur[i]) { + p[i] = clr[i1][i]; + continue; + } + for (y2 = i2 = 0; y2 < colour->height; y2++) { + dy = (ssize_t)y1 - (ssize_t)y2; + dy *= dy; + if (!noalpha) { + for (x2 = 0; x2 < colour->width; x2++, i2++) { + d = (ssize_t)x1 - (ssize_t)x2; + d = d * d + dy; + m = c[i1] * exp(d * k[i1]); + p[i] += clr[i2][i] * m; + p[3] += clr[i2][3] * m; + } + } else { + for (x2 = 0; x2 < colour->width; x2++, i2++) { + d = (ssize_t)x1 - (ssize_t)x2; + d = d * d + dy; + m = c[i1] * exp(d * k[i1]); + p[i] += clr[i2][i] * m; + } + } + } + blurred += 1; + } + if (!noalpha) { + dblurred = blurred; + for (y2 = i2 = 0; y2 < colour->height; y2++) + for (x2 = 0; x2 < colour->width; x2++, i2++) + p[3] /= dblurred; + } + } + + continue; + no_blur: + img[i1][0] = clr[i1][0]; + img[i1][1] = clr[i1][1]; + img[i1][2] = clr[i1][2]; + img[i1][3] = clr[i1][3]; + } + } + + ejoin_jobs(is_master); + + /* unpremultiply alpha channel */ + if (!noalpha) { + for (y1 = i1 = 0; y1 < colour->height; y1++) { + for (x1 = 0; x1 < colour->width; x1++, i1++) { + if (!img[i1][3]) + continue; + img[i1][0] /= img[i1][3]; + img[i1][1] /= img[i1][3]; + img[i1][2] /= img[i1][3]; + } + } + } + + (void) unused; +} + +int +main(int argc, char *argv[]) +{ + struct stream colour, sigma; + void (*process)(char *restrict output, char *restrict cbuf, char *restrict sbuf, + struct stream *colour, struct stream *sigma, size_t cn, size_t sn); + + ARGBEGIN { + case 'a': + noalpha = 1; + break; + case 'c': + chroma = 1; + break; + case 'j': + jobs = etozu_flag('j', EARG(), 1, SHRT_MAX); + break; + default: + usage(); + } ARGEND; + + if (argc != 1) + usage(); + + colour.file = ""; + colour.fd = STDIN_FILENO; + einit_stream(&colour); + + sigma.file = argv[0]; + sigma.fd = eopen(sigma.file, O_RDONLY); + einit_stream(&sigma); + + if (!strcmp(colour.pixfmt, "xyza")) + process = process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); + + echeck_compat(&colour, &sigma); + + process_each_frame_two_streams(&colour, &sigma, STDOUT_FILENO, "", process); + + return 0; +} diff --git a/src/blind-invert-luma.c b/src/blind-invert-luma.c new file mode 100644 index 0000000..aa3b260 --- /dev/null +++ b/src/blind-invert-luma.c @@ -0,0 +1,73 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include + +USAGE("[-i] mask-stream") + +static void +process_xyza(struct stream *colour, struct stream *mask, size_t n) +{ + size_t i; + double w, y; + for (i = 0; i < n; i += colour->pixel_size) { + w = ((double *)(mask->buf + i))[1]; + w *= ((double *)(mask->buf + i))[3]; + y = ((double *)(colour->buf + i))[3]; + y = (1 - y) * w + y * (1 - w); + ((double *)(colour->buf + i))[3] = y; + } +} + +static void +process_xyza_i(struct stream *colour, struct stream *mask, size_t n) +{ + size_t i; + double w, y; + for (i = 0; i < n; i += colour->pixel_size) { + w = 1 - ((double *)(mask->buf + i))[1]; + w *= ((double *)(mask->buf + i))[3]; + y = ((double *)(colour->buf + i))[3]; + y = (1 - y) * w + y * (1 - w); + ((double *)(colour->buf + i))[3] = y; + } +} + +int +main(int argc, char *argv[]) +{ + int invert = 0; + struct stream colour, mask; + void (*process)(struct stream *colour, struct stream *mask, size_t n) = NULL; + + ARGBEGIN { + case 'i': + invert = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 1) + usage(); + + colour.file = ""; + colour.fd = STDIN_FILENO; + einit_stream(&colour); + + mask.file = argv[0]; + mask.fd = eopen(mask.file, O_RDONLY); + einit_stream(&mask); + + if (!strcmp(colour.pixfmt, "xyza")) + process = invert ? process_xyza_i : process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); + + process_two_streams(&colour, &mask, STDOUT_FILENO, "", process); + return 0; +} diff --git a/src/blind-next-frame.c b/src/blind-next-frame.c new file mode 100644 index 0000000..6a55790 --- /dev/null +++ b/src/blind-next-frame.c @@ -0,0 +1,63 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include + +USAGE("width height pixel-format ...") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + size_t n, w; + int i, anything = 0; + char *p; + + ENOFLAGS(argc < 3); + + stream.frames = 1; + stream.fd = STDIN_FILENO; + stream.file = ""; + stream.pixfmt[0] = '\0'; + + stream.width = entozu_arg(2, "the width", argv[0], 1, SIZE_MAX); + stream.height = entozu_arg(2, "the height", argv[1], 1, SIZE_MAX); + argv += 2, argc -= 2; + + n = (size_t)argc - 1; + for (i = 0; i < argc; i++) + n += strlen(argv[i]); + if (n < sizeof(stream.pixfmt)) { + p = stpcpy(stream.pixfmt, argv[0]); + for (i = 1; i < argc; i++) { + *p++ = ' '; + p = stpcpy(p, argv[i]); + } + } + + enset_pixel_size(2, &stream); + + fprint_stream_head(stdout, &stream); + enfflush(2, stdout, ""); + + w = stream.width * stream.pixel_size; + while (stream.height) { + stream.height--; + for (n = w; n; n -= stream.ptr) { + stream.ptr = 0; + if (!enread_stream(2, &stream, n)) + goto done; + anything = 1; + enwriteall(2, STDOUT_FILENO, stream.buf, stream.ptr, ""); + } + } +done: + + if (stream.height || n) + enprintf(2, "incomplete frame\n"); + + return !anything; +} diff --git a/src/blind-read-head.c b/src/blind-read-head.c new file mode 100644 index 0000000..afb2fbc --- /dev/null +++ b/src/blind-read-head.c @@ -0,0 +1,63 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include + +USAGE("") + +int +main(int argc, char *argv[]) +{ + char buf[STREAM_HEAD_MAX]; + char magic[] = {'\0', 'u', 'i', 'v', 'f'}; + char b, *p; + size_t i, ptr; + ssize_t r; + + ENOFLAGS(argc); + + for (ptr = 0; ptr < sizeof(buf);) { + r = read(STDIN_FILENO, buf + ptr, 1); + if (r < 0) + eprintf("read :"); + if (r == 0) + goto bad_format; + if (buf[ptr++] == '\n') + break; + } + if (ptr == sizeof(buf)) + goto bad_format; + + p = buf; + for (i = 0; i < 5; i++) { + r = read(STDIN_FILENO, &b, 1); + if (r < 0) + eprintf("read :"); + if (r == 0 || b != magic[i]) + goto bad_format; + } + + for (i = 0; i < 3; i++) { + if (!isdigit(*p)) + goto bad_format; + while (isdigit(*p)) p++; + if (*p++ != ' ') + goto bad_format; + } + while (isalnum(*p) || *p == ' ') { + if (p[0] == ' ' && p[-1] == ' ') + goto bad_format; + p++; + } + if (p[-1] == ' ' || p[0] != '\n') + goto bad_format; + + ewriteall(STDOUT_FILENO, buf, ptr, ""); + + return 0; +bad_format: + eprintf(": file format not supported\n"); + return 0; +} diff --git a/src/blind-repeat.c b/src/blind-repeat.c new file mode 100644 index 0000000..367d976 --- /dev/null +++ b/src/blind-repeat.c @@ -0,0 +1,59 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include +#include + +USAGE("(count | 'inf') file") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + size_t count = 0, ptr; + ssize_t r; + char buf[BUFSIZ]; + int inf = 0; + + ENOFLAGS(argc != 2); + + if (!strcmp(argv[0], "inf")) + inf = 1; + else + count = etozu_arg("the count", argv[0], 0, SIZE_MAX); + + if (inf) + einf_check_fd(STDOUT_FILENO, ""); + + stream.file = argv[1]; + stream.fd = eopen(stream.file, O_RDONLY); + einit_stream(&stream); + if (count > SIZE_MAX / stream.frames) + eprintf("%s: video is too long\n", stream.file); + stream.frames *= count; + fprint_stream_head(stdout, &stream); + efflush(stdout, ""); + + while (inf || count--) { + posix_fadvise(stream.fd, stream.headlen, 0, POSIX_FADV_SEQUENTIAL); + for (ptr = stream.headlen;; ptr += (size_t)r) { + r = pread(stream.fd, buf, sizeof(buf), ptr); + if (r < 0) + eprintf("pread %s:", stream.file); + if (r == 0) + break; + if (writeall(STDOUT_FILENO, buf, (size_t)r)) { + if (!inf || errno != EPIPE) + eprintf("write :"); + return 0; + } + } + } + + close(stream.fd); + return 0; +} diff --git a/src/blind-reverse.c b/src/blind-reverse.c new file mode 100644 index 0000000..5c978f2 --- /dev/null +++ b/src/blind-reverse.c @@ -0,0 +1,47 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include + +USAGE("file") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + size_t frame_size, ptr, end, n; + ssize_t r; + char buf[BUFSIZ]; + + ENOFLAGS(argc != 1); + + stream.file = argv[0]; + stream.fd = eopen(stream.file, O_RDONLY); + einit_stream(&stream); + fprint_stream_head(stdout, &stream); + efflush(stdout, ""); + echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); + frame_size = stream.width * stream.height * stream.pixel_size; + if (stream.frames > SSIZE_MAX / frame_size) + eprintf("%s: video is too large\n", stream.file); + + posix_fadvise(stream.fd, 0, 0, POSIX_FADV_RANDOM); + while (stream.frames--) { + ptr = stream.frames * frame_size; + end = ptr + frame_size; + while (ptr < end) { + r = pread(stream.fd, buf, sizeof(buf), ptr); + if (r < 0) + eprintf("pread %s:", stream.file); + else if (r == 0) + eprintf("%s: file is shorter than expected\n", stream.file); + ptr += n = (size_t)r; + ewriteall(STDOUT_FILENO, buf, n, ""); + } + } + + close(stream.fd); + return 0; +} diff --git a/src/blind-rewrite-head.c b/src/blind-rewrite-head.c new file mode 100644 index 0000000..0de1716 --- /dev/null +++ b/src/blind-rewrite-head.c @@ -0,0 +1,129 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include +#include + +USAGE("[-h] file [(frames | 'auto') [(width | 'same') (height | 'same') [format | 'same']]]") + +static void +rewrite(struct stream *stream, int frames_auto) +{ + char head[STREAM_HEAD_MAX]; + ssize_t headlen; + size_t frame_size, frame_count, length; + struct stat st; + char *data; + + echeck_frame_size(stream->width, stream->height, stream->pixel_size, 0, stream->file); + frame_size = stream->width * stream->height * stream->pixel_size; + + if (fstat(stream->fd, &st)) + eprintf("fstat %s:", stream->file); + if (!S_ISREG(st.st_mode)) + eprintf("%s: not a regular file\n", stream->file); + + frame_count = (size_t)(st.st_size) / frame_size; + if (frame_count * frame_size != (size_t)(st.st_size)) + eprintf("%s: given the select width and height, " + "the file has an incomplete frame\n", stream->file); + if (frames_auto) + stream->frames = frame_count; + else if (stream->frames != frame_count) + eprintf("%s: frame count mismatch\n", stream->file); + + sprintf(head, "%zu %zu %zu %s\n%cuivf%zn", + stream->frames, stream->width, stream->height, stream->pixfmt, 0, &headlen); + + length = stream->frames * frame_size; + if (length > (size_t)SSIZE_MAX || headlen > (size_t)SSIZE_MAX - length) + eprintf("%s: video is too long\n", stream->file); + + if (headlen > stream->headlen) + if (ftruncate(stream->fd, length + headlen)) + eprintf("ftruncate %s:", stream->file); + + data = mmap(0, length + (size_t)headlen, PROT_READ | PROT_WRITE, MAP_PRIVATE, stream->fd, 0); + if (data == MAP_FAILED) + eprintf("mmap %s:", stream->file); + if (headlen != stream->headlen) + memmove(data + headlen, data + stream->headlen, length); + memcpy(data, head, (size_t)headlen); + munmap(data, length + (size_t)headlen); + + if (headlen < stream->headlen) + if (ftruncate(stream->fd, length + headlen)) + eprintf("ftruncate %s:", stream->file); +} + +int +main(int argc, char *argv[]) +{ + struct stream stream; + int headless = 0, frames_auto = 0; + + ARGBEGIN { + case 'h': + headless = 1; + break; + default: + usage(); + } ARGEND; + + + if (headless) { + if (argc != 5) + eprintf("all positional arguments are mandatory unless -h is used\n"); + } else if (argc != 1 || argc != 2 || argc != 4 || argc != 5) { + usage(); + } + + + memset(&stream, 0, sizeof(stream)); + stream.file = argv[0]; + stream.fd = eopen(stream.file, O_RDWR); + if (!headless) + einit_stream(&stream); + + + if (argc < 2 || !strcmp(argv[1], "auto")) + frames_auto = 1; + else + stream.frames = etozu_arg("the frame count", argv[1], 0, SIZE_MAX); + + if (argc < 4); + else if (strcmp(argv[2], "same")) + stream.width = etozu_arg("the width", argv[2], 1, SIZE_MAX); + else if (headless) + eprintf("cannot use both 'same' and -h\n"); + + if (argc < 4); + else if (strcmp(argv[3], "same")) + stream.height = etozu_arg("the height", argv[3], 1, SIZE_MAX); + else if (headless) + eprintf("cannot use both 'same' and -h\n"); + + if (argc < 5); + else if (strcmp(argv[4], "same")) { + if (strlen(argv[4]) >= sizeof(stream.pixfmt)) + eprintf("choosen pixel format is unsupported\n"); + strcpy(stream.pixfmt, argv[5]); + if (set_pixel_size(&stream)) + eprintf("choosen pixel format is unsupported\n"); + } else if (headless) { + eprintf("cannot use both 'same' and -h\n"); + } else if (argc > 1) { + usage(); + } + + + rewrite(&stream, frames_auto); + close(stream.fd); + return 0; +} diff --git a/src/blind-set-alpha.c b/src/blind-set-alpha.c new file mode 100644 index 0000000..2e80154 --- /dev/null +++ b/src/blind-set-alpha.c @@ -0,0 +1,69 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include + +USAGE("[-i] alpha-stream") + +static void +process_xyza(struct stream *colour, struct stream *alpha, size_t n) +{ + size_t i; + double a; + for (i = 0; i < n; i += colour->pixel_size) { + a = ((double *)(alpha->buf + i))[1]; + a *= ((double *)(alpha->buf + i))[3]; + ((double *)(colour->buf + i))[3] *= a; + } +} + +static void +process_xyza_i(struct stream *colour, struct stream *alpha, size_t n) +{ + size_t i; + double a; + for (i = 0; i < n; i += colour->pixel_size) { + a = 1 - ((double *)(alpha->buf + i))[1]; + a *= ((double *)(alpha->buf + i))[3]; + ((double *)(colour->buf + i))[3] *= a; + } +} + +int +main(int argc, char *argv[]) +{ + int invert = 0; + struct stream colour, alpha; + void (*process)(struct stream *colour, struct stream *alpha, size_t n) = NULL; + + ARGBEGIN { + case 'i': + invert = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 1) + usage(); + + colour.file = ""; + colour.fd = STDIN_FILENO; + einit_stream(&colour); + + alpha.file = argv[0]; + alpha.fd = eopen(alpha.file, O_RDONLY); + einit_stream(&alpha); + + if (!strcmp(colour.pixfmt, "xyza")) + process = invert ? process_xyza_i : process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); + + process_two_streams(&colour, &alpha, STDOUT_FILENO, "", process); + return 0; +} diff --git a/src/blind-set-luma.c b/src/blind-set-luma.c new file mode 100644 index 0000000..4500645 --- /dev/null +++ b/src/blind-set-luma.c @@ -0,0 +1,47 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include + +USAGE("luma-stream") + +static void +process_xyza(struct stream *colour, struct stream *luma, size_t n) +{ + size_t i; + double a; + for (i = 0; i < n; i += colour->pixel_size) { + a = ((double *)(luma->buf + i))[1]; + a *= ((double *)(luma->buf + i))[3]; + ((double *)(colour->buf + i))[1] *= a; + } +} + +int +main(int argc, char *argv[]) +{ + struct stream colour, luma; + void (*process)(struct stream *colour, struct stream *luma, size_t n); + + ENOFLAGS(argc != 1); + + colour.file = ""; + colour.fd = STDIN_FILENO; + einit_stream(&colour); + + luma.file = argv[0]; + luma.fd = eopen(luma.file, O_RDONLY); + einit_stream(&luma); + + if (!strcmp(colour.pixfmt, "xyza")) + process = process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); + + process_two_streams(&colour, &luma, STDOUT_FILENO, "", process); + return 0; +} diff --git a/src/blind-set-saturation.c b/src/blind-set-saturation.c new file mode 100644 index 0000000..1d3ed83 --- /dev/null +++ b/src/blind-set-saturation.c @@ -0,0 +1,79 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include + +USAGE("[-w] saturation-stream") + +static void +process_xyza(struct stream *colour, struct stream *satur, size_t n) +{ + size_t i; + double s, *x, *z, X, Z; + X = D65_XYY_X / D65_XYY_Y; + Z = 1 / D65_XYY_Y - 1 - X; + for (i = 0; i < n; i += colour->pixel_size) { + s = ((double *)(satur->buf + i))[1]; + s *= ((double *)(satur->buf + i))[3]; + x = ((double *)(colour->buf + i)) + 0; + z = ((double *)(colour->buf + i)) + 2; + *x = (*x - X) * s + X; + *z = (*z - Z) * s + Z; + } +} + +static void +process_xyza_w(struct stream *colour, struct stream *satur, size_t n) +{ + size_t i; + double s, *x, *z, X, Z; + for (i = 0; i < n; i += colour->pixel_size) { + X = ((double *)(satur->buf + i))[0]; + Z = ((double *)(satur->buf + i))[2]; + s = ((double *)(satur->buf + i))[1]; + s *= ((double *)(satur->buf + i))[3]; + x = ((double *)(colour->buf + i)) + 0; + z = ((double *)(colour->buf + i)) + 2; + *x = (*x - X) * s + X; + *z = (*z - Z) * s + Z; + } +} + +int +main(int argc, char *argv[]) +{ + struct stream colour, satur; + int whitepoint = 0; + void (*process)(struct stream *colour, struct stream *satur, size_t n) = NULL; + + ARGBEGIN { + case 'w': + whitepoint = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 1) + usage(); + + colour.file = ""; + colour.fd = STDIN_FILENO; + einit_stream(&colour); + + satur.file = argv[0]; + satur.fd = eopen(satur.file, O_RDONLY); + einit_stream(&satur); + + if (!strcmp(colour.pixfmt, "xyza")) + process = whitepoint ? process_xyza_w : process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); + + process_two_streams(&colour, &satur, STDOUT_FILENO, "", process); + return 0; +} diff --git a/src/blind-single-colour.c b/src/blind-single-colour.c new file mode 100644 index 0000000..254ea2a --- /dev/null +++ b/src/blind-single-colour.c @@ -0,0 +1,88 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include + +USAGE("[-f frames | -f 'inf'] -w width -h height (X Y Z | Y) [alpha]") + +typedef double pixel_t[4]; + +int +main(int argc, char *argv[]) +{ + struct stream stream; + double X, Y, Z, alpha = 1; + size_t x, y, n; + pixel_t buf[1024]; + ssize_t r; + int inf = 0; + char *arg; + + stream.width = 0; + stream.height = 0; + stream.frames = 1; + + ARGBEGIN { + case 'f': + arg = EARG(); + if (!strcmp(arg, "inf")) + inf = 1, stream.frames = 0; + else + stream.frames = etozu_flag('f', arg, 1, SIZE_MAX); + break; + case 'w': + stream.width = etozu_flag('w', EARG(), 1, SIZE_MAX); + break; + case 'h': + stream.height = etozu_flag('h', EARG(), 1, SIZE_MAX); + break; + default: + usage(); + } ARGEND; + + if (!stream.width || !stream.height || !argc || argc > 4) + usage(); + + if (argc < 3) { + X = D65_XYY_X / D65_XYY_Y; + Z = 1 / D65_XYY_Y - 1 - X; + Y = etolf_arg("the Y value", argv[1]); + } else { + X = etolf_arg("the X value", argv[0]); + Y = etolf_arg("the Y value", argv[1]); + Z = etolf_arg("the Z value", argv[2]); + } + if (~argc & 1) + alpha = etolf_arg("the alpha value", argv[argc - 1]); + + if (inf) + einf_check_fd(STDOUT_FILENO, ""); + + strcpy(stream.pixfmt, "xyza"); + fprint_stream_head(stdout, &stream); + efflush(stdout, ""); + + for (x = 0; x < ELEMENTSOF(buf); x++) { + buf[x][0] = X; + buf[x][1] = Y; + buf[x][2] = Z; + buf[x][3] = alpha; + } + while (inf || stream.frames--) { + for (y = stream.height; y--;) { + for (x = stream.width; x;) { + x -= n = ELEMENTSOF(buf) < x ? ELEMENTSOF(buf) : x; + for (n *= sizeof(*buf); n; n -= (size_t)r) { + r = write(STDOUT_FILENO, buf, n); + if (r < 0) + eprintf("write :"); + } + } + } + } + + return 0; +} diff --git a/src/blind-split.c b/src/blind-split.c new file mode 100644 index 0000000..ff6ce38 --- /dev/null +++ b/src/blind-split.c @@ -0,0 +1,72 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include + +USAGE("(file (end-point | 'end')) ...") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + size_t *ends, i, parts, ptr, end, frame_size, n; + FILE *fp; + int fd; + + ENOFLAGS(argc < 2 || argc % 2); + + stream.file = ""; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); + frame_size = stream.width * stream.height * stream.pixel_size; + if (stream.frames > SSIZE_MAX / frame_size) + eprintf("%s: video is too large\n", stream.file); + + parts = (size_t)argc / 2; + ends = alloca(parts * sizeof(*ends)); + + for (i = 0; i < parts; i++) { + if (!strcmp(argv[i * 2 + 1], "end")) + ends[i] = stream.frames; + else if (tozu(argv[i * 2 + 1], 0, SIZE_MAX, ends + i)) + eprintf("the end point must be an integer in [0, %zu]\n", SIZE_MAX); + if (i && ends[i] <= ends[i - 1]) + eprintf("the end points must be in strictly ascending order\n"); + if (ends[i] > stream.frames) + eprintf("frame %zu is beyond the end of the video\n", ends[i]); + } + + ptr = 0; + for (i = 0; i < parts; i++) { + fd = eopen(argv[i * 2], O_WRONLY | O_CREAT | O_TRUNC, 0666); + fp = fdopen(fd, "wb"); + if (!fp) + eprintf("fdopen %s:", argv[i * 2]); + + stream.frames = ends[i] - (i ? ends[i - 1] : 0); + fprint_stream_head(fp, &stream); + efflush(fp, argv[i * 2]); + + for (end = ends[i] * frame_size; ptr < end; ptr += n) { + if (stream.ptr == sizeof(stream.buf)) + n = stream.ptr < end - ptr ? stream.ptr : end - ptr; + else if (!(n = eread_stream(&stream, end - ptr))) + eprintf("%s: file is shorter than expected\n", stream.file); + ewriteall(STDOUT_FILENO, stream.buf, n, ""); + memmove(stream.buf, stream.buf + n, stream.ptr -= n); + } + + if (fclose(fp)) + eprintf("%s:", argv[i * 2]); + close(fd); + } + + return 0; +} diff --git a/src/blind-stack.c b/src/blind-stack.c new file mode 100644 index 0000000..a03fd91 --- /dev/null +++ b/src/blind-stack.c @@ -0,0 +1,80 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include + +USAGE("[-b] bottom-stream ... top-stream") + +#define PROCESS_LINEAR_3CH_ALPHA(TYPE, BLEND)\ + do {\ + TYPE x1, y1, z1, a1;\ + TYPE x2, y2, z2, a2;\ + size_t i, j;\ + for (i = 0; i < n; i += streams->pixel_size) {\ + x1 = ((TYPE *)(streams[0].buf + i))[0];\ + y1 = ((TYPE *)(streams[0].buf + i))[1];\ + z1 = ((TYPE *)(streams[0].buf + i))[2];\ + a1 = ((TYPE *)(streams[0].buf + i))[3];\ + for (j = 1; j < n_streams; j++) {\ + x2 = ((TYPE *)(streams[j].buf + i))[0];\ + y2 = ((TYPE *)(streams[j].buf + i))[1];\ + z2 = ((TYPE *)(streams[j].buf + i))[2];\ + a2 = ((TYPE *)(streams[j].buf + i))[3];\ + if (BLEND)\ + a2 /= j + 1;\ + x1 = x1 * a1 * (1 - a2) + x2 * a2;\ + y1 = y1 * a1 * (1 - a2) + y2 * a2;\ + z1 = z1 * a1 * (1 - a2) + z2 * a2;\ + a1 = a1 * (1 - a2) + a2;\ + }\ + ((TYPE *)(streams[0].buf + i))[0] = x1;\ + ((TYPE *)(streams[0].buf + i))[1] = y1;\ + ((TYPE *)(streams[0].buf + i))[2] = z1;\ + ((TYPE *)(streams[0].buf + i))[3] = a1;\ + }\ + } while (0) + +static void process_xyza (struct stream *streams, size_t n_streams, size_t n) { PROCESS_LINEAR_3CH_ALPHA(double, 0); } +static void process_xyza_b(struct stream *streams, size_t n_streams, size_t n) { PROCESS_LINEAR_3CH_ALPHA(double, 1); } + +int +main(int argc, char *argv[]) +{ + struct stream *streams; + size_t n_streams, i; + int blend = 0; + void (*process)(struct stream *streams, size_t n_streams, size_t n) = NULL; + + ARGBEGIN { + case 'b': + blend = 1; + break; + default: + usage(); + } ARGEND; + + if (argc < 2) + usage(); + + n_streams = (size_t)argc; + streams = ecalloc(n_streams, sizeof(*streams)); + + for (i = 0; i < n_streams; i++) { + streams[i].file = argv[i]; + streams[i].fd = eopen(streams[i].file, O_RDONLY); + } + + if (!strcmp(streams->pixfmt, "xyza")) + process = blend ? process_xyza_b : process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", streams->pixfmt); + + process_multiple_streams(streams, n_streams, STDOUT_FILENO, "", process); + + free(streams); + return 0; +} diff --git a/src/blind-to-image.c b/src/blind-to-image.c new file mode 100644 index 0000000..4b3d20c --- /dev/null +++ b/src/blind-to-image.c @@ -0,0 +1,150 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include + +USAGE("[-d depth | -f]") + +static int luma_warning_triggered = 0; +static int gamut_warning_triggered = 0; +static int alpha_warning_triggered = 0; + +static void +write_pixel(double R, double G, double B, double A, int bytes, unsigned long long int max) +{ + unsigned long long int colours[4]; + unsigned char buf[4 * 8]; + int i, j, k, bm = bytes - 1; + + if (R < 0 || G < 0 || B < 0 || R > 1 || G > 1 || B > 1) { + if (gamut_warning_triggered) { + gamut_warning_triggered = 1; + weprintf("warning: out-of-gamut colour detected\n"); + } + ; /* TODO gamut */ + R = R < 0 ? 0 : R > 1 ? 1 : R; + G = G < 0 ? 0 : G > 1 ? 1 : G; + B = B < 0 ? 0 : B > 1 ? 1 : B; + } + + if (A < 0 || A > 1) { + if (alpha_warning_triggered) { + alpha_warning_triggered = 1; + weprintf("warning: alpha values truncated\n"); + } + A = A < 0 ? 0 : 1; + } + + colours[0] = srgb_encode(R) * max + 0.5; + colours[1] = srgb_encode(G) * max + 0.5; + colours[2] = srgb_encode(B) * max + 0.5; + colours[3] = A * max + 0.5; + + for (i = k = 0; i < 4; i++) { + for (j = 0; j < bytes; j++, k++) { + buf[k + bm - j] = (unsigned char)(colours[j]); + colours[j] >>= 8; + } + } + + ewriteall(STDOUT_FILENO, buf, (size_t)bytes * 4, ""); +} + +static void +process_xyza(struct stream *stream, size_t n, int bytes, unsigned long long int max) +{ + size_t i; + double X, Y, Z, A, R, G, B; + for (i = 0; i < n; i += stream->pixel_size) { + X = ((double *)(stream->buf + i))[0]; + Y = ((double *)(stream->buf + i))[1]; + Z = ((double *)(stream->buf + i))[2]; + A = ((double *)(stream->buf + i))[3]; + + if (Y < 0 || Y > 1) { + if (luma_warning_triggered) { + luma_warning_triggered = 1; + weprintf("warning: %s colour detected\n", + Y < 0 ? "subblack" : "superwhite"); + } + } + + srgb_to_ciexyz(X, Y, Z, &R, &G, &B); + write_pixel(R, G, B, A, bytes, max); + } +} + +int +main(int argc, char *argv[]) +{ + struct stream stream; + int depth = 16, bytes, farbfeld = 0; + unsigned long long int max; + size_t n; + void (*process)(struct stream *stream, size_t n, int bytes, unsigned long long int max); + + ARGBEGIN { + case 'd': + depth = etoi_flag('d', EARG(), 1, 64); + break; + case 'f': + farbfeld = 1; + break; + default: + usage(); + } ARGEND; + + if (argc || (farbfeld && depth != 16)) + usage(); + + stream.fd = STDIN_FILENO; + stream.file = ""; + einit_stream(&stream); + + max = 1ULL << (depth - 1); + max |= max - 1; + for (bytes = 1; bytes * 8 < depth; bytes++); + + if (!strcmp(stream.pixfmt, "xyza")) + process = process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); + + if (farbfeld) { + uint32_t width = stream.width, height = stream.height; + if (stream.width > UINT32_MAX) + eprintf("%s: frame is too wide\n", stream.file); + if (stream.height > UINT32_MAX) + eprintf("%s: frame is too tall\n", stream.file); + printf("farbfeld"); + memmove(stream.buf + 8, stream.buf, stream.ptr); + stream.ptr += 8; + width = htonl(width); + height = htonl(height); + memcpy(stream.buf + 0, &width, 4); + memcpy(stream.buf + 4, &height, 4); + } else { + printf("P7\n" + "WIDTH %zu\n" + "HEIGHT %zu\n" + "DEPTH 4\n" /* Depth actually means channels */ + "MAXVAL %llu\n" + "TUPLTYPE RGB_ALPHA\n" + "ENDHDR\n", stream.width, stream.height, max); + } + efflush(stdout, ""); + + do { + n = stream.ptr - (stream.ptr % stream.pixel_size); + process(&stream, n, bytes, max); + memmove(stream.buf, stream.buf + n, stream.ptr -= n); + } while (eread_stream(&stream, SIZE_MAX)); + + return 0; +} diff --git a/src/blind-to-text.c b/src/blind-to-text.c new file mode 100644 index 0000000..73bf981 --- /dev/null +++ b/src/blind-to-text.c @@ -0,0 +1,51 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include + +USAGE("") + +static void +process_xyza(struct stream *stream, size_t n) +{ + size_t i; + for (i = 0; i < n; i += stream->pixel_size) + printf("%lf %lf %lf %lf\n", + ((double *)(stream->buf + i))[0], + ((double *)(stream->buf + i))[1], + ((double *)(stream->buf + i))[2], + ((double *)(stream->buf + i))[3]); +} + +int +main(int argc, char *argv[]) +{ + struct stream stream; + size_t n; + void (*process)(struct stream *stream, size_t n) = NULL; + + ENOFLAGS(argc); + + stream.file = ""; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + + if (!strcmp(stream.pixfmt, "xyza")) + process = process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); + + printf("%zu %zu %zu %s", stream.frames, stream.width, stream.height, stream.pixfmt); + + while ((n = eread_stream(&stream, SIZE_MAX))) { + n -= n % stream.pixel_size; + process(&stream, n); + memmove(stream.buf, stream.buf + n, stream.ptr -= n); + } + + efshut(stdout, ""); + return 0; +} diff --git a/src/blind-to-video.c b/src/blind-to-video.c new file mode 100644 index 0000000..ac4707e --- /dev/null +++ b/src/blind-to-video.c @@ -0,0 +1,146 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#if defined(HAVE_PRCTL) +# include +#endif +#include +#include +#include +#include +#include +#include + +USAGE("[-d] frame-rate ffmpeg-arguments ...") + +static int draft = 0; + +static void +process_xyza(char *buf, size_t n, int fd, const char *fname) +{ + double *pixel, r, g, b; + uint16_t *pixels, *end; + uint16_t pixbuf[1024]; + long int a, y, u, v; + size_t ptr; + pixels = pixbuf; + end = pixbuf + ELEMENTSOF(pixbuf); + if (draft) { + for (ptr = 0; ptr < n; ptr += sizeof(pixel)) { + pixel = (double *)(buf + ptr); + a = (long int)(pixel[3] * 0xFFFFL); + ciexyz_to_scaled_yuv(pixel[0], pixel[1], pixel[2], &r, &g, &b); + y = (long int)r + 16 * 256; + u = (long int)g + 128 * 256; + v = (long int)b + 128 * 256; + *pixels++ = htons((uint16_t)(a < 0 ? 0 : a > 0xFFFFL ? 0xFFFFL : a)); + *pixels++ = htons((uint16_t)(y < 0 ? 0 : y > 0xFFFFL ? 0xFFFFL : y)); + *pixels++ = htons((uint16_t)(u < 0 ? 0 : u > 0xFFFFL ? 0xFFFFL : u)); + *pixels++ = htons((uint16_t)(v < 0 ? 0 : v > 0xFFFFL ? 0xFFFFL : v)); + if (pixels == end) + ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), fname); + } + } else { + for (ptr = 0; ptr < n; ptr += sizeof(pixel)) { + pixel = (double *)(buf + ptr); + a = (long int)(pixel[3] * 0xFFFFL); + ciexyz_to_srgb(pixel[0], pixel[1], pixel[2], &r, &g, &b); + r = srgb_encode(r); + g = srgb_encode(g); + b = srgb_encode(b); + srgb_to_yuv(r, g, b, pixel + 0, pixel + 1, pixel + 2); + y = (long int)(pixel[0] * 0xFFFFL); + u = (long int)(pixel[1] * 0xFFFFL); + v = (long int)(pixel[2] * 0xFFFFL); + y += 16 * 256; + u += 128 * 256; + v += 128 * 256; + *pixels++ = htons((uint16_t)(a < 0 ? 0 : a > 0xFFFFL ? 0xFFFFL : a)); + *pixels++ = htons((uint16_t)(y < 0 ? 0 : y > 0xFFFFL ? 0xFFFFL : y)); + *pixels++ = htons((uint16_t)(u < 0 ? 0 : u > 0xFFFFL ? 0xFFFFL : u)); + *pixels++ = htons((uint16_t)(v < 0 ? 0 : v > 0xFFFFL ? 0xFFFFL : v)); + if (pixels == end) + ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), fname); + } + } + if (pixels != pixbuf) + ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), fname); +} + +int +main(int argc, char *argv[]) +{ + struct stream stream; + char geometry[2 * 3 * sizeof(size_t) + 2]; + char *frame_rate; + const char **cmd; + size_t n = 0; + int status, pipe_rw[2]; + pid_t pid; + void (*process)(char *buf, size_t n, int fd, const char *fname) = NULL; + + ARGBEGIN { + case 'd': + draft = 1; + break; + default: + usage(); + } ARGEND; + + if (argc < 2) + usage(); + + frame_rate = *argv++, argc--; + cmd = ecalloc((size_t)argc + 12, sizeof(*cmd)); + cmd[n++] = "ffmpeg"; + cmd[n++] = "-f", cmd[n++] = "rawvideo"; + cmd[n++] = "-pix_fmt", cmd[n++] = "ayuv64le"; + cmd[n++] = "-r", cmd[n++] = frame_rate; + cmd[n++] = "-s:v", cmd[n++] = geometry; + cmd[n++] = "-i", cmd[n++] = "-"; + memcpy(cmd + n, argv, (size_t)argc * sizeof(*cmd)); + + stream.file = ""; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + + sprintf(geometry, "%zux%zu", stream.width, stream.height); + + if (!strcmp(stream.pixfmt, "xyza")) + process = process_xyza; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); + + if (pipe(pipe_rw)) + eprintf("pipe:"); + + pid = fork(); + if (pid < 0) + eprintf("fork:"); + + if (!pid) { +#if defined(HAVE_PRCTL) && defined(PR_SET_PDEATHSIG) + prctl(PR_SET_PDEATHSIG, SIGKILL); +#endif + close(pipe_rw[1]); + if (dup2(pipe_rw[0], STDIN_FILENO) == -1) + eprintf("dup2:"); + close(pipe_rw[0]); + eprintf("exec ffmpeg:"); + } + + close(pipe_rw[0]); + while (!eread_stream(&stream, SIZE_MAX)) { + n = stream.ptr - (stream.ptr % stream.pixel_size); + process(stream.buf, n, pipe_rw[1], ""); + memmove(stream.buf, stream.buf + n, stream.ptr -= n); + } + close(pipe_rw[1]); + + if (waitpid(pid, &status, 0) == -1) + eprintf("waitpid:"); + + return !!status; +} diff --git a/src/blind-transpose.c b/src/blind-transpose.c new file mode 100644 index 0000000..0c32d81 --- /dev/null +++ b/src/blind-transpose.c @@ -0,0 +1,45 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include + +USAGE("") + +int +main(int argc, char *argv[]) +{ + struct stream stream; + char *buf, *image; + size_t n, imgw, imgh, x, y, i, b; + + ENOFLAGS(argc); + + stream.file = ""; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + fprint_stream_head(stdout, &stream); + efflush(stdout, ""); + + echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, ""); + n = stream.width * stream.height * stream.pixel_size; + buf = emalloc(n); + image = emalloc(n); + + imgw = stream.width * (imgh = stream.height * stream.pixel_size); + memcpy(buf, stream.buf, stream.ptr); + while (eread_frame(&stream, buf, n)) { + for (b = y = 0; y < imgh; y += stream.pixel_size) + for (x = 0; x < imgw; x += imgh) + for (i = 0; i < stream.pixel_size; i++) + image[x + y + i] = buf[b++]; + ewriteall(STDOUT_FILENO, image, n, ""); + } + + free(buf); + free(image); + return 0; +} diff --git a/src/blind-write-head.c b/src/blind-write-head.c new file mode 100644 index 0000000..9e7c4a3 --- /dev/null +++ b/src/blind-write-head.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "util.h" + +USAGE("parameters ...") + +int +main(int argc, char *argv[]) +{ + ENOFLAGS(!argc); + + printf("%s", *argv++); + while (*argv) + printf(" %s", *argv++); + printf("\n%cuivf", 0); + + efshut(stdout, ""); + return 0; +} diff --git a/src/vu-arithm.c b/src/vu-arithm.c deleted file mode 100644 index ce85287..0000000 --- a/src/vu-arithm.c +++ /dev/null @@ -1,80 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include -#include - -USAGE("right-hand-stream") - -/* Because the syntax for a function returning a function pointer is disgusting. */ -typedef void (*process_func)(struct stream *left, struct stream *right, size_t n); - -#define LIST_OPERATORS\ - X(add, *lh += rh)\ - X(sub, *lh -= rh)\ - X(mul, *lh *= rh)\ - X(div, *lh /= rh)\ - X(exp, *lh = pow(*lh, rh))\ - X(log, *lh = log(*lh) / log(rh))\ - X(min, *lh = *lh < rh ? *lh : rh)\ - X(max, *lh = *lh > rh ? *lh : rh) - -#define X(NAME, ALGO)\ - static void\ - process_lf_##NAME(struct stream *left, struct stream *right, size_t n)\ - {\ - size_t i;\ - double *lh, rh;\ - for (i = 0; i < n; i += 4 * sizeof(double)) {\ - lh = ((double *)(left->buf + i)) + 0, rh = ((double *)(right->buf + i))[0];\ - ALGO;\ - lh = ((double *)(left->buf + i)) + 1, rh = ((double *)(right->buf + i))[1];\ - ALGO;\ - lh = ((double *)(left->buf + i)) + 2, rh = ((double *)(right->buf + i))[2];\ - ALGO;\ - lh = ((double *)(left->buf + i)) + 3, rh = ((double *)(right->buf + i))[3];\ - ALGO;\ - }\ - } -LIST_OPERATORS -#undef X - -static process_func -get_lf_process(const char *operation) -{ -#define X(NAME, ALGO)\ - if (!strcmp(operation, #NAME)) return process_lf_##NAME; -LIST_OPERATORS -#undef X - eprintf("algorithm not recognised: %s\n", operation); - return NULL; -} - -int -main(int argc, char *argv[]) -{ - struct stream left, right; - process_func process = NULL; - - ENOFLAGS(argc != 1); - - left.file = ""; - left.fd = STDIN_FILENO; - einit_stream(&left); - - right.file = argv[1]; - right.fd = eopen(right.file, O_RDONLY); - einit_stream(&right); - - if (!strcmp(left.pixfmt, "xyza")) - process = get_lf_process(argv[0]); - else - eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt); - - process_two_streams(&left, &right, STDOUT_FILENO, "", process); - return 0; -} diff --git a/src/vu-colour-srgb.c b/src/vu-colour-srgb.c deleted file mode 100644 index 53fb784..0000000 --- a/src/vu-colour-srgb.c +++ /dev/null @@ -1,43 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "util.h" - -USAGE("[-d depth] [-l] red green blue") - -int -main(int argc, char *argv[]) -{ - unsigned long long int max; - double red, green, blue, X, Y, Z; - int depth = 8, linear = 0; - - ARGBEGIN { - case 'd': - depth = etoi_flag('d', EARG(), 1, 64); - break; - case 'l': - linear = 1; - break; - default: - usage(); - } ARGEND; - - if (argc != 3) - usage(); - - max = 1ULL << (depth - 1); - max |= max - 1; - red = etolf_arg("the red value", argv[0]) / max; - green = etolf_arg("the green value", argv[1]) / max; - blue = etolf_arg("the blue value", argv[2]) / max; - if (!linear) { - red = srgb_decode(red); - green = srgb_decode(green); - blue = srgb_decode(blue); - } - - srgb_to_ciexyz(red, green, blue, &X, &Y, &Z); - printf("%lf %lf %lf\n", X, Y, Z); - - efshut(stdout, ""); - return 0; -} diff --git a/src/vu-concat.c b/src/vu-concat.c deleted file mode 100644 index 95676e2..0000000 --- a/src/vu-concat.c +++ /dev/null @@ -1,114 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include -#include - -USAGE("[-o output-file] first-stream ... last-stream") - -static void -concat_to_stdout(int argc, char *argv[]) -{ - struct stream *streams; - size_t frames = 0; - int i; - - streams = emalloc((size_t)argc * sizeof(*streams)); - - for (i = 0; i < argc; i++) { - streams[i].file = argv[i]; - streams[i].fd = eopen(streams[i].file, O_RDONLY); - einit_stream(streams + i); - if (i) - echeck_compat(streams + i, streams); - if (streams[i].frames > SIZE_MAX - frames) - eprintf("resulting video is too long\n"); - frames += streams[i].frames; - } - - streams->frames = frames; - fprint_stream_head(stdout, streams); - efflush(stdout, ""); - - for (; argc--; streams++) { - for (; eread_stream(streams, SIZE_MAX); streams->ptr = 0) - ewriteall(STDOUT_FILENO, streams->buf, streams->ptr, ""); - close(streams->fd); - } - - free(streams); -} - -static void -concat_to_file(int argc, char *argv[], char *output_file) -{ - struct stream stream, refstream; - int first = 0; - int fd = eopen(output_file, O_RDWR | O_CREAT | O_TRUNC, 0666); - char head[STREAM_HEAD_MAX]; - ssize_t headlen, size = 0; - char *data; - - for (; argc--; argv++) { - stream.file = *argv; - stream.fd = eopen(stream.file, O_RDONLY); - einit_stream(&stream); - - if (first) { - stream = refstream; - } else { - if (refstream.frames > SIZE_MAX - stream.frames) - eprintf("resulting video is too long\n"); - refstream.frames += stream.frames; - echeck_compat(&stream, &refstream); - } - - for (; eread_stream(&stream, SIZE_MAX); stream.ptr = 0) { - ewriteall(STDOUT_FILENO, stream.buf, stream.ptr, ""); - size += stream.ptr; - } - close(stream.fd); - } - - sprintf(head, "%zu %zu %zu %s\n%cuivf%zn", - stream.frames, stream.width, stream.height, stream.pixfmt, 0, &headlen); - - ewriteall(fd, head, (size_t)headlen, output_file); - - data = mmap(0, size + (size_t)headlen, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (data == MAP_FAILED) - eprintf("mmap %s:", output_file); - memmove(data + headlen, data, size); - memcpy(data, head, (size_t)headlen); - munmap(data, size + (size_t)headlen); - - close(fd); -} - -int -main(int argc, char *argv[]) -{ - char *output_file = NULL; - - ARGBEGIN { - case 'o': - output_file = EARG(); - break; - default: - usage(); - } ARGEND; - - if (argc < 2) - usage(); - - if (output_file) - concat_to_file(argc, argv, output_file); - else - concat_to_stdout(argc, argv); - - return 0; -} diff --git a/src/vu-crop.c b/src/vu-crop.c deleted file mode 100644 index bf5a930..0000000 --- a/src/vu-crop.c +++ /dev/null @@ -1,86 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include - -USAGE("[-t] width height left top") - -int -main(int argc, char *argv[]) -{ - struct stream stream; - char *buf, *image, *p; - size_t width = 0, height = 0, left = 0, top = 0; - size_t off, yoff = 0, x, y, irown, orown, ptr, n, m; - int tile = 0; - - ARGBEGIN { - case 't': - tile = 1; - break; - default: - usage(); - } ARGEND; - - if (argc != 4) - usage(); - - width = etozu_arg("the width", argv[0], 1, SIZE_MAX); - height = etozu_arg("the height", argv[1], 1, SIZE_MAX); - left = etozu_arg("the left position", argv[2], 0, SIZE_MAX); - top = etozu_arg("the top position", argv[3], 0, SIZE_MAX); - - stream.file = ""; - stream.fd = STDIN_FILENO; - einit_stream(&stream); - if (left + width > stream.width || top + height > stream.height) - eprintf("crop area extends beyond original image\n"); - if (tile) { - fprint_stream_head(stdout, &stream); - } else { - x = stream.width, stream.width = width; - y = stream.height, stream.height = height; - fprint_stream_head(stdout, &stream); - stream.width = x; - stream.height = y; - } - efflush(stdout, ""); - - echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); - n = stream.height * (irown = stream.width * stream.pixel_size); - buf = emalloc(n); - orown = width * stream.pixel_size; - m = tile ? n : height * orown; - image = emalloc(m); - - left *= stream.pixel_size; - if (!tile) { - off = top * irown; - } else { - off = (orown - (left % orown)) % orown; - yoff = (height - (top % height)) % height; - } - - memcpy(buf, stream.buf, ptr = stream.ptr); - while (eread_frame(&stream, buf, n)) { - if (!tile) { - for (y = 0; y < height; y++) - memcpy(image + y * orown, buf + y * irown + off, orown); - } else { - for (ptr = y = 0; y < stream.height; y++) { - p = buf + ((y + yoff) % height) * irown + left; - for (x = 0; x < irown; x++, ptr++) - image[ptr++] = p[(x + off) % orown]; - } - } - ewriteall(STDOUT_FILENO, image, m, ""); - } - - free(buf); - free(image); - return 0; -} diff --git a/src/vu-cut.c b/src/vu-cut.c deleted file mode 100644 index e229cf1..0000000 --- a/src/vu-cut.c +++ /dev/null @@ -1,70 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include -#include - -USAGE("start-point (end-point | 'end') file") - -int -main(int argc, char *argv[]) -{ - struct stream stream; - size_t frame_size, start = 0, end = 0, ptr, max; - ssize_t r; - char buf[BUFSIZ]; - int to_end = 0; - - ENOFLAGS(argc != 3); - - if (!strcmp(argv[0], "end")) - eprintf("refusing to create video with zero frames\n"); - else - start = etozu_arg("the start point", argv[1], 0, SIZE_MAX); - - if (!strcmp(argv[1], "end")) - to_end = 1; - else - end = etozu_arg("the end point", argv[1], 0, SIZE_MAX); - - stream.file = argv[2]; - stream.fd = eopen(stream.file, O_RDONLY); - einit_stream(&stream); - if (to_end) - end = stream.frames; - else if (end > stream.frames) - eprintf("end point is after end of video\n"); - stream.frames = end - start; - fprint_stream_head(stdout, &stream); - efflush(stdout, ""); - echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); - frame_size = stream.width * stream.height * stream.pixel_size; - if (stream.frames > SSIZE_MAX / frame_size) - eprintf("%s: video is too large\n", stream.file); - - if (start >= end) - eprintf("%s\n", start > end ? - "start point is after end point" : - "refusing to create video with zero frames"); - end = end * frame_size + stream.headlen; - start = start * frame_size + stream.headlen; - - posix_fadvise(stream.fd, start, end - start, POSIX_FADV_SEQUENTIAL); - for (ptr = start; ptr < end; ptr += (size_t)r) { - max = end - ptr; - max = max < sizeof(buf) ? max : sizeof(buf); - r = pread(stream.fd, buf, max, ptr); - if (r < 0) - eprintf("pread %s:", stream.file); - if (r == 0) - eprintf("%s: file is shorter than expected\n", stream.file); - ewriteall(STDOUT_FILENO, buf, (size_t)r, ""); - } - - close(stream.fd); - return 0; -} diff --git a/src/vu-dissolve.c b/src/vu-dissolve.c deleted file mode 100644 index 83b9091..0000000 --- a/src/vu-dissolve.c +++ /dev/null @@ -1,70 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include - -USAGE("[-r]") - -static size_t fm; -static double fmd; - -static void -process_xyza(struct stream *stream, size_t n, size_t f) -{ - size_t i; - double a; - for (i = 0; i < n; i += stream->pixel_size) { - a = ((double *)(stream->buf + i))[3]; - a = a * (double)f / fmd; - ((double *)(stream->buf + i))[3] = a; - } -} - -static void -process_xyza_r(struct stream *stream, size_t n, size_t f) -{ - size_t i; - double a; - for (i = 0; i < n; i += stream->pixel_size) { - a = ((double *)(stream->buf + i))[3]; - a = a * (double)(fm - f) / fmd; - ((double *)(stream->buf + i))[3] = a; - } -} - -int -main(int argc, char *argv[]) -{ - struct stream stream; - int reverse = 0; - void (*process)(struct stream *stream, size_t n, size_t f) = NULL; - - ARGBEGIN { - case 'r': - reverse = 1; - break; - default: - usage(); - } ARGEND; - - if (argc) - usage(); - - stream.fd = STDIN_FILENO; - stream.file = ""; - einit_stream(&stream); - fprint_stream_head(stdout, &stream); - efflush(stdout, ""); - - if (!strcmp(stream.pixfmt, "xyza")) - process = reverse ? process_xyza_r : process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); - - fmd = fm = stream.frames - 1; - process_each_frame_segmented(&stream, STDOUT_FILENO, "", process); - - return 0; -} diff --git a/src/vu-extend.c b/src/vu-extend.c deleted file mode 100644 index 71be7f0..0000000 --- a/src/vu-extend.c +++ /dev/null @@ -1,103 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include - -USAGE("[-l left] [-r right] [-a above] [-b below] [-t]") - -int -main(int argc, char *argv[]) -{ - struct stream stream; - char *buf, *image; - size_t ptr, n, m, imgw, imgh, rown; - size_t xoff, yoff, h, x, y; - size_t left = 0, right = 0, top = 0, bottom = 0; - int tile = 0; - - ARGBEGIN { - case 'l': - left = etozu_flag('l', EARG(), 0, SIZE_MAX); - break; - case 'r': - right = etozu_flag('r', EARG(), 0, SIZE_MAX); - break; - case 'a': - top = etozu_flag('a', EARG(), 0, SIZE_MAX); - break; - case 'b': - bottom = etozu_flag('b', EARG(), 0, SIZE_MAX); - break; - case 't': - tile = 1; - break; - default: - usage(); - } ARGEND; - - if (argc) - usage(); - - stream.file = ""; - stream.fd = STDIN_FILENO; - einit_stream(&stream); - - echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); - n = stream.height * stream.width * stream.pixel_size; - buf = emalloc(n); - - if (stream.width > SIZE_MAX - left) - eprintf(": output video is too wide\n"); - imgw = stream.width + left; - if (imgw > SIZE_MAX - right) - eprintf(": output video is too wide\n"); - imgw += right; - if (stream.height > SIZE_MAX - top) - eprintf(": output video is too tall\n"); - imgh = stream.height + top; - if (imgh > SIZE_MAX - bottom) - eprintf(": output video is too tall\n"); - imgh += bottom; - echeck_frame_size(imgw, imgh, stream.pixel_size, "output", ""); - m = imgh * (imgw *= stream.pixel_size); - image = tile ? emalloc(m) : ecalloc(1, m); - - stream.width += left + right; - h = stream.height += top + bottom; - fprint_stream_head(stdout, &stream); - efflush(stdout, ""); - stream.width -= left + right; - stream.height -= top + bottom; - - left *= stream.pixel_size; - right *= stream.pixel_size; - rown = stream.width * stream.pixel_size; - - xoff = (rown - (left % rown)) % rown; - yoff = (stream.height - (top % stream.height)) % stream.height; - - memcpy(buf, stream.buf, ptr = stream.ptr); - while (eread_frame(&stream, buf, n)) { - if (!tile) { - for (y = 0; y < stream.height; y++) - memcpy(image + left + (y + top) * imgw, buf + y * rown, rown); - } else { - for (y = 0; y < stream.height; y++) - for (x = 0; x < imgw; x++) - image[x + (y + top) * imgw] = buf[((x + xoff) % rown) + y * rown]; - for (y = 0; y < top; y++) - memcpy(image + y * imgw, image + (((y + yoff) % stream.height) + top) * imgw, imgw); - for (y = top + stream.height; y < h; y++) - memcpy(image + y * imgw, image + (((y + yoff) % stream.height) + top) * imgw, imgw); - } - ewriteall(STDOUT_FILENO, image, m, ""); - } - - free(buf); - free(image); - return 0; -} diff --git a/src/vu-flip.c b/src/vu-flip.c deleted file mode 100644 index 98e0d58..0000000 --- a/src/vu-flip.c +++ /dev/null @@ -1,36 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include - -USAGE("") - -int -main(int argc, char *argv[]) -{ - struct stream stream; - size_t n, ptr, row_size; - char *buf; - - ENOFLAGS(argc); - - stream.file = ""; - stream.fd = STDIN_FILENO; - einit_stream(&stream); - fprint_stream_head(stdout, &stream); - efflush(stdout, ""); - - echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); - n = stream.height * (row_size = stream.width * stream.pixel_size); - buf = emalloc(n); - - memcpy(buf, stream.buf, stream.ptr); - while (eread_frame(&stream, buf, n)) - for (ptr = n; ptr;) - ewriteall(STDOUT_FILENO, buf + (ptr -= row_size), row_size, ""); - - free(buf); - return 0; -} diff --git a/src/vu-flop.c b/src/vu-flop.c deleted file mode 100644 index e98771d..0000000 --- a/src/vu-flop.c +++ /dev/null @@ -1,44 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include - -USAGE("") - -int -main(int argc, char *argv[]) -{ - struct stream stream; - char *buf, *image; - size_t i, j, n, m; - - ENOFLAGS(argc); - - stream.file = ""; - stream.fd = STDIN_FILENO; - einit_stream(&stream); - fprint_stream_head(stdout, &stream); - efflush(stdout, ""); - - if (stream.width > SIZE_MAX / stream.pixel_size) - eprintf(": video frame is too wide\n"); - n = stream.width * stream.pixel_size; - buf = emalloc(n); - image = emalloc(n); - - m = n - stream.pixel_size; - memcpy(buf, stream.buf, stream.ptr); - while (eread_row(&stream, buf, n)) { - for (i = 0; i < stream.pixel_size; i++) - for (j = 0; j < n; j += stream.pixel_size) - image[m - j + i] = buf[i + j]; - ewriteall(STDOUT_FILENO, image, n, ""); - } - - free(buf); - free(image); - return 0; -} diff --git a/src/vu-from-image.c b/src/vu-from-image.c deleted file mode 100644 index 9c2d047..0000000 --- a/src/vu-from-image.c +++ /dev/null @@ -1,273 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "util.h" - -#include -#include -#include -#include -#include - -USAGE("[-h] [-f | -p]") - -static char buf[BUFSIZ]; -static char width[3 * sizeof(size_t) + 1] = {0}; -static char height[3 * sizeof(size_t) + 1] = {0}; -static const char *conv_fail_msg = "convertion failed, if converting a farbfeld file, try -f"; -static size_t pixel_size; -static double value_max; -static double (*get_value)(char **bufp); -static void (*convert)(size_t n); -static int with_alpha = 1; -static int with_colour = 1; - -static double -get_value_u8(char** bufp) -{ - uint8_t value = *(uint8_t *)(*bufp); - *bufp += 1; - return value / value_max; -} - -static double -get_value_u16(char** bufp) -{ - uint16_t value = ntohs(*(uint16_t *)(*bufp)); - *bufp += 2; - return value / value_max; -} - -static double -get_value_u32(char** bufp) -{ - uint32_t value = ntohl(*(uint32_t *)(*bufp)); - *bufp += 4; - return value / value_max; -} - -static double -get_value_u64(char** bufp) -{ - uint64_t value; - value = (uint64_t)(buf[0]) << 56; - value |= (uint64_t)(buf[1]) << 48; - value |= (uint64_t)(buf[2]) << 40; - value |= (uint64_t)(buf[3]) << 32; - value |= (uint64_t)(buf[4]) << 24; - value |= (uint64_t)(buf[5]) << 16; - value |= (uint64_t)(buf[6]) << 8; - value |= (uint64_t)(buf[7]); - *bufp += 8; - return value / value_max; -} - -static void -from_srgb(size_t n) -{ - double red, green, blue, pixel[4]; - size_t ptr; - char *p; - for (ptr = 0; ptr + pixel_size <= n; ptr += pixel_size) { - p = buf + ptr; - red = srgb_decode(get_value(&p)); - green = with_colour ? srgb_decode(get_value(&p)) : red; - blue = with_colour ? srgb_decode(get_value(&p)) : red; - pixel[3] = with_alpha ? get_value(&p) : 1; - srgb_to_ciexyz(red, green, blue, pixel + 0, pixel + 1, pixel + 2); - ewriteall(STDOUT_FILENO, pixel, sizeof(pixel), ""); - } -} - -static size_t -farbfeld_head(int fd, const char *fname) -{ - if (ereadall(fd, buf, 16, fname) != 16) - eprintf("%s\n", conv_fail_msg); - if (memcmp(buf, "farbfeld", 8)) - eprintf("%s\n", conv_fail_msg); - sprintf(width, "%"PRIu32, ntohl(*(uint32_t *)(buf + 8))); - sprintf(height, "%"PRIu32, ntohl(*(uint32_t *)(buf + 12))); - pixel_size = 4 * sizeof(uint16_t); - value_max = UINT16_MAX; - get_value = get_value_u16; - convert = from_srgb; - return 0; -} - -static size_t -pam_head(int fd, const char *fname) -{ - size_t ptr; - char *p; - unsigned long long int maxval = UINT8_MAX; - for (ptr = 0;;) { - ptr += ereadall(fd, buf + ptr, (size_t)buf - ptr, fname); - for (;;) { - p = memchr(buf, '\n', ptr); - if (!p) { - if (ptr == sizeof(buf)) - eprintf("%s\n", conv_fail_msg); - break; - } - *p++ = '\0'; - if (strstr(buf, "WIDTH ") == buf) { - if (*width || !buf[6] || strlen(buf + 6) >= sizeof(width)) - eprintf("%s\n", conv_fail_msg); - strcpy(width, buf + 6); - } else if (strstr(buf, "HEIGHT ") == buf) { - if (*height || !buf[7] || strlen(buf + 7) >= sizeof(height)) - eprintf("%s\n", conv_fail_msg); - strcpy(height, buf + 7); - } else if (strstr(buf, "MAXVAL ") == buf) { - if (tollu(buf + 7, 0, UINT64_MAX, &maxval)) { - if (errno != ERANGE) - eprintf("%s\n", conv_fail_msg); - eprintf("image uses greater colour resolution than supported\n"); - } else if (!maxval) { - eprintf("%s\n", conv_fail_msg); - } - } else if (strstr(buf, "TUPLTYPE ") == buf) { - if (!strcmp(buf, "TUPLTYPE BLACKANDWHITE")) - maxval = 1, with_colour = 0, with_alpha = 0; - else if (!strcmp(buf, "TUPLTYPE BLACKANDWHITE_ALPHA")) - maxval = 1, with_colour = 0, with_alpha = 1; - else if (!strcmp(buf, "TUPLTYPE GRAYSCALE")) - with_colour = 0, with_alpha = 0; - else if (!strcmp(buf, "TUPLTYPE GRAYSCALE_ALPHA")) - with_colour = 0, with_alpha = 1; - else if (!strcmp(buf, "TUPLTYPE RGB")) - with_colour = 1, with_alpha = 0; - else if (!strcmp(buf, "TUPLTYPE RGB_ALPHA")) - with_colour = 1, with_alpha = 1; - else - eprintf("image uses an unsupported tuple type: %s\n", buf + sizeof("TUPLTYPE")); - } 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 (maxval < (size_t)UINT8_MAX) { - pixel_size = sizeof(uint8_t); - get_value = get_value_u8; - } else if (maxval < (size_t)UINT16_MAX) { - pixel_size = sizeof(uint16_t); - get_value = get_value_u16; - } else if (maxval < (size_t)UINT32_MAX) { - pixel_size = sizeof(uint32_t); - get_value = get_value_u32; - } else { - pixel_size = sizeof(uint64_t); - get_value = get_value_u64; - } - value_max = maxval; - pixel_size *= (with_colour ? 3 : 1) + with_alpha; - convert = from_srgb; - return ptr; -} - -int -main(int argc, char *argv[]) -{ - int status, pipe_rw[2], i, old_fd, forked = 0; - int headless = 0, farbfeld = 0, pam = 0; - pid_t pid = 0; - size_t off, n; - ssize_t r; - const char *file = ""; - const char *conv_fail_msg = "convertion failed, if converting a farbfeld file, try -f"; - - ARGBEGIN { - case 'f': - farbfeld = 1; - break; - case 'h': - headless = 1; - break; - case 'p': - pam = 1; - break; - default: - usage(); - } ARGEND; - - if (argc || (farbfeld && pam)) - usage(); - - if (farbfeld) - conv_fail_msg = "not a valid farbfeld file, try without -f"; - else if (pam) - conv_fail_msg = "not a valid RGBA portable arbitrary map file, try without -p"; - else - forked = 1; - - if (forked) { - file = ""; - pipe_rw[0] = STDIN_FILENO; - goto after_fork; - } - - 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) == -1) - 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]); -after_fork: - - if (farbfeld) - n = farbfeld_head(pipe_rw[0], file); - else - n = pam_head(pipe_rw[0], file); - - if (!*width || !*height) - eprintf("%s\n", conv_fail_msg); - - if (!headless) { - printf("1 %s %s xyza\n%cuivf", width, height, 0); - efflush(stdout, ""); - } - - for (;;) { - convert(n); - off = n - (n % pixel_size); - memmove(buf, buf + off, n -= off); - r = read(pipe_rw[0], buf + n, sizeof(buf) - n); - if (r < 0) - eprintf("read %s:", file); - if (r == 0) - break; - n += (size_t)r; - } - - if (!forked) - return 0; - close(pipe_rw[0]); - while (waitpid(pid, &status, 0) != pid); - return !!status; -} diff --git a/src/vu-from-text.c b/src/vu-from-text.c deleted file mode 100644 index 88cee62..0000000 --- a/src/vu-from-text.c +++ /dev/null @@ -1,71 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include - -USAGE("") - -static void -process_xyza(struct stream *stream) -{ - double buf[BUFSIZ / sizeof(double)]; - size_t i; - int r, done = 0; - - while (!done) { - for (i = 0; i < ELEMENTSOF(buf); i += (size_t)r) { - r = scanf("%lf", buf + i); - if (r == EOF) { - done = 1; - break; - } - } - ewriteall(STDOUT_FILENO, buf, i * sizeof(*buf), ""); - } -} - -int -main(int argc, char *argv[]) -{ - struct stream stream; - size_t size = 0; - char *line = NULL; - ssize_t len; - void (*process)(struct stream *stream) = NULL; - - ENOFLAGS(argc); - - len = getline(&line, &size, stdin); - if (len < 0) { - if (ferror(stdin)) - eprintf("getline :"); - else - eprintf(": no input\n"); - } - if (len && line[len - 1] == '\n') - line[--len] = '\n'; - if (len + 6 > sizeof(stream.buf)) - eprintf(": head is too long\n"); - stream.fd = -1; - stream.file = ""; - memcpy(stream.buf, line, (size_t)len); - memcpy(stream.buf + len, "\n\0uivf", 6); - stream.ptr = (size_t)len + 6; - free(line); - ewriteall(STDOUT_FILENO, stream.buf, stream.ptr, ""); - einit_stream(&stream); - - if (!strcmp(stream.pixfmt, "xyza")) - process = process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); - - process(&stream); - - efshut(stdin, ""); - return 0; -} diff --git a/src/vu-from-video.c b/src/vu-from-video.c deleted file mode 100644 index c780b55..0000000 --- a/src/vu-from-video.c +++ /dev/null @@ -1,285 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#if defined(HAVE_PRCTL) -# include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -USAGE("[-r frame-rate] [-w width -h height] [-d] input-file output-file") - -static int draft = 0; - -static void -read_metadata(FILE *fp, char *fname, size_t *width, size_t *height, size_t *frames) -{ - char *line = NULL; - size_t size = 0; - ssize_t len; - int have_width = !width, have_height = !height, have_frames = 0; - char *p; - - while ((len = getline(&line, &size, fp)) != -1) { - if (len && line[len - 1]) - line[--len] = '\0'; - p = strchr(line, '=') + 1; - if (width && strstr(line, "width=") == line) { - if (tozu(p, 1, SIZE_MAX, width)) - eprintf("invalid width: %s\n", p); - have_width = 1; - } else if (height && strstr(line, "height=") == line) { - if (tozu(p, 1, SIZE_MAX, height)) - eprintf("invalid height: %s\n", p); - have_height = 1; - } else if (strstr(line, "nb_read_frames=") == line) { - if (tozu(p, 0, SIZE_MAX, frames)) - eprintf("invalid frame count: %s\n", p); - have_frames = 1; - } - } - - if (ferror(fp)) - eprintf("getline %s:", fname); - free(line); - - if (have_width + have_height + have_frames < 3) - eprintf("could not get all required metadata\n"); -} - -static void -get_metadata(char *file, size_t *width, size_t *height, size_t *frames) -{ - FILE *fp; - int fd, pipe_rw[2]; - pid_t pid; - int status; - - if (pipe(pipe_rw)) - eprintf("pipe:"); - - pid = fork(); - if (pid == -1) - eprintf("fork:"); - - if (!pid) { -#if defined(HAVE_PRCTL) && defined(PR_SET_PDEATHSIG) - prctl(PR_SET_PDEATHSIG, SIGKILL); -#endif - fd = eopen(file, O_RDONLY); - if (dup2(fd, STDIN_FILENO) == -1) - eprintf("dup2:"); - close(fd); - close(pipe_rw[0]); - if (dup2(pipe_rw[1], STDOUT_FILENO) == -1) - eprintf("dup2:"); - close(pipe_rw[1]); - execlp("ffprobe", "ffprobe", "-v", "quiet", "-show_streams", - "-select_streams", "v", "-count_frames", "-", NULL); - eprintf("exec ffprobe:"); - } - - close(pipe_rw[1]); - fp = fdopen(pipe_rw[0], "rb"); - if (!fp) - eprintf("fdopen :"); - read_metadata(fp, file, width, height, frames); - fclose(fp); - close(pipe_rw[0]); - - if (waitpid(pid, &status, 0) == -1) - eprintf("waitpid:"); - if (status) - exit(1); -} - -static void -convert_segment(char *buf, size_t n, int fd, char *file) -{ - typedef double pixel_t[4]; - size_t i, ptr; - double y, u, v, max = (double)UINT16_MAX; - double r, g, b; - pixel_t pixels[1024]; - if (draft) { - for (ptr = i = 0; ptr < n; ptr += 8) { - pixels[i][3] = ntohs(((uint16_t *)(buf + ptr))[0]) / max; - y = (ntohs(((uint16_t *)(buf + ptr))[1]) - 16 * 256); - u = (ntohs(((uint16_t *)(buf + ptr))[2]) - 128 * 256); - v = (ntohs(((uint16_t *)(buf + ptr))[3]) - 128 * 256); - scaled_yuv_to_ciexyz(y, u, v, pixels[i] + 0, pixels[i] + 1, pixels[i] + 2); - if (++i == 1024) { - i = 0; - ewriteall(fd, pixels, sizeof(pixels), file); - } - } - } else { - for (ptr = i = 0; ptr < n; ptr += 8) { - pixels[i][3] = ntohs(((uint16_t *)(buf + ptr))[0]) / max; - y = (ntohs(((uint16_t *)(buf + ptr))[1]) - 16 * 256) / max; - u = (ntohs(((uint16_t *)(buf + ptr))[2]) - 128 * 256) / max; - v = (ntohs(((uint16_t *)(buf + ptr))[3]) - 128 * 256) / max; - yuv_to_srgb(y, u, v, &r, &g, &b); - r = srgb_decode(r); - g = srgb_decode(g); - b = srgb_decode(b); - srgb_to_ciexyz(r, g, b, pixels[i] + 0, pixels[i] + 1, pixels[i] + 2); - if (++i == 1024) { - i = 0; - ewriteall(fd, pixels, sizeof(pixels), file); - } - } - } - if (i) - ewriteall(fd, pixels, i * sizeof(*pixels), file); -} - -static void -convert(char *infile, int outfd, char *outfile, size_t width, size_t height, char *frame_rate) -{ - char geometry[2 * 3 * sizeof(size_t) + 2], *cmd[13], buf[BUFSIZ]; - int status, fd, pipe_rw[2]; - size_t i = 0, n, ptr; - ssize_t r; - pid_t pid; - - cmd[i++] = "ffmpeg"; - cmd[i++] = "-i", cmd[i++] = "-"; - cmd[i++] = "-f", cmd[i++] = "rawvideo"; - cmd[i++] = "-pix_fmt", cmd[i++] = "ayuv64le"; - if (width && height) { - sprintf(geometry, "%zux%zu", width, height); - cmd[i++] = "-s:v", cmd[i++] = geometry; - } - if (frame_rate) - cmd[i++] = "-r", cmd[i++] = frame_rate; - cmd[i++] = "-"; - cmd[i++] = NULL; - - if (pipe(pipe_rw)) - eprintf("pipe:"); - - pid = fork(); - if (pid == -1) - eprintf("fork:"); - - if (!pid) { -#if defined(HAVE_PRCTL) && defined(PR_SET_PDEATHSIG) - prctl(PR_SET_PDEATHSIG, SIGKILL); -#endif - fd = eopen(infile, O_RDONLY); - if (dup2(fd, STDIN_FILENO) == -1) - eprintf("dup2:"); - close(fd); - close(pipe_rw[0]); - if (dup2(pipe_rw[1], STDOUT_FILENO) == -1) - eprintf("dup2:"); - close(pipe_rw[1]); - execvp("ffmpeg", cmd); - eprintf("exec ffmpeg:"); - } - - close(pipe_rw[1]); - - for (ptr = 0;;) { - r = read(pipe_rw[0], buf + ptr, sizeof(buf) - ptr); - if (r < 0) - eprintf("read :"); - if (r == 0) - break; - ptr += (size_t)r; - n = ptr - (ptr % 8); - convert_segment(buf, n, outfd, outfile); - memmove(buf, buf + n, ptr -= n); - } - if (ptr) - eprintf(": incomplete frame\n"); - - close(pipe_rw[0]); - if (waitpid(pid, &status, 0) == -1) - eprintf("waitpid:"); - if (status) - exit(1); -} - -int -main(int argc, char *argv[]) -{ - size_t width = 0, height = 0, frames; - char head[STREAM_HEAD_MAX]; - char *frame_rate = NULL; - char *infile; - char *outfile; - char *data; - ssize_t headlen; - size_t length; - int outfd, status; - pid_t pid; - struct stat st; - - ARGBEGIN { - case 'd': - draft = 1; - break; - case 'r': - frame_rate = EARG(); - break; - case 'w': - width = etozu_flag('w', EARG(), 1, SIZE_MAX); - break; - case 'h': - height = etozu_flag('h', EARG(), 1, SIZE_MAX); - break; - default: - usage(); - } ARGEND; - - if (argc != 2 || !width != !height) - usage(); - - infile = argv[0]; - outfile = argv[1]; - - outfd = eopen(outfile, O_RDWR | O_CREAT | O_TRUNC, 0666); - - pid = fork(); - if (pid == -1) - eprintf("fork:"); - - if (!pid) { -#if defined(HAVE_PRCTL) && defined(PR_SET_PDEATHSIG) - prctl(PR_SET_PDEATHSIG, SIGKILL); -#endif - convert(infile, outfd, outfile, width, height, frame_rate); - exit(0); - } - - get_metadata(infile, width ? NULL : &width, height ? NULL : &height, &frames); - - if (waitpid(pid, &status, 0) == -1) - eprintf("waitpid:"); - if (status) - exit(1); - - if (fstat(outfd, &st)) - eprintf("fstat %s:", outfile); - length = (size_t)(st.st_size); - - sprintf(head, "%zu %zu %zu %s\n%cuivf%zn", frames, width, height, "xyza", 0, &headlen); - ewriteall(outfd, head, (size_t)headlen, outfile); - data = mmap(0, length + (size_t)headlen, PROT_READ | PROT_WRITE, MAP_PRIVATE, outfd, 0); - memmove(data + headlen, data, length); - memcpy(data, head, (size_t)headlen); - munmap(data, length + (size_t)headlen); - - close(outfd); - return 0; -} diff --git a/src/vu-gauss-blur.c b/src/vu-gauss-blur.c deleted file mode 100644 index b64391c..0000000 --- a/src/vu-gauss-blur.c +++ /dev/null @@ -1,189 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include -#include -#include - -USAGE("[-j jobs] [-ac] sd-stream") - -static int chroma = 0; -static int noalpha = 0; -static size_t jobs = 1; - -static void -process_xyza(char *restrict output, char *restrict cbuf, char *restrict sbuf, - struct stream *colour, struct stream *sigma, size_t n, size_t unused) -{ - typedef double pixel_t[4]; - - pixel_t *restrict clr = (pixel_t *)cbuf; - pixel_t *restrict sig = (pixel_t *)sbuf; - pixel_t *img = (pixel_t *)output; - pixel_t c, k; - double *p; - size_t x1, y1, i1, x2, y2, i2; - double dy, d, m, dblurred; - int i, blurred, blur[3] = {0, 0, 0}; - size_t start = 0, end = colour->height; - int is_master; - - /* premultiply alpha channel */ - if (!noalpha) { - for (y1 = i1 = 0; y1 < colour->height; y1++) { - for (x1 = 0; x1 < colour->width; x1++, i1++) { - clr[i1][0] *= clr[i1][3]; - clr[i1][1] *= clr[i1][3]; - clr[i1][2] *= clr[i1][3]; - } - } - } - - is_master = efork_jobs(&start, &end, jobs); - - /* blur */ - i1 = start * colour->width; - for (y1 = i1 = start; y1 < end; y1++) { - for (x1 = 0; x1 < colour->width; x1++, i1++) { - if (sig[i1][3] == 0) - goto no_blur; - if (!chroma) { - for (i = 0; i < 3; i++) { - k[i] = sig[i1][i] * sig[i1][3], c[i] = k[i] *= k[i] * 2, c[i] *= M_PI; - k[i] = 1 / k[i], c[i] = -1 / c[i]; - blur[i] = !sig[i1][1]; - } - } else { - k[1] = sig[i1][1] * sig[i1][3], c[1] = k[1] *= k[1] * 2, c[1] *= M_PI; - k[1] = 1 / -k[1], c[1] = 1 / c[1]; - blur[1] = !sig[i1][1]; - } - if (blur[0] + blur[1] + blur[2] == 0) - goto no_blur; - - p = img[i1]; - p[0] = p[1] = p[2] = 0; - p[3] = noalpha; - if (k[0] == k[1] && k[1] == k[2]) { - for (y2 = i2 = 0; y2 < colour->height; y2++) { - dy = (ssize_t)y1 - (ssize_t)y2; - dy *= dy; - for (x2 = 0; x2 < colour->width; x2++, i2++) { - d = (ssize_t)x1 - (ssize_t)x2; - d = d * d + dy; - m = c[i1] * exp(d * k[i1]); - for (i = noalpha ? 3 : 4; i--;) - p[i] += clr[i2][i] * m; - } - } - } else { - blurred = 0; - for (i = 0; i < n; i++) { - if (!blur[i]) { - p[i] = clr[i1][i]; - continue; - } - for (y2 = i2 = 0; y2 < colour->height; y2++) { - dy = (ssize_t)y1 - (ssize_t)y2; - dy *= dy; - if (!noalpha) { - for (x2 = 0; x2 < colour->width; x2++, i2++) { - d = (ssize_t)x1 - (ssize_t)x2; - d = d * d + dy; - m = c[i1] * exp(d * k[i1]); - p[i] += clr[i2][i] * m; - p[3] += clr[i2][3] * m; - } - } else { - for (x2 = 0; x2 < colour->width; x2++, i2++) { - d = (ssize_t)x1 - (ssize_t)x2; - d = d * d + dy; - m = c[i1] * exp(d * k[i1]); - p[i] += clr[i2][i] * m; - } - } - } - blurred += 1; - } - if (!noalpha) { - dblurred = blurred; - for (y2 = i2 = 0; y2 < colour->height; y2++) - for (x2 = 0; x2 < colour->width; x2++, i2++) - p[3] /= dblurred; - } - } - - continue; - no_blur: - img[i1][0] = clr[i1][0]; - img[i1][1] = clr[i1][1]; - img[i1][2] = clr[i1][2]; - img[i1][3] = clr[i1][3]; - } - } - - ejoin_jobs(is_master); - - /* unpremultiply alpha channel */ - if (!noalpha) { - for (y1 = i1 = 0; y1 < colour->height; y1++) { - for (x1 = 0; x1 < colour->width; x1++, i1++) { - if (!img[i1][3]) - continue; - img[i1][0] /= img[i1][3]; - img[i1][1] /= img[i1][3]; - img[i1][2] /= img[i1][3]; - } - } - } - - (void) unused; -} - -int -main(int argc, char *argv[]) -{ - struct stream colour, sigma; - void (*process)(char *restrict output, char *restrict cbuf, char *restrict sbuf, - struct stream *colour, struct stream *sigma, size_t cn, size_t sn); - - ARGBEGIN { - case 'a': - noalpha = 1; - break; - case 'c': - chroma = 1; - break; - case 'j': - jobs = etozu_flag('j', EARG(), 1, SHRT_MAX); - break; - default: - usage(); - } ARGEND; - - if (argc != 1) - usage(); - - colour.file = ""; - colour.fd = STDIN_FILENO; - einit_stream(&colour); - - sigma.file = argv[0]; - sigma.fd = eopen(sigma.file, O_RDONLY); - einit_stream(&sigma); - - if (!strcmp(colour.pixfmt, "xyza")) - process = process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); - - echeck_compat(&colour, &sigma); - - process_each_frame_two_streams(&colour, &sigma, STDOUT_FILENO, "", process); - - return 0; -} diff --git a/src/vu-invert-luma.c b/src/vu-invert-luma.c deleted file mode 100644 index aa3b260..0000000 --- a/src/vu-invert-luma.c +++ /dev/null @@ -1,73 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include - -USAGE("[-i] mask-stream") - -static void -process_xyza(struct stream *colour, struct stream *mask, size_t n) -{ - size_t i; - double w, y; - for (i = 0; i < n; i += colour->pixel_size) { - w = ((double *)(mask->buf + i))[1]; - w *= ((double *)(mask->buf + i))[3]; - y = ((double *)(colour->buf + i))[3]; - y = (1 - y) * w + y * (1 - w); - ((double *)(colour->buf + i))[3] = y; - } -} - -static void -process_xyza_i(struct stream *colour, struct stream *mask, size_t n) -{ - size_t i; - double w, y; - for (i = 0; i < n; i += colour->pixel_size) { - w = 1 - ((double *)(mask->buf + i))[1]; - w *= ((double *)(mask->buf + i))[3]; - y = ((double *)(colour->buf + i))[3]; - y = (1 - y) * w + y * (1 - w); - ((double *)(colour->buf + i))[3] = y; - } -} - -int -main(int argc, char *argv[]) -{ - int invert = 0; - struct stream colour, mask; - void (*process)(struct stream *colour, struct stream *mask, size_t n) = NULL; - - ARGBEGIN { - case 'i': - invert = 1; - break; - default: - usage(); - } ARGEND; - - if (argc != 1) - usage(); - - colour.file = ""; - colour.fd = STDIN_FILENO; - einit_stream(&colour); - - mask.file = argv[0]; - mask.fd = eopen(mask.file, O_RDONLY); - einit_stream(&mask); - - if (!strcmp(colour.pixfmt, "xyza")) - process = invert ? process_xyza_i : process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); - - process_two_streams(&colour, &mask, STDOUT_FILENO, "", process); - return 0; -} diff --git a/src/vu-next-frame.c b/src/vu-next-frame.c deleted file mode 100644 index 6a55790..0000000 --- a/src/vu-next-frame.c +++ /dev/null @@ -1,63 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include - -USAGE("width height pixel-format ...") - -int -main(int argc, char *argv[]) -{ - struct stream stream; - size_t n, w; - int i, anything = 0; - char *p; - - ENOFLAGS(argc < 3); - - stream.frames = 1; - stream.fd = STDIN_FILENO; - stream.file = ""; - stream.pixfmt[0] = '\0'; - - stream.width = entozu_arg(2, "the width", argv[0], 1, SIZE_MAX); - stream.height = entozu_arg(2, "the height", argv[1], 1, SIZE_MAX); - argv += 2, argc -= 2; - - n = (size_t)argc - 1; - for (i = 0; i < argc; i++) - n += strlen(argv[i]); - if (n < sizeof(stream.pixfmt)) { - p = stpcpy(stream.pixfmt, argv[0]); - for (i = 1; i < argc; i++) { - *p++ = ' '; - p = stpcpy(p, argv[i]); - } - } - - enset_pixel_size(2, &stream); - - fprint_stream_head(stdout, &stream); - enfflush(2, stdout, ""); - - w = stream.width * stream.pixel_size; - while (stream.height) { - stream.height--; - for (n = w; n; n -= stream.ptr) { - stream.ptr = 0; - if (!enread_stream(2, &stream, n)) - goto done; - anything = 1; - enwriteall(2, STDOUT_FILENO, stream.buf, stream.ptr, ""); - } - } -done: - - if (stream.height || n) - enprintf(2, "incomplete frame\n"); - - return !anything; -} diff --git a/src/vu-read-head.c b/src/vu-read-head.c deleted file mode 100644 index afb2fbc..0000000 --- a/src/vu-read-head.c +++ /dev/null @@ -1,63 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include - -USAGE("") - -int -main(int argc, char *argv[]) -{ - char buf[STREAM_HEAD_MAX]; - char magic[] = {'\0', 'u', 'i', 'v', 'f'}; - char b, *p; - size_t i, ptr; - ssize_t r; - - ENOFLAGS(argc); - - for (ptr = 0; ptr < sizeof(buf);) { - r = read(STDIN_FILENO, buf + ptr, 1); - if (r < 0) - eprintf("read :"); - if (r == 0) - goto bad_format; - if (buf[ptr++] == '\n') - break; - } - if (ptr == sizeof(buf)) - goto bad_format; - - p = buf; - for (i = 0; i < 5; i++) { - r = read(STDIN_FILENO, &b, 1); - if (r < 0) - eprintf("read :"); - if (r == 0 || b != magic[i]) - goto bad_format; - } - - for (i = 0; i < 3; i++) { - if (!isdigit(*p)) - goto bad_format; - while (isdigit(*p)) p++; - if (*p++ != ' ') - goto bad_format; - } - while (isalnum(*p) || *p == ' ') { - if (p[0] == ' ' && p[-1] == ' ') - goto bad_format; - p++; - } - if (p[-1] == ' ' || p[0] != '\n') - goto bad_format; - - ewriteall(STDOUT_FILENO, buf, ptr, ""); - - return 0; -bad_format: - eprintf(": file format not supported\n"); - return 0; -} diff --git a/src/vu-repeat.c b/src/vu-repeat.c deleted file mode 100644 index 367d976..0000000 --- a/src/vu-repeat.c +++ /dev/null @@ -1,59 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include -#include - -USAGE("(count | 'inf') file") - -int -main(int argc, char *argv[]) -{ - struct stream stream; - size_t count = 0, ptr; - ssize_t r; - char buf[BUFSIZ]; - int inf = 0; - - ENOFLAGS(argc != 2); - - if (!strcmp(argv[0], "inf")) - inf = 1; - else - count = etozu_arg("the count", argv[0], 0, SIZE_MAX); - - if (inf) - einf_check_fd(STDOUT_FILENO, ""); - - stream.file = argv[1]; - stream.fd = eopen(stream.file, O_RDONLY); - einit_stream(&stream); - if (count > SIZE_MAX / stream.frames) - eprintf("%s: video is too long\n", stream.file); - stream.frames *= count; - fprint_stream_head(stdout, &stream); - efflush(stdout, ""); - - while (inf || count--) { - posix_fadvise(stream.fd, stream.headlen, 0, POSIX_FADV_SEQUENTIAL); - for (ptr = stream.headlen;; ptr += (size_t)r) { - r = pread(stream.fd, buf, sizeof(buf), ptr); - if (r < 0) - eprintf("pread %s:", stream.file); - if (r == 0) - break; - if (writeall(STDOUT_FILENO, buf, (size_t)r)) { - if (!inf || errno != EPIPE) - eprintf("write :"); - return 0; - } - } - } - - close(stream.fd); - return 0; -} diff --git a/src/vu-reverse.c b/src/vu-reverse.c deleted file mode 100644 index 5c978f2..0000000 --- a/src/vu-reverse.c +++ /dev/null @@ -1,47 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include - -USAGE("file") - -int -main(int argc, char *argv[]) -{ - struct stream stream; - size_t frame_size, ptr, end, n; - ssize_t r; - char buf[BUFSIZ]; - - ENOFLAGS(argc != 1); - - stream.file = argv[0]; - stream.fd = eopen(stream.file, O_RDONLY); - einit_stream(&stream); - fprint_stream_head(stdout, &stream); - efflush(stdout, ""); - echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); - frame_size = stream.width * stream.height * stream.pixel_size; - if (stream.frames > SSIZE_MAX / frame_size) - eprintf("%s: video is too large\n", stream.file); - - posix_fadvise(stream.fd, 0, 0, POSIX_FADV_RANDOM); - while (stream.frames--) { - ptr = stream.frames * frame_size; - end = ptr + frame_size; - while (ptr < end) { - r = pread(stream.fd, buf, sizeof(buf), ptr); - if (r < 0) - eprintf("pread %s:", stream.file); - else if (r == 0) - eprintf("%s: file is shorter than expected\n", stream.file); - ptr += n = (size_t)r; - ewriteall(STDOUT_FILENO, buf, n, ""); - } - } - - close(stream.fd); - return 0; -} diff --git a/src/vu-rewrite-head.c b/src/vu-rewrite-head.c deleted file mode 100644 index 0de1716..0000000 --- a/src/vu-rewrite-head.c +++ /dev/null @@ -1,129 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include -#include -#include -#include - -USAGE("[-h] file [(frames | 'auto') [(width | 'same') (height | 'same') [format | 'same']]]") - -static void -rewrite(struct stream *stream, int frames_auto) -{ - char head[STREAM_HEAD_MAX]; - ssize_t headlen; - size_t frame_size, frame_count, length; - struct stat st; - char *data; - - echeck_frame_size(stream->width, stream->height, stream->pixel_size, 0, stream->file); - frame_size = stream->width * stream->height * stream->pixel_size; - - if (fstat(stream->fd, &st)) - eprintf("fstat %s:", stream->file); - if (!S_ISREG(st.st_mode)) - eprintf("%s: not a regular file\n", stream->file); - - frame_count = (size_t)(st.st_size) / frame_size; - if (frame_count * frame_size != (size_t)(st.st_size)) - eprintf("%s: given the select width and height, " - "the file has an incomplete frame\n", stream->file); - if (frames_auto) - stream->frames = frame_count; - else if (stream->frames != frame_count) - eprintf("%s: frame count mismatch\n", stream->file); - - sprintf(head, "%zu %zu %zu %s\n%cuivf%zn", - stream->frames, stream->width, stream->height, stream->pixfmt, 0, &headlen); - - length = stream->frames * frame_size; - if (length > (size_t)SSIZE_MAX || headlen > (size_t)SSIZE_MAX - length) - eprintf("%s: video is too long\n", stream->file); - - if (headlen > stream->headlen) - if (ftruncate(stream->fd, length + headlen)) - eprintf("ftruncate %s:", stream->file); - - data = mmap(0, length + (size_t)headlen, PROT_READ | PROT_WRITE, MAP_PRIVATE, stream->fd, 0); - if (data == MAP_FAILED) - eprintf("mmap %s:", stream->file); - if (headlen != stream->headlen) - memmove(data + headlen, data + stream->headlen, length); - memcpy(data, head, (size_t)headlen); - munmap(data, length + (size_t)headlen); - - if (headlen < stream->headlen) - if (ftruncate(stream->fd, length + headlen)) - eprintf("ftruncate %s:", stream->file); -} - -int -main(int argc, char *argv[]) -{ - struct stream stream; - int headless = 0, frames_auto = 0; - - ARGBEGIN { - case 'h': - headless = 1; - break; - default: - usage(); - } ARGEND; - - - if (headless) { - if (argc != 5) - eprintf("all positional arguments are mandatory unless -h is used\n"); - } else if (argc != 1 || argc != 2 || argc != 4 || argc != 5) { - usage(); - } - - - memset(&stream, 0, sizeof(stream)); - stream.file = argv[0]; - stream.fd = eopen(stream.file, O_RDWR); - if (!headless) - einit_stream(&stream); - - - if (argc < 2 || !strcmp(argv[1], "auto")) - frames_auto = 1; - else - stream.frames = etozu_arg("the frame count", argv[1], 0, SIZE_MAX); - - if (argc < 4); - else if (strcmp(argv[2], "same")) - stream.width = etozu_arg("the width", argv[2], 1, SIZE_MAX); - else if (headless) - eprintf("cannot use both 'same' and -h\n"); - - if (argc < 4); - else if (strcmp(argv[3], "same")) - stream.height = etozu_arg("the height", argv[3], 1, SIZE_MAX); - else if (headless) - eprintf("cannot use both 'same' and -h\n"); - - if (argc < 5); - else if (strcmp(argv[4], "same")) { - if (strlen(argv[4]) >= sizeof(stream.pixfmt)) - eprintf("choosen pixel format is unsupported\n"); - strcpy(stream.pixfmt, argv[5]); - if (set_pixel_size(&stream)) - eprintf("choosen pixel format is unsupported\n"); - } else if (headless) { - eprintf("cannot use both 'same' and -h\n"); - } else if (argc > 1) { - usage(); - } - - - rewrite(&stream, frames_auto); - close(stream.fd); - return 0; -} diff --git a/src/vu-set-alpha.c b/src/vu-set-alpha.c deleted file mode 100644 index 2e80154..0000000 --- a/src/vu-set-alpha.c +++ /dev/null @@ -1,69 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include - -USAGE("[-i] alpha-stream") - -static void -process_xyza(struct stream *colour, struct stream *alpha, size_t n) -{ - size_t i; - double a; - for (i = 0; i < n; i += colour->pixel_size) { - a = ((double *)(alpha->buf + i))[1]; - a *= ((double *)(alpha->buf + i))[3]; - ((double *)(colour->buf + i))[3] *= a; - } -} - -static void -process_xyza_i(struct stream *colour, struct stream *alpha, size_t n) -{ - size_t i; - double a; - for (i = 0; i < n; i += colour->pixel_size) { - a = 1 - ((double *)(alpha->buf + i))[1]; - a *= ((double *)(alpha->buf + i))[3]; - ((double *)(colour->buf + i))[3] *= a; - } -} - -int -main(int argc, char *argv[]) -{ - int invert = 0; - struct stream colour, alpha; - void (*process)(struct stream *colour, struct stream *alpha, size_t n) = NULL; - - ARGBEGIN { - case 'i': - invert = 1; - break; - default: - usage(); - } ARGEND; - - if (argc != 1) - usage(); - - colour.file = ""; - colour.fd = STDIN_FILENO; - einit_stream(&colour); - - alpha.file = argv[0]; - alpha.fd = eopen(alpha.file, O_RDONLY); - einit_stream(&alpha); - - if (!strcmp(colour.pixfmt, "xyza")) - process = invert ? process_xyza_i : process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); - - process_two_streams(&colour, &alpha, STDOUT_FILENO, "", process); - return 0; -} diff --git a/src/vu-set-luma.c b/src/vu-set-luma.c deleted file mode 100644 index 4500645..0000000 --- a/src/vu-set-luma.c +++ /dev/null @@ -1,47 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include - -USAGE("luma-stream") - -static void -process_xyza(struct stream *colour, struct stream *luma, size_t n) -{ - size_t i; - double a; - for (i = 0; i < n; i += colour->pixel_size) { - a = ((double *)(luma->buf + i))[1]; - a *= ((double *)(luma->buf + i))[3]; - ((double *)(colour->buf + i))[1] *= a; - } -} - -int -main(int argc, char *argv[]) -{ - struct stream colour, luma; - void (*process)(struct stream *colour, struct stream *luma, size_t n); - - ENOFLAGS(argc != 1); - - colour.file = ""; - colour.fd = STDIN_FILENO; - einit_stream(&colour); - - luma.file = argv[0]; - luma.fd = eopen(luma.file, O_RDONLY); - einit_stream(&luma); - - if (!strcmp(colour.pixfmt, "xyza")) - process = process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); - - process_two_streams(&colour, &luma, STDOUT_FILENO, "", process); - return 0; -} diff --git a/src/vu-set-saturation.c b/src/vu-set-saturation.c deleted file mode 100644 index 1d3ed83..0000000 --- a/src/vu-set-saturation.c +++ /dev/null @@ -1,79 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include - -USAGE("[-w] saturation-stream") - -static void -process_xyza(struct stream *colour, struct stream *satur, size_t n) -{ - size_t i; - double s, *x, *z, X, Z; - X = D65_XYY_X / D65_XYY_Y; - Z = 1 / D65_XYY_Y - 1 - X; - for (i = 0; i < n; i += colour->pixel_size) { - s = ((double *)(satur->buf + i))[1]; - s *= ((double *)(satur->buf + i))[3]; - x = ((double *)(colour->buf + i)) + 0; - z = ((double *)(colour->buf + i)) + 2; - *x = (*x - X) * s + X; - *z = (*z - Z) * s + Z; - } -} - -static void -process_xyza_w(struct stream *colour, struct stream *satur, size_t n) -{ - size_t i; - double s, *x, *z, X, Z; - for (i = 0; i < n; i += colour->pixel_size) { - X = ((double *)(satur->buf + i))[0]; - Z = ((double *)(satur->buf + i))[2]; - s = ((double *)(satur->buf + i))[1]; - s *= ((double *)(satur->buf + i))[3]; - x = ((double *)(colour->buf + i)) + 0; - z = ((double *)(colour->buf + i)) + 2; - *x = (*x - X) * s + X; - *z = (*z - Z) * s + Z; - } -} - -int -main(int argc, char *argv[]) -{ - struct stream colour, satur; - int whitepoint = 0; - void (*process)(struct stream *colour, struct stream *satur, size_t n) = NULL; - - ARGBEGIN { - case 'w': - whitepoint = 1; - break; - default: - usage(); - } ARGEND; - - if (argc != 1) - usage(); - - colour.file = ""; - colour.fd = STDIN_FILENO; - einit_stream(&colour); - - satur.file = argv[0]; - satur.fd = eopen(satur.file, O_RDONLY); - einit_stream(&satur); - - if (!strcmp(colour.pixfmt, "xyza")) - process = whitepoint ? process_xyza_w : process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); - - process_two_streams(&colour, &satur, STDOUT_FILENO, "", process); - return 0; -} diff --git a/src/vu-single-colour.c b/src/vu-single-colour.c deleted file mode 100644 index 254ea2a..0000000 --- a/src/vu-single-colour.c +++ /dev/null @@ -1,88 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include - -USAGE("[-f frames | -f 'inf'] -w width -h height (X Y Z | Y) [alpha]") - -typedef double pixel_t[4]; - -int -main(int argc, char *argv[]) -{ - struct stream stream; - double X, Y, Z, alpha = 1; - size_t x, y, n; - pixel_t buf[1024]; - ssize_t r; - int inf = 0; - char *arg; - - stream.width = 0; - stream.height = 0; - stream.frames = 1; - - ARGBEGIN { - case 'f': - arg = EARG(); - if (!strcmp(arg, "inf")) - inf = 1, stream.frames = 0; - else - stream.frames = etozu_flag('f', arg, 1, SIZE_MAX); - break; - case 'w': - stream.width = etozu_flag('w', EARG(), 1, SIZE_MAX); - break; - case 'h': - stream.height = etozu_flag('h', EARG(), 1, SIZE_MAX); - break; - default: - usage(); - } ARGEND; - - if (!stream.width || !stream.height || !argc || argc > 4) - usage(); - - if (argc < 3) { - X = D65_XYY_X / D65_XYY_Y; - Z = 1 / D65_XYY_Y - 1 - X; - Y = etolf_arg("the Y value", argv[1]); - } else { - X = etolf_arg("the X value", argv[0]); - Y = etolf_arg("the Y value", argv[1]); - Z = etolf_arg("the Z value", argv[2]); - } - if (~argc & 1) - alpha = etolf_arg("the alpha value", argv[argc - 1]); - - if (inf) - einf_check_fd(STDOUT_FILENO, ""); - - strcpy(stream.pixfmt, "xyza"); - fprint_stream_head(stdout, &stream); - efflush(stdout, ""); - - for (x = 0; x < ELEMENTSOF(buf); x++) { - buf[x][0] = X; - buf[x][1] = Y; - buf[x][2] = Z; - buf[x][3] = alpha; - } - while (inf || stream.frames--) { - for (y = stream.height; y--;) { - for (x = stream.width; x;) { - x -= n = ELEMENTSOF(buf) < x ? ELEMENTSOF(buf) : x; - for (n *= sizeof(*buf); n; n -= (size_t)r) { - r = write(STDOUT_FILENO, buf, n); - if (r < 0) - eprintf("write :"); - } - } - } - } - - return 0; -} diff --git a/src/vu-split.c b/src/vu-split.c deleted file mode 100644 index ff6ce38..0000000 --- a/src/vu-split.c +++ /dev/null @@ -1,72 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include -#include -#include - -USAGE("(file (end-point | 'end')) ...") - -int -main(int argc, char *argv[]) -{ - struct stream stream; - size_t *ends, i, parts, ptr, end, frame_size, n; - FILE *fp; - int fd; - - ENOFLAGS(argc < 2 || argc % 2); - - stream.file = ""; - stream.fd = STDIN_FILENO; - einit_stream(&stream); - echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, stream.file); - frame_size = stream.width * stream.height * stream.pixel_size; - if (stream.frames > SSIZE_MAX / frame_size) - eprintf("%s: video is too large\n", stream.file); - - parts = (size_t)argc / 2; - ends = alloca(parts * sizeof(*ends)); - - for (i = 0; i < parts; i++) { - if (!strcmp(argv[i * 2 + 1], "end")) - ends[i] = stream.frames; - else if (tozu(argv[i * 2 + 1], 0, SIZE_MAX, ends + i)) - eprintf("the end point must be an integer in [0, %zu]\n", SIZE_MAX); - if (i && ends[i] <= ends[i - 1]) - eprintf("the end points must be in strictly ascending order\n"); - if (ends[i] > stream.frames) - eprintf("frame %zu is beyond the end of the video\n", ends[i]); - } - - ptr = 0; - for (i = 0; i < parts; i++) { - fd = eopen(argv[i * 2], O_WRONLY | O_CREAT | O_TRUNC, 0666); - fp = fdopen(fd, "wb"); - if (!fp) - eprintf("fdopen %s:", argv[i * 2]); - - stream.frames = ends[i] - (i ? ends[i - 1] : 0); - fprint_stream_head(fp, &stream); - efflush(fp, argv[i * 2]); - - for (end = ends[i] * frame_size; ptr < end; ptr += n) { - if (stream.ptr == sizeof(stream.buf)) - n = stream.ptr < end - ptr ? stream.ptr : end - ptr; - else if (!(n = eread_stream(&stream, end - ptr))) - eprintf("%s: file is shorter than expected\n", stream.file); - ewriteall(STDOUT_FILENO, stream.buf, n, ""); - memmove(stream.buf, stream.buf + n, stream.ptr -= n); - } - - if (fclose(fp)) - eprintf("%s:", argv[i * 2]); - close(fd); - } - - return 0; -} diff --git a/src/vu-stack.c b/src/vu-stack.c deleted file mode 100644 index a03fd91..0000000 --- a/src/vu-stack.c +++ /dev/null @@ -1,80 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include - -USAGE("[-b] bottom-stream ... top-stream") - -#define PROCESS_LINEAR_3CH_ALPHA(TYPE, BLEND)\ - do {\ - TYPE x1, y1, z1, a1;\ - TYPE x2, y2, z2, a2;\ - size_t i, j;\ - for (i = 0; i < n; i += streams->pixel_size) {\ - x1 = ((TYPE *)(streams[0].buf + i))[0];\ - y1 = ((TYPE *)(streams[0].buf + i))[1];\ - z1 = ((TYPE *)(streams[0].buf + i))[2];\ - a1 = ((TYPE *)(streams[0].buf + i))[3];\ - for (j = 1; j < n_streams; j++) {\ - x2 = ((TYPE *)(streams[j].buf + i))[0];\ - y2 = ((TYPE *)(streams[j].buf + i))[1];\ - z2 = ((TYPE *)(streams[j].buf + i))[2];\ - a2 = ((TYPE *)(streams[j].buf + i))[3];\ - if (BLEND)\ - a2 /= j + 1;\ - x1 = x1 * a1 * (1 - a2) + x2 * a2;\ - y1 = y1 * a1 * (1 - a2) + y2 * a2;\ - z1 = z1 * a1 * (1 - a2) + z2 * a2;\ - a1 = a1 * (1 - a2) + a2;\ - }\ - ((TYPE *)(streams[0].buf + i))[0] = x1;\ - ((TYPE *)(streams[0].buf + i))[1] = y1;\ - ((TYPE *)(streams[0].buf + i))[2] = z1;\ - ((TYPE *)(streams[0].buf + i))[3] = a1;\ - }\ - } while (0) - -static void process_xyza (struct stream *streams, size_t n_streams, size_t n) { PROCESS_LINEAR_3CH_ALPHA(double, 0); } -static void process_xyza_b(struct stream *streams, size_t n_streams, size_t n) { PROCESS_LINEAR_3CH_ALPHA(double, 1); } - -int -main(int argc, char *argv[]) -{ - struct stream *streams; - size_t n_streams, i; - int blend = 0; - void (*process)(struct stream *streams, size_t n_streams, size_t n) = NULL; - - ARGBEGIN { - case 'b': - blend = 1; - break; - default: - usage(); - } ARGEND; - - if (argc < 2) - usage(); - - n_streams = (size_t)argc; - streams = ecalloc(n_streams, sizeof(*streams)); - - for (i = 0; i < n_streams; i++) { - streams[i].file = argv[i]; - streams[i].fd = eopen(streams[i].file, O_RDONLY); - } - - if (!strcmp(streams->pixfmt, "xyza")) - process = blend ? process_xyza_b : process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", streams->pixfmt); - - process_multiple_streams(streams, n_streams, STDOUT_FILENO, "", process); - - free(streams); - return 0; -} diff --git a/src/vu-to-image.c b/src/vu-to-image.c deleted file mode 100644 index 4b3d20c..0000000 --- a/src/vu-to-image.c +++ /dev/null @@ -1,150 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include -#include -#include - -USAGE("[-d depth | -f]") - -static int luma_warning_triggered = 0; -static int gamut_warning_triggered = 0; -static int alpha_warning_triggered = 0; - -static void -write_pixel(double R, double G, double B, double A, int bytes, unsigned long long int max) -{ - unsigned long long int colours[4]; - unsigned char buf[4 * 8]; - int i, j, k, bm = bytes - 1; - - if (R < 0 || G < 0 || B < 0 || R > 1 || G > 1 || B > 1) { - if (gamut_warning_triggered) { - gamut_warning_triggered = 1; - weprintf("warning: out-of-gamut colour detected\n"); - } - ; /* TODO gamut */ - R = R < 0 ? 0 : R > 1 ? 1 : R; - G = G < 0 ? 0 : G > 1 ? 1 : G; - B = B < 0 ? 0 : B > 1 ? 1 : B; - } - - if (A < 0 || A > 1) { - if (alpha_warning_triggered) { - alpha_warning_triggered = 1; - weprintf("warning: alpha values truncated\n"); - } - A = A < 0 ? 0 : 1; - } - - colours[0] = srgb_encode(R) * max + 0.5; - colours[1] = srgb_encode(G) * max + 0.5; - colours[2] = srgb_encode(B) * max + 0.5; - colours[3] = A * max + 0.5; - - for (i = k = 0; i < 4; i++) { - for (j = 0; j < bytes; j++, k++) { - buf[k + bm - j] = (unsigned char)(colours[j]); - colours[j] >>= 8; - } - } - - ewriteall(STDOUT_FILENO, buf, (size_t)bytes * 4, ""); -} - -static void -process_xyza(struct stream *stream, size_t n, int bytes, unsigned long long int max) -{ - size_t i; - double X, Y, Z, A, R, G, B; - for (i = 0; i < n; i += stream->pixel_size) { - X = ((double *)(stream->buf + i))[0]; - Y = ((double *)(stream->buf + i))[1]; - Z = ((double *)(stream->buf + i))[2]; - A = ((double *)(stream->buf + i))[3]; - - if (Y < 0 || Y > 1) { - if (luma_warning_triggered) { - luma_warning_triggered = 1; - weprintf("warning: %s colour detected\n", - Y < 0 ? "subblack" : "superwhite"); - } - } - - srgb_to_ciexyz(X, Y, Z, &R, &G, &B); - write_pixel(R, G, B, A, bytes, max); - } -} - -int -main(int argc, char *argv[]) -{ - struct stream stream; - int depth = 16, bytes, farbfeld = 0; - unsigned long long int max; - size_t n; - void (*process)(struct stream *stream, size_t n, int bytes, unsigned long long int max); - - ARGBEGIN { - case 'd': - depth = etoi_flag('d', EARG(), 1, 64); - break; - case 'f': - farbfeld = 1; - break; - default: - usage(); - } ARGEND; - - if (argc || (farbfeld && depth != 16)) - usage(); - - stream.fd = STDIN_FILENO; - stream.file = ""; - einit_stream(&stream); - - max = 1ULL << (depth - 1); - max |= max - 1; - for (bytes = 1; bytes * 8 < depth; bytes++); - - if (!strcmp(stream.pixfmt, "xyza")) - process = process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); - - if (farbfeld) { - uint32_t width = stream.width, height = stream.height; - if (stream.width > UINT32_MAX) - eprintf("%s: frame is too wide\n", stream.file); - if (stream.height > UINT32_MAX) - eprintf("%s: frame is too tall\n", stream.file); - printf("farbfeld"); - memmove(stream.buf + 8, stream.buf, stream.ptr); - stream.ptr += 8; - width = htonl(width); - height = htonl(height); - memcpy(stream.buf + 0, &width, 4); - memcpy(stream.buf + 4, &height, 4); - } else { - printf("P7\n" - "WIDTH %zu\n" - "HEIGHT %zu\n" - "DEPTH 4\n" /* Depth actually means channels */ - "MAXVAL %llu\n" - "TUPLTYPE RGB_ALPHA\n" - "ENDHDR\n", stream.width, stream.height, max); - } - efflush(stdout, ""); - - do { - n = stream.ptr - (stream.ptr % stream.pixel_size); - process(&stream, n, bytes, max); - memmove(stream.buf, stream.buf + n, stream.ptr -= n); - } while (eread_stream(&stream, SIZE_MAX)); - - return 0; -} diff --git a/src/vu-to-text.c b/src/vu-to-text.c deleted file mode 100644 index 73bf981..0000000 --- a/src/vu-to-text.c +++ /dev/null @@ -1,51 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include - -USAGE("") - -static void -process_xyza(struct stream *stream, size_t n) -{ - size_t i; - for (i = 0; i < n; i += stream->pixel_size) - printf("%lf %lf %lf %lf\n", - ((double *)(stream->buf + i))[0], - ((double *)(stream->buf + i))[1], - ((double *)(stream->buf + i))[2], - ((double *)(stream->buf + i))[3]); -} - -int -main(int argc, char *argv[]) -{ - struct stream stream; - size_t n; - void (*process)(struct stream *stream, size_t n) = NULL; - - ENOFLAGS(argc); - - stream.file = ""; - stream.fd = STDIN_FILENO; - einit_stream(&stream); - - if (!strcmp(stream.pixfmt, "xyza")) - process = process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); - - printf("%zu %zu %zu %s", stream.frames, stream.width, stream.height, stream.pixfmt); - - while ((n = eread_stream(&stream, SIZE_MAX))) { - n -= n % stream.pixel_size; - process(&stream, n); - memmove(stream.buf, stream.buf + n, stream.ptr -= n); - } - - efshut(stdout, ""); - return 0; -} diff --git a/src/vu-to-video.c b/src/vu-to-video.c deleted file mode 100644 index ac4707e..0000000 --- a/src/vu-to-video.c +++ /dev/null @@ -1,146 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#if defined(HAVE_PRCTL) -# include -#endif -#include -#include -#include -#include -#include -#include - -USAGE("[-d] frame-rate ffmpeg-arguments ...") - -static int draft = 0; - -static void -process_xyza(char *buf, size_t n, int fd, const char *fname) -{ - double *pixel, r, g, b; - uint16_t *pixels, *end; - uint16_t pixbuf[1024]; - long int a, y, u, v; - size_t ptr; - pixels = pixbuf; - end = pixbuf + ELEMENTSOF(pixbuf); - if (draft) { - for (ptr = 0; ptr < n; ptr += sizeof(pixel)) { - pixel = (double *)(buf + ptr); - a = (long int)(pixel[3] * 0xFFFFL); - ciexyz_to_scaled_yuv(pixel[0], pixel[1], pixel[2], &r, &g, &b); - y = (long int)r + 16 * 256; - u = (long int)g + 128 * 256; - v = (long int)b + 128 * 256; - *pixels++ = htons((uint16_t)(a < 0 ? 0 : a > 0xFFFFL ? 0xFFFFL : a)); - *pixels++ = htons((uint16_t)(y < 0 ? 0 : y > 0xFFFFL ? 0xFFFFL : y)); - *pixels++ = htons((uint16_t)(u < 0 ? 0 : u > 0xFFFFL ? 0xFFFFL : u)); - *pixels++ = htons((uint16_t)(v < 0 ? 0 : v > 0xFFFFL ? 0xFFFFL : v)); - if (pixels == end) - ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), fname); - } - } else { - for (ptr = 0; ptr < n; ptr += sizeof(pixel)) { - pixel = (double *)(buf + ptr); - a = (long int)(pixel[3] * 0xFFFFL); - ciexyz_to_srgb(pixel[0], pixel[1], pixel[2], &r, &g, &b); - r = srgb_encode(r); - g = srgb_encode(g); - b = srgb_encode(b); - srgb_to_yuv(r, g, b, pixel + 0, pixel + 1, pixel + 2); - y = (long int)(pixel[0] * 0xFFFFL); - u = (long int)(pixel[1] * 0xFFFFL); - v = (long int)(pixel[2] * 0xFFFFL); - y += 16 * 256; - u += 128 * 256; - v += 128 * 256; - *pixels++ = htons((uint16_t)(a < 0 ? 0 : a > 0xFFFFL ? 0xFFFFL : a)); - *pixels++ = htons((uint16_t)(y < 0 ? 0 : y > 0xFFFFL ? 0xFFFFL : y)); - *pixels++ = htons((uint16_t)(u < 0 ? 0 : u > 0xFFFFL ? 0xFFFFL : u)); - *pixels++ = htons((uint16_t)(v < 0 ? 0 : v > 0xFFFFL ? 0xFFFFL : v)); - if (pixels == end) - ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), fname); - } - } - if (pixels != pixbuf) - ewriteall(fd, pixels = pixbuf, sizeof(pixbuf), fname); -} - -int -main(int argc, char *argv[]) -{ - struct stream stream; - char geometry[2 * 3 * sizeof(size_t) + 2]; - char *frame_rate; - const char **cmd; - size_t n = 0; - int status, pipe_rw[2]; - pid_t pid; - void (*process)(char *buf, size_t n, int fd, const char *fname) = NULL; - - ARGBEGIN { - case 'd': - draft = 1; - break; - default: - usage(); - } ARGEND; - - if (argc < 2) - usage(); - - frame_rate = *argv++, argc--; - cmd = ecalloc((size_t)argc + 12, sizeof(*cmd)); - cmd[n++] = "ffmpeg"; - cmd[n++] = "-f", cmd[n++] = "rawvideo"; - cmd[n++] = "-pix_fmt", cmd[n++] = "ayuv64le"; - cmd[n++] = "-r", cmd[n++] = frame_rate; - cmd[n++] = "-s:v", cmd[n++] = geometry; - cmd[n++] = "-i", cmd[n++] = "-"; - memcpy(cmd + n, argv, (size_t)argc * sizeof(*cmd)); - - stream.file = ""; - stream.fd = STDIN_FILENO; - einit_stream(&stream); - - sprintf(geometry, "%zux%zu", stream.width, stream.height); - - if (!strcmp(stream.pixfmt, "xyza")) - process = process_xyza; - else - eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); - - if (pipe(pipe_rw)) - eprintf("pipe:"); - - pid = fork(); - if (pid < 0) - eprintf("fork:"); - - if (!pid) { -#if defined(HAVE_PRCTL) && defined(PR_SET_PDEATHSIG) - prctl(PR_SET_PDEATHSIG, SIGKILL); -#endif - close(pipe_rw[1]); - if (dup2(pipe_rw[0], STDIN_FILENO) == -1) - eprintf("dup2:"); - close(pipe_rw[0]); - eprintf("exec ffmpeg:"); - } - - close(pipe_rw[0]); - while (!eread_stream(&stream, SIZE_MAX)) { - n = stream.ptr - (stream.ptr % stream.pixel_size); - process(stream.buf, n, pipe_rw[1], ""); - memmove(stream.buf, stream.buf + n, stream.ptr -= n); - } - close(pipe_rw[1]); - - if (waitpid(pid, &status, 0) == -1) - eprintf("waitpid:"); - - return !!status; -} diff --git a/src/vu-transpose.c b/src/vu-transpose.c deleted file mode 100644 index 0c32d81..0000000 --- a/src/vu-transpose.c +++ /dev/null @@ -1,45 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "stream.h" -#include "util.h" - -#include -#include -#include -#include - -USAGE("") - -int -main(int argc, char *argv[]) -{ - struct stream stream; - char *buf, *image; - size_t n, imgw, imgh, x, y, i, b; - - ENOFLAGS(argc); - - stream.file = ""; - stream.fd = STDIN_FILENO; - einit_stream(&stream); - fprint_stream_head(stdout, &stream); - efflush(stdout, ""); - - echeck_frame_size(stream.width, stream.height, stream.pixel_size, 0, ""); - n = stream.width * stream.height * stream.pixel_size; - buf = emalloc(n); - image = emalloc(n); - - imgw = stream.width * (imgh = stream.height * stream.pixel_size); - memcpy(buf, stream.buf, stream.ptr); - while (eread_frame(&stream, buf, n)) { - for (b = y = 0; y < imgh; y += stream.pixel_size) - for (x = 0; x < imgw; x += imgh) - for (i = 0; i < stream.pixel_size; i++) - image[x + y + i] = buf[b++]; - ewriteall(STDOUT_FILENO, image, n, ""); - } - - free(buf); - free(image); - return 0; -} diff --git a/src/vu-write-head.c b/src/vu-write-head.c deleted file mode 100644 index 9e7c4a3..0000000 --- a/src/vu-write-head.c +++ /dev/null @@ -1,18 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "util.h" - -USAGE("parameters ...") - -int -main(int argc, char *argv[]) -{ - ENOFLAGS(!argc); - - printf("%s", *argv++); - while (*argv) - printf(" %s", *argv++); - printf("\n%cuivf", 0); - - efshut(stdout, ""); - return 0; -} -- cgit v1.2.3-70-g09d2