blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

commit 9b496d0545a151b6516ea1240fb3bd6b725ccf40
parent 233c9c368c163570e7599d0922f3350b9915ba1a
Author: Mattias Andrée <maandree@kth.se>
Date:   Wed, 11 Jan 2017 00:12:32 +0100

Add vu-extend

Signed-off-by: Mattias Andrée <maandree@kth.se>

Diffstat:
MMakefile | 1+
MTODO | 1-
Asrc/vu-extend.c | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/vu-flip.c | 2+-
Msrc/vu-flop.c | 2+-
Msrc/vu-transpose.c | 4++--
6 files changed, 149 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile @@ -7,6 +7,7 @@ BIN =\ vu-concat\ vu-cut\ vu-dissolve\ + vu-extend\ vu-flip\ vu-flop\ vu-from-image\ diff --git a/TODO b/TODO @@ -8,6 +8,5 @@ vu-to-video use ffmpeg to convert to another format vu-primaries given three selectable primaries split the video into three side-by-side which only one primary active vu-crop crop video, -t for creating tiling instead of cropping -vu-extend extend the video on which side with transparency, , -t for tiling vu-distort-map remap pixels using the X and Y values, -t for tiling, -s for improve quality on downscaling (pixels' neighbours must not change) diff --git a/src/vu-extend.c 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 <fcntl.h> +#include <inttypes.h> +#include <string.h> +#include <unistd.h> + +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 = "<stdin>"; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + + if (stream.width > SIZE_MAX / stream.pixel_size) + eprintf("<stdin>: video frame is too large\n"); + n = stream.width * stream.pixel_size; + if (n > SIZE_MAX / stream.height) + eprintf("<stdin>: video frame is too large\n"); + n *= stream.height; + if (!(buf = malloc(n))) + eprintf("malloc:"); + + if (stream.width > SIZE_MAX - left) + eprintf("<stdout>: output video is too wide\n"); + imgw = stream.width + left; + if (imgw > SIZE_MAX - right) + eprintf("<stdout>: output video is too wide\n"); + imgw += right; + if (stream.height > SIZE_MAX - top) + eprintf("<stdout>: output video is too tall\n"); + imgh = stream.height + top; + if (imgh > SIZE_MAX - bottom) + eprintf("<stdout>: output video is too tall\n"); + imgh += bottom; + if (imgw > SIZE_MAX / stream.pixel_size) + eprintf("<stdout>: output video frame is too large\n"); + m = imgw *= stream.pixel_size; + if (m > SIZE_MAX / imgh) + eprintf("<stdout>: 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("<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); + 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 <stdout>"); + } + } + + return 0; +} diff --git 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("<stdin>:"); + eprintf("<stdout>:"); if (stream.width > SIZE_MAX / stream.pixel_size) eprintf("<stdin>: video is too wide\n"); diff --git 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("<stdin>:"); + eprintf("<stdout>:"); if (stream.width > SIZE_MAX / stream.pixel_size) eprintf("<stdin>: video is too wide\n"); diff --git 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("<stdin>:"); + eprintf("<stdout>:"); if (stream.width > SIZE_MAX / stream.pixel_size) - eprintf("<stdin>: video is too wide\n"); + eprintf("<stdin>: video frame is too large\n"); n = stream.width * stream.pixel_size; if (n > SIZE_MAX / stream.height) eprintf("<stdin>: video frame is too large\n");