blind-stack.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-stack.c (2685B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include "common.h"
            3 
            4 USAGE("[-bs] bottom-stream ... top-stream")
            5 
            6 #define PROCESS(TYPE, BLEND)\
            7         do {\
            8                 TYPE x1, y1, z1, a1;\
            9                 TYPE x2, y2, z2, a2;\
           10                 size_t i, j;\
           11                 for (i = 0; i < n; i += streams->pixel_size) {\
           12                         x1 = ((TYPE *)(streams[0].buf + i))[0];\
           13                         y1 = ((TYPE *)(streams[0].buf + i))[1];\
           14                         z1 = ((TYPE *)(streams[0].buf + i))[2];\
           15                         a1 = ((TYPE *)(streams[0].buf + i))[3];\
           16                         for (j = 1; j < n_streams; j++) {\
           17                                 x2 = ((TYPE *)(streams[j].buf + i))[0];\
           18                                 y2 = ((TYPE *)(streams[j].buf + i))[1];\
           19                                 z2 = ((TYPE *)(streams[j].buf + i))[2];\
           20                                 a2 = ((TYPE *)(streams[j].buf + i))[3];\
           21                                 if (BLEND)\
           22                                         a2 /= (TYPE)(j + 1);\
           23                                 a1 *= 1 - a2;\
           24                                 x1 = x1 * a1 + x2 * a2;\
           25                                 y1 = y1 * a1 + y2 * a2;\
           26                                 z1 = z1 * a1 + z2 * a2;\
           27                                 a1 += a2;\
           28                         }\
           29                         ((TYPE *)(streams[0].buf + i))[0] = x1;\
           30                         ((TYPE *)(streams[0].buf + i))[1] = y1;\
           31                         ((TYPE *)(streams[0].buf + i))[2] = z1;\
           32                         ((TYPE *)(streams[0].buf + i))[3] = a1;\
           33                 }\
           34         } while (0)
           35 
           36 static void process_lf  (struct stream *streams, size_t n_streams, size_t n) { PROCESS(double, 0); }
           37 static void process_lf_b(struct stream *streams, size_t n_streams, size_t n) { PROCESS(double, 1); }
           38 static void process_f   (struct stream *streams, size_t n_streams, size_t n) { PROCESS(float, 0); }
           39 static void process_f_b (struct stream *streams, size_t n_streams, size_t n) { PROCESS(float, 1); }
           40 
           41 int
           42 main(int argc, char *argv[])
           43 {
           44         struct stream *streams;
           45         size_t n_streams, i, frames = 0, tmp;
           46         int blend = 0, shortest = 0;
           47         void (*process)(struct stream *streams, size_t n_streams, size_t n);
           48 
           49         ARGBEGIN {
           50         case 'b':
           51                 blend = 1;
           52                 break;
           53         case 's':
           54                 shortest = 1;
           55                 frames = SIZE_MAX;
           56                 break;
           57         default:
           58                 usage();
           59         } ARGEND;
           60 
           61         if (argc < 2)
           62                 usage();
           63 
           64         n_streams = (size_t)argc;
           65         streams = ecalloc(n_streams, sizeof(*streams));
           66 
           67         for (i = 0; i < n_streams; i++) {
           68                 eopen_stream(streams + i, argv[i]);
           69                 if (shortest ?
           70                     (streams[i].frames && streams[i].frames < frames) :
           71                     (streams[i].frames || streams[i].frames > frames))
           72                         frames = streams[i].frames;
           73         }
           74 
           75         if (streams->encoding == DOUBLE)
           76                 process = blend ? process_lf_b :process_lf;
           77         else if (streams->encoding == FLOAT)
           78                 process = blend ? process_f_b : process_f;
           79         else
           80                 eprintf("pixel format %s is not supported, try xyza\n", streams->pixfmt);
           81         CHECK_ALPHA_CHAN(streams);
           82         CHECK_N_CHAN(streams, 4, 4);
           83 
           84         tmp = streams->frames, streams->frames = frames;
           85         fprint_stream_head(stdout, streams);
           86         efflush(stdout, "<stdout>");
           87         streams->frames = tmp;
           88         process_multiple_streams(streams, n_streams, STDOUT_FILENO, "<stdout>", shortest, process);
           89 
           90         free(streams);
           91         return 0;
           92 }