From 9b496d0545a151b6516ea1240fb3bd6b725ccf40 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Wed, 11 Jan 2017 00:12:32 +0100 Subject: Add vu-extend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/vu-extend.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/vu-flip.c | 2 +- src/vu-flop.c | 2 +- src/vu-transpose.c | 4 +- 4 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 src/vu-extend.c (limited to 'src') diff --git a/src/vu-extend.c b/src/vu-extend.c new file mode 100644 index 0000000..1177be6 --- /dev/null +++ b/src/vu-extend.c @@ -0,0 +1,144 @@ +/* See LICENSE file for copyright and license details. */ +#include "arg.h" +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include + +static void +usage(void) +{ + eprintf("usage: %s [-l left] [-r right] [-a above] [-b below] [-t]\n", argv0); +} + +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; + ssize_t r; + int tile = 0; + + ARGBEGIN { + case 'l': + if (tozu(EARGF(usage()), 0, SIZE_MAX, &left)) + eprintf("argument of -l must be an integer in [0, %zu]\n", SIZE_MAX); + break; + case 'r': + if (tozu(EARGF(usage()), 0, SIZE_MAX, &right)) + eprintf("argument of -r must be an integer in [0, %zu]\n", SIZE_MAX); + break; + case 'a': + if (tozu(EARGF(usage()), 0, SIZE_MAX, &top)) + eprintf("argument of -a must be an integer in [0, %zu]\n", SIZE_MAX); + break; + case 'b': + if (tozu(EARGF(usage()), 0, SIZE_MAX, &bottom)) + eprintf("argument of -b must be an integer in [0, %zu]\n", SIZE_MAX); + break; + case 't': + tile = 1; + break; + default: + usage(); + } ARGEND; + + if (argc) + usage(); + + stream.file = ""; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + + if (stream.width > SIZE_MAX / stream.pixel_size) + eprintf(": video frame is too large\n"); + n = stream.width * stream.pixel_size; + if (n > SIZE_MAX / stream.height) + eprintf(": video frame is too large\n"); + n *= stream.height; + if (!(buf = malloc(n))) + eprintf("malloc:"); + + 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; + if (imgw > SIZE_MAX / stream.pixel_size) + eprintf(": output video frame is too large\n"); + m = imgw *= stream.pixel_size; + if (m > SIZE_MAX / imgh) + eprintf(": output video frame is too large\n"); + m *= imgh; + if (!(image = malloc(m))) + eprintf("malloc:"); + + if (!tile) + memset(image, 0, m); + + stream.width += left + right; + h = stream.height += top + bottom; + fprint_stream_head(stdout, &stream); + fflush(stdout); + if (ferror(stdout)) + eprintf(":"); + 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); + for (;;) { + for (; ptr < n; ptr += (size_t)r) { + r = read(stream.fd, buf + ptr, n - ptr); + if (r < 0) { + eprintf("read %s:", stream.file); + } else if (r == 0) { + if (!ptr) + break; + eprintf("%s: incomplete frame", stream.file); + } + } + if (!ptr) + break; + + 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); + } + + for (ptr = 0; ptr < m; ptr += (size_t)r) { + r = write(STDOUT_FILENO, image + ptr, m - ptr); + if (r < 0) + eprintf("write "); + } + } + + return 0; +} diff --git a/src/vu-flip.c b/src/vu-flip.c index 372d5eb..d28d1cf 100644 --- a/src/vu-flip.c +++ b/src/vu-flip.c @@ -36,7 +36,7 @@ main(int argc, char *argv[]) fprint_stream_head(stdout, &stream); fflush(stdout); if (ferror(stdout)) - eprintf(":"); + eprintf(":"); if (stream.width > SIZE_MAX / stream.pixel_size) eprintf(": video is too wide\n"); diff --git a/src/vu-flop.c b/src/vu-flop.c index 733ced5..1d21d20 100644 --- a/src/vu-flop.c +++ b/src/vu-flop.c @@ -36,7 +36,7 @@ main(int argc, char *argv[]) fprint_stream_head(stdout, &stream); fflush(stdout); if (ferror(stdout)) - eprintf(":"); + eprintf(":"); if (stream.width > SIZE_MAX / stream.pixel_size) eprintf(": video is too wide\n"); diff --git a/src/vu-transpose.c b/src/vu-transpose.c index 09fe4b8..d9b7aeb 100644 --- a/src/vu-transpose.c +++ b/src/vu-transpose.c @@ -47,10 +47,10 @@ main(int argc, char *argv[]) fprint_stream_head(stdout, &stream); fflush(stdout); if (ferror(stdout)) - eprintf(":"); + eprintf(":"); if (stream.width > SIZE_MAX / stream.pixel_size) - eprintf(": video is too wide\n"); + eprintf(": video frame is too large\n"); n = stream.width * stream.pixel_size; if (n > SIZE_MAX / stream.height) eprintf(": video frame is too large\n"); -- cgit v1.2.3-70-g09d2