blind-mean.c - blind - suckless command-line video editing utility | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
blind-mean.c (5615B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include "common.h" | |
3 | |
4 USAGE("[-d | -g | -h | -H | -i | -l power-stream | -L | -p power-stream … | |
5 /* TODO add [-w weight-stream] for [-ghlpv] */ | |
6 | |
7 /* Because the syntax for a function returning a function pointer is dis… | |
8 typedef void (*process_func)(struct stream *streams, size_t n_streams, s… | |
9 | |
10 /* | |
11 * X-parameter 1: method enum value | |
12 * X-parameter 2: identifier-friendly name | |
13 * X-parameter 3: initial assignments | |
14 * X-parameter 4: initial value | |
15 * X-parameter 5: subcell processing | |
16 * X-parameter 6: subcell finalisation | |
17 */ | |
18 #define LIST_MEANS(TYPE)\ | |
19 /* [default] arithmetic mean */\ | |
20 X(ARITHMETIC, arithmetic, sn = (TYPE)1 / sn, 0, img += val, img … | |
21 /* standard deviation */\ | |
22 X(STANDARD_DEVIATION, sd, sn = (TYPE)1 / sn, 0, (img += val * va… | |
23 img = nnpow((img - aux * aux * sn) * sn, (TYPE)0.5))\ | |
24 /* geometric mean */\ | |
25 X(GEOMETRIC, geometric, sn = (TYPE)1 / sn, 1, img *= val, img = … | |
26 /* harmonic mean */\ | |
27 X(HARMONIC, harmonic,, 0, img += (TYPE)1 / val, img = sn / img)\ | |
28 /* Heronian mean */\ | |
29 X(HERONIAN, heronian,, 0, auxs[j] = val,\ | |
30 img = (auxs[0] + sqrt(auxs[0] * auxs[1]) + auxs[1]) / (TYPE)3)\ | |
31 /* identric mean */\ | |
32 X(IDENTRIC, identric, a = (TYPE)(1. / M_E), 0, auxs[j] = val,\ | |
33 img = auxs[0] == auxs[1] ? auxs[0] :\ | |
34 nnpow(nnpow(auxs[0], auxs[0]) / nnpow(auxs[1], auxs[1]),… | |
35 /* Lehmer mean */\ | |
36 X(LEHMER, lehmer,, 0, (img += nnpow(val, *pows), aux += nnpow(va… | |
37 /* logarithmic mean */\ | |
38 X(LOGARITHMIC, logarithmic,, 0, auxs[j] = val,\ | |
39 img = auxs[0] == auxs[1] ? auxs[0] : (!auxs[0] || !auxs[1]) ? … | |
40 (auxs[1] - auxs[0]) / log(auxs[1] / auxs[0]))\ | |
41 /* power mean (Hölder mean) (m = 2 for root square mean; m = 3 … | |
42 X(POWER, power, sn = (TYPE)1 / sn, 0,\ | |
43 img += nnpow(val, *pows), img = nnpow(img, (TYPE)1 / *pows) * … | |
44 /* Stolarsky mean */\ | |
45 X(STOLARSKY, stolarsky,, 0, auxs[j] = val,\ | |
46 img = auxs[0] == auxs[1] ? auxs[0] :\ | |
47 nnpow((nnpow(auxs[0], *pows) - nnpow(auxs[1], *pows)) /\ | |
48 (*pows * (auxs[0] - auxs[1])), (TYPE)1 / (*pows - … | |
49 /* variance */\ | |
50 X(VARIANCE, variance, sn = (TYPE)1 / sn, 0, (img += val * val, a… | |
51 img = (img - aux * aux * sn) * sn)\ | |
52 /* Heinz mean */\ | |
53 X(HEINZ, heinz,, 0, auxs[j] = val,\ | |
54 img = (nnpow(auxs[0], *pows) * nnpow(auxs[1], (TYPE)1 - *pows)… | |
55 nnpow(auxs[0], (TYPE)1 - *pows) * nnpow(auxs[1], *pows)… | |
56 | |
57 #define X(V, ...) V, | |
58 enum method { LIST_MEANS() }; | |
59 #undef X | |
60 | |
61 static const char *power_file = NULL; | |
62 | |
63 #define aux (*auxs) | |
64 #define MAKE_PROCESS(PIXFMT, TYPE,\ | |
65 _1, NAME, INIT, INITIAL, PROCESS_SUBCELL, FINALISE_SUBCELL)\ | |
66 static void\ | |
67 process_##PIXFMT##_##NAME(struct stream *streams, size_t n_strea… | |
68 {\ | |
69 size_t i, j;\ | |
70 TYPE img, auxs[2], val, a, sn;\ | |
71 TYPE *pows = power_file ? (TYPE *)(streams[n_streams - 1… | |
72 n_streams -= (size_t)!!power_file;\ | |
73 sn = (TYPE)n_streams;\ | |
74 INIT;\ | |
75 for (i = 0; i < n; i += sizeof(TYPE), pows++) {\ | |
76 img = auxs[0] = auxs[1] = INITIAL;\ | |
77 for (j = 0; j < n_streams; j++) {\ | |
78 val = *(TYPE *)(streams[j].buf + i);\ | |
79 PROCESS_SUBCELL;\ | |
80 }\ | |
81 FINALISE_SUBCELL;\ | |
82 *(TYPE *)(streams->buf + i) = img;\ | |
83 }\ | |
84 (void) aux, (void) a, (void) pows, (void) sn;\ | |
85 } | |
86 #define X(...) MAKE_PROCESS(lf, double, __VA_ARGS__) | |
87 LIST_MEANS(double) | |
88 #undef X | |
89 #define X(...) MAKE_PROCESS(f, float, __VA_ARGS__) | |
90 LIST_MEANS(float) | |
91 #undef X | |
92 #undef MAKE_PROCESS | |
93 #undef aux | |
94 | |
95 #define X(ID, NAME, ...) [ID] = process_lf_##NAME, | |
96 static const process_func process_functions_lf[] = { LIST_MEANS() }; | |
97 #undef X | |
98 | |
99 #define X(ID, NAME, ...) [ID] = process_f_##NAME, | |
100 static const process_func process_functions_f[] = { LIST_MEANS() }; | |
101 #undef X | |
102 | |
103 int | |
104 main(int argc, char *argv[]) | |
105 { | |
106 struct stream *streams; | |
107 process_func process; | |
108 size_t frames = SIZE_MAX, tmp; | |
109 enum method method = ARITHMETIC; | |
110 int i, two = 0; | |
111 | |
112 ARGBEGIN { | |
113 case 'd': | |
114 method = STANDARD_DEVIATION; | |
115 break; | |
116 case 'g': | |
117 method = GEOMETRIC; | |
118 break; | |
119 case 'h': | |
120 method = HARMONIC; | |
121 break; | |
122 case 'H': | |
123 method = HERONIAN; | |
124 two = 1; | |
125 break; | |
126 case 'i': | |
127 method = IDENTRIC; | |
128 two = 1; | |
129 break; | |
130 case 'l': | |
131 method = LEHMER; | |
132 power_file = UARGF(); | |
133 break; | |
134 case 'L': | |
135 method = LOGARITHMIC; | |
136 two = 1; | |
137 break; | |
138 case 'p': | |
139 method = POWER; | |
140 power_file = UARGF(); | |
141 break; | |
142 case 's': | |
143 method = STOLARSKY; | |
144 two = 1; | |
145 power_file = UARGF(); | |
146 break; | |
147 case 'v': | |
148 method = VARIANCE; | |
149 break; | |
150 case 'z': | |
151 method = HEINZ; | |
152 two = 1; | |
153 power_file = UARGF(); | |
154 break; | |
155 default: | |
156 usage(); | |
157 } ARGEND; | |
158 | |
159 if (argc < 2 || (argc > 2 && two)) | |
160 usage(); | |
161 | |
162 streams = alloca((size_t)(argc + !!power_file) * sizeof(*streams… | |
163 for (i = 0; i < argc; i++) { | |
164 eopen_stream(streams + i, argv[i]); | |
165 if (streams[i].frames && streams[i].frames < frames) | |
166 frames = streams[i].frames; | |
167 } | |
168 if (power_file != NULL) | |
169 eopen_stream(streams + argc, power_file); | |
170 | |
171 if (streams->encoding == DOUBLE) | |
172 process = process_functions_lf[method]; | |
173 else if (streams->encoding == FLOAT) | |
174 process = process_functions_f[method]; | |
175 else | |
176 eprintf("pixel format %s is not supported, try xyza\n", … | |
177 | |
178 tmp = streams->frames, streams->frames = frames; | |
179 fprint_stream_head(stdout, streams); | |
180 efflush(stdout, "<stdout>"); | |
181 streams->frames = tmp; | |
182 process_multiple_streams(streams, (size_t)(argc + !!power_file), | |
183 STDOUT_FILENO, "<stdout>", 1, process); | |
184 return 0; | |
185 } |