blind-arithm.c - blind - suckless command-line video editing utility | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
blind-arithm.c (3393B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include "common.h" | |
3 | |
4 USAGE("[-axyz] operation right-hand-stream ...") | |
5 | |
6 static int skip_ch[4] = {0, 0, 0, 0}; | |
7 | |
8 /* Because the syntax for a function returning a function pointer is dis… | |
9 typedef void (*process_func)(struct stream *streams, size_t n_streams, s… | |
10 | |
11 #define LIST_OPERATORS(PIXFMT, TYPE)\ | |
12 X(add, 0, *lh += rh, PIXFMT, TYPE)\ | |
13 X(sub, 0, *lh -= rh, PIXFMT, TYPE)\ | |
14 X(mul, 0, *lh *= rh, PIXFMT, TYPE)\ | |
15 X(div, 0, *lh /= rh, PIXFMT, TYPE)\ | |
16 X(mod, 0, *lh = posmod(*lh, rh), PIXFMT, TYPE)\ | |
17 X(exp, 1, *lh = pow(*lh, rh), PIXFMT, TYPE)\ | |
18 X(log, 0, *lh = log2(*lh) / log2(rh), PIXFMT, TYPE)\ | |
19 X(min, 0, *lh = MIN(*lh, rh), PIXFMT, TYPE)\ | |
20 X(max, 0, *lh = MAX(*lh, rh), PIXFMT, TYPE)\ | |
21 X(abs, 0, *lh = abs(*lh - rh) + rh, PIXFMT, TYPE) | |
22 | |
23 #define P(L, R, ALGO, TYPE)\ | |
24 (lh = (TYPE *)(streams[L].buf + k),\ | |
25 rh = *((TYPE *)(streams[R].buf + k)),\ | |
26 (ALGO)) | |
27 | |
28 #define X(NAME, RTL, ALGO, PIXFMT, TYPE)\ | |
29 static void\ | |
30 process_##PIXFMT##_##NAME(struct stream *streams, size_t n_strea… | |
31 {\ | |
32 size_t i, j, k;\ | |
33 TYPE *lh, rh;\ | |
34 if (RTL) {\ | |
35 for (i = 0; i < streams->n_chan; i++)\ | |
36 if (!skip_ch[i])\ | |
37 for (j = n_streams; --j;)\ | |
38 for (k = i * sizeof(TYPE… | |
39 P(j - 1, j, ALGO… | |
40 } else {\ | |
41 for (i = 0; i < streams->n_chan; i++)\ | |
42 if (!skip_ch[i])\ | |
43 for (j = 1; j < n_streams; j++)\ | |
44 for (k = i * sizeof(TYPE… | |
45 P(0, j, ALGO, TY… | |
46 }\ | |
47 } | |
48 LIST_OPERATORS(lf, double) | |
49 LIST_OPERATORS(f, float) | |
50 #undef X | |
51 | |
52 static process_func | |
53 get_process_lf(const char *operation) | |
54 { | |
55 #define X(NAME, _RTL, _ALGO, PIXFMT, _TYPE)\ | |
56 if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME; | |
57 LIST_OPERATORS(lf, double) | |
58 #undef X | |
59 eprintf("algorithm not recognised: %s\n", operation); | |
60 return NULL; | |
61 } | |
62 | |
63 static process_func | |
64 get_process_f(const char *operation) | |
65 { | |
66 #define X(NAME, _RTL, _ALGO, PIXFMT, _TYPE)\ | |
67 if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME; | |
68 LIST_OPERATORS(f, float) | |
69 #undef X | |
70 eprintf("algorithm not recognised: %s\n", operation); | |
71 return NULL; | |
72 } | |
73 | |
74 int | |
75 main(int argc, char *argv[]) | |
76 { | |
77 struct stream *streams; | |
78 process_func process; | |
79 const char *operation; | |
80 size_t frames = SIZE_MAX, tmp; | |
81 int i; | |
82 | |
83 ARGBEGIN { | |
84 case 'a': | |
85 skip_ch[3] = 1; | |
86 break; | |
87 case 'x': | |
88 case 'y': | |
89 case 'z': | |
90 skip_ch[ARGC() - 'x'] = 1; | |
91 break; | |
92 default: | |
93 usage(); | |
94 } ARGEND; | |
95 | |
96 if (argc < 2) | |
97 usage(); | |
98 | |
99 operation = *argv; | |
100 streams = alloca((size_t)argc * sizeof(*streams)); | |
101 *argv = NULL; | |
102 for (i = 0; i < argc; i++) { | |
103 eopen_stream(streams + i, argv[i]); | |
104 if (streams[i].frames && streams[i].frames < frames) | |
105 frames = streams[i].frames; | |
106 } | |
107 | |
108 if (streams->alpha) | |
109 CHECK_ALPHA(streams); | |
110 CHECK_N_CHAN(streams, 1, 3 + !!streams->alpha); | |
111 if (streams->encoding == DOUBLE) | |
112 process = get_process_lf(operation); | |
113 else if (streams->encoding == FLOAT) | |
114 process = get_process_f(operation); | |
115 else | |
116 eprintf("pixel format %s is not supported, try xyza\n", … | |
117 | |
118 tmp = streams->frames, streams->frames = frames; | |
119 fprint_stream_head(stdout, streams); | |
120 efflush(stdout, "<stdout>"); | |
121 streams->frames = tmp; | |
122 process_multiple_streams(streams, (size_t)argc, STDOUT_FILENO, "… | |
123 return 0; | |
124 } |