From 0804a80954bf9b8c11392d77a4933ec0a4ff635b Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 8 Apr 2017 23:02:48 +0200 Subject: Add blind-translate and fix errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/blind-translate.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/blind-translate.c (limited to 'src/blind-translate.c') diff --git a/src/blind-translate.c b/src/blind-translate.c new file mode 100644 index 0000000..95b8dab --- /dev/null +++ b/src/blind-translate.c @@ -0,0 +1,184 @@ +/* See LICENSE file for copyright and license details. */ +#include "stream.h" +#include "util.h" + +#include +#include +#include +#include +#include + +USAGE("[-wp] translation-stream") + +static int invtrans = 0; +static char zeroes[BUFSIZ]; + +static void* +next_pixel(struct stream *stream, size_t *ptr) +{ + void *ret; + if (*ptr + stream->pixel_size >= stream->ptr) { + memmove(stream->buf, stream->buf + *ptr, stream->ptr -= *ptr); + *ptr = 0; + while (stream->ptr < stream->pixel_size) + if (!eread_stream(stream, SIZE_MAX)) + return NULL; + } + ret = stream->buf + *ptr; + *ptr += stream->pixel_size; + return ret; +} + +static int +process_frame(struct stream *stream, char *buf, size_t n, + size_t above, size_t below, size_t left, size_t right) +{ +#define ZEROES(N) ewritezeroes(STDOUT_FILENO, zeroes, sizeof(zeroes), N, "") + + size_t i, w = n - left - right; + int first = 1; + + if (!eread_row(stream, buf, n)) + return 0; + + for (i = 0; i < above; i++) + ZEROES(n); + for (i = 0; i < below; i++, first = 0) + if (!first && !eread_row(stream, buf, n)) + goto eof; + + for (i = above + below; i < stream->height; i++, first = 0) { + if (!first && !eread_row(stream, buf, n)) + goto eof; + ZEROES((size_t)left); + ewriteall(STDOUT_FILENO, buf + right, w, ""); + ZEROES((size_t)right); + } + + for (i = 0; i < below; i++) + ZEROES(n); + for (i = 0; i < above; i++, first = 0) + if (!first && !eread_row(stream, buf, n)) + goto eof; + + return 1; +eof: + eprintf("%s: file is shorter than expected\n", stream->file); + return 0; + +#undef ZEROES +} + +static void +process(struct stream *stream, struct stream *trstream) +{ + char *buf; + size_t n, p = 0; + double *trans; + ssize_t trx = 0, try = 0; + size_t above = 0, below = 0, left = 0, right = 0; + + memset(zeroes, 0, sizeof(zeroes)); + + if (!check_frame_size(stream->width, 1, stream->pixel_size)) + eprintf("%s: video frame is too wide\n", stream->file); + n = stream->width * stream->pixel_size; + buf = emalloc(n); + + do { + if ((trans = next_pixel(trstream, &p))) { + trx = (ssize_t)round(invtrans ? -trans[0] : trans[0]); + try = (ssize_t)round(invtrans ? -trans[1] : trans[1]); + + above = try > 0 ? (size_t)try : 0; + below = try < 0 ? (size_t)-try : 0; + left = (trx > 0 ? (size_t)trx : 0) * stream->pixel_size; + right = (trx < 0 ? (size_t)-trx : 0) * stream->pixel_size; + + above = above < stream->height ? above : stream->height; + below = below < stream->height ? below : stream->height; + left = left < n ? left : n; + right = right < n ? right : n; + } + } while (process_frame(stream, buf, n, above, below, left, right)); + + free(buf); +} + +static void +process_wrap(struct stream *stream, struct stream *trstream) +{ + char *buf, *row; + size_t n, rown, p = 0; + double *trans; + ssize_t trx = 0, try = 0, py; + size_t off = 0, y; + + echeck_frame_size(stream->width, stream->height, stream->pixel_size, 0, ""); + n = stream->height * (rown = stream->width * stream->pixel_size); + buf = emalloc(n); + + while (eread_frame(stream, buf, n)) { + if ((trans = next_pixel(trstream, &p))) { + trx = (ssize_t)round(invtrans ? -trans[0] : trans[0]); + try = (ssize_t)round(invtrans ? -trans[1] : trans[1]); + trx %= (ssize_t)stream->width; + if (trx < 0) + trx += (ssize_t)stream->width; + off = (stream->width - (size_t)trx) % stream->width; + off = off * stream->pixel_size; + } + + for (y = 0; y < stream->height; y++) { + py = ((ssize_t)y - try) % (ssize_t)stream->height; + if (py < 0) + py += (ssize_t)stream->height; + row = buf + (size_t)py * rown; + ewriteall(STDOUT_FILENO, row + off, rown - off, ""); + ewriteall(STDOUT_FILENO, row, off, ""); + } + } + + free(buf); +} + +int +main(int argc, char *argv[]) +{ + struct stream stream; + struct stream trstream; + int wrap = 0; + + ARGBEGIN { + case 'w': + wrap = 1; + break; + case 'p': + invtrans = 1; + break; + } ARGEND; + + if (argc != 1) + usage(); + + stream.file = ""; + stream.fd = STDIN_FILENO; + einit_stream(&stream); + fprint_stream_head(stdout, &stream); + efflush(stdout, ""); + + trstream.file = argv[0]; + trstream.fd = eopen(trstream.file, O_RDONLY); + einit_stream(&trstream); + + if (trstream.width != 1 || trstream.height != 1) + eprintf("translation-stream does not have 1x1 geometry\n"); + + if (strcmp(trstream.pixfmt, "xyza")) + eprintf("pixel format of translation-stream %s " + "is not supported, try xyza\n", trstream.pixfmt); + + (wrap ? process_wrap : process)(&stream, &trstream); + close(trstream.fd); + return 0; +} -- cgit v1.2.3-70-g09d2