blind-translate.c - blind - suckless command-line video editing utility
 (HTM) git clone git://git.suckless.org/blind
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       blind-translate.c (4130B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include "common.h"
            3 
            4 USAGE("[-wp] translation-stream")
            5 
            6 static int invtrans = 0;
            7 static char zeroes[BUFSIZ];
            8 
            9 static void*
           10 next_pixel(struct stream *stream, size_t *ptr)
           11 {
           12         void *ret;
           13         if (*ptr + stream->pixel_size >= stream->ptr) {
           14                 memmove(stream->buf, stream->buf + *ptr, stream->ptr -= *ptr);
           15                 *ptr = 0;
           16                 while (stream->ptr < stream->pixel_size)
           17                         if (!eread_stream(stream, SIZE_MAX))
           18                                 return NULL;
           19         }
           20         ret = stream->buf + *ptr;
           21         *ptr += stream->pixel_size;
           22         return ret;
           23 }
           24 
           25 static int
           26 process_frame(struct stream *stream, char *buf, size_t above, size_t below, size_t left, size_t right)
           27 {
           28 #define ZEROES(N) ewritezeroes(STDOUT_FILENO, zeroes, sizeof(zeroes), N, "<stdout>")
           29 
           30         size_t i, w = stream->row_size - left - right;
           31         int first = 1;
           32 
           33         if (!eread_row(stream, buf))
           34                 return 0;
           35 
           36         for (i = 0; i < above; i++)
           37                 ZEROES(stream->row_size);
           38         for (i = 0; i < below; i++, first = 0)
           39                 if (!first && !eread_row(stream, buf))
           40                         goto eof;
           41 
           42         for (i = above + below; i < stream->height; i++, first = 0) {
           43                 if (!first && !eread_row(stream, buf))
           44                         goto eof;
           45                 ZEROES((size_t)left);
           46                 ewriteall(STDOUT_FILENO, buf + right, w, "<stdout>");
           47                 ZEROES((size_t)right);
           48         }
           49 
           50         for (i = 0; i < below; i++)
           51                 ZEROES(stream->row_size);
           52         for (i = 0; i < above; i++, first = 0)
           53                 if (!first && !eread_row(stream, buf))
           54                         goto eof;
           55 
           56         return 1;
           57 eof:
           58         eprintf("%s: file is shorter than expected\n", stream->file);
           59 }
           60 
           61 static void
           62 process(struct stream *stream, struct stream *trstream)
           63 {
           64         char *buf;
           65         size_t p = 0;
           66         double *trans, tmp;
           67         ssize_t trx = 0, try = 0;
           68         size_t above = 0, below = 0, left = 0, right = 0;
           69 
           70         memset(zeroes, 0, sizeof(zeroes));
           71 
           72         echeck_dimensions(stream, WIDTH, NULL);
           73         buf = emalloc(stream->row_size);
           74 
           75         do {
           76                 if ((trans = next_pixel(trstream, &p))) {
           77                         trx = (ssize_t)(tmp = round(invtrans ? -trans[0] : trans[0]));
           78                         try = (ssize_t)(tmp = round(invtrans ? -trans[1] : trans[1]));
           79 
           80                         above =  try > 0 ? (size_t)try  : 0;
           81                         below =  try < 0 ? (size_t)-try : 0;
           82                         left  = (trx > 0 ? (size_t)trx  : 0) * stream->pixel_size;
           83                         right = (trx < 0 ? (size_t)-trx : 0) * stream->pixel_size;
           84 
           85                         above = MIN(above, stream->height);
           86                         below = MIN(below, stream->height);
           87                         left  = MIN(left,  stream->row_size);
           88                         right = MIN(right, stream->row_size);
           89                 }
           90         } while (process_frame(stream, buf, above, below, left, right));
           91 
           92         free(buf);
           93 }
           94 
           95 static void
           96 process_wrap(struct stream *stream, struct stream *trstream)
           97 {
           98         char *buf, *row;
           99         size_t p = 0;
          100         double *trans, tmp;
          101         ssize_t trx = 0, try = 0, py;
          102         size_t off = 0, y;
          103 
          104         echeck_dimensions(stream, WIDTH | HEIGHT, NULL);
          105         buf = emalloc(stream->frame_size);
          106 
          107         while (eread_frame(stream, buf)) {
          108                 if ((trans = next_pixel(trstream, &p))) {
          109                         trx = (ssize_t)(tmp = round(invtrans ? -trans[0] : trans[0]));
          110                         try = (ssize_t)(tmp = round(invtrans ? -trans[1] : trans[1]));
          111                         trx %= (ssize_t)stream->width;
          112                         if (trx < 0)
          113                                 trx += (ssize_t)stream->width;
          114                         off = (stream->width - (size_t)trx) % stream->width;
          115                         off = off * stream->pixel_size;
          116                 }
          117 
          118                 for (y = 0; y < stream->height; y++) {
          119                         py = ((ssize_t)y - try) % (ssize_t)stream->height;
          120                         if (py < 0)
          121                                 py += (ssize_t)stream->height;
          122                         row = buf + (size_t)py * stream->row_size;
          123                         ewriteall(STDOUT_FILENO, row + off, stream->row_size - off, "<stdout>");
          124                         ewriteall(STDOUT_FILENO, row, off, "<stdout>");
          125                 }
          126         }
          127 
          128         free(buf);
          129 }
          130 
          131 int
          132 main(int argc, char *argv[])
          133 {
          134         struct stream stream;
          135         struct stream trstream;
          136         int wrap = 0;
          137 
          138         ARGBEGIN {
          139         case 'w':
          140                 wrap = 1;
          141                 break;
          142         case 'p':
          143                 invtrans = 1;
          144                 break;
          145         default:
          146                 usage();
          147         } ARGEND;
          148 
          149         if (argc != 1)
          150                 usage();
          151 
          152         eopen_stream(&stream, NULL);
          153         eopen_stream(&trstream, argv[0]);
          154 
          155         if (trstream.width != 1 || trstream.height != 1)
          156                 eprintf("translation-stream does not have 1x1 geometry\n");
          157 
          158         if (strcmp(trstream.pixfmt, "xyza"))
          159                 eprintf("pixel format of translation-stream %s "
          160                         "is not supported, try xyza\n", trstream.pixfmt);
          161 
          162         fprint_stream_head(stdout, &stream);
          163         efflush(stdout, "<stdout>");
          164 
          165         (wrap ? process_wrap : process)(&stream, &trstream);
          166         close(trstream.fd);
          167         return 0;
          168 }