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 }