blind-arithm.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-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 disgusting. */
9 typedef void (*process_func)(struct stream *streams, size_t n_streams, size_t n);
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_streams, size_t n)\
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); k < n; k += 4 * sizeof(TYPE))\
39 P(j - 1, j, ALGO, TYPE);\
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); k < n; k += 4 * sizeof(TYPE))\
45 P(0, j, ALGO, TYPE);\
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", streams->pixfmt);
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, "<stdout>", 1, process);
123 return 0;
124 }