blind-temporal-mean.c - blind - suckless command-line video editing utility | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
blind-temporal-mean.c (5440B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include "common.h" | |
3 | |
4 USAGE("[-d | -g | -h | -l power-stream | -p power-stream | -v]") | |
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 *stream, void *buffer, void *… | |
9 | |
10 /* | |
11 * X-parameter 1: method enum value | |
12 * X-parameter 2: identifier-friendly name | |
13 * X-parameter 3: images | |
14 * X-parameter 4: action for first frame | |
15 * X-parameter 5: pre-process assignments | |
16 * X-parameter 6: subcell processing | |
17 * X-parameter 7: pre-finalise assignments | |
18 * X-parameter 8: subcell finalisation | |
19 */ | |
20 #define LIST_MEANS(TYPE)\ | |
21 /* [default] arithmetic mean */\ | |
22 X(ARITHMETIC, arithmetic, 1, COPY_FRAME,, *img += *buf,\ | |
23 a = (TYPE)1 / (TYPE)frame, *img *= a)\ | |
24 /* standard deviation */\ | |
25 X(STANDARD_DEVIATION, sd, 2, ZERO_AND_PROCESS_FRAME,, (*img += *… | |
26 a = (TYPE)1 / (TYPE)frame, *img = nnpow((*img - *aux * *aux * … | |
27 /* geometric mean */\ | |
28 X(GEOMETRIC, geometric, 1, COPY_FRAME,, *img *= *buf,\ | |
29 a = (TYPE)1 / (TYPE)frame, *img = nnpow(*img, a))\ | |
30 /* harmonic mean */\ | |
31 X(HARMONIC, harmonic, 1, ZERO_AND_PROCESS_FRAME,, *img += (TYPE)… | |
32 a = (TYPE)frame, *img = a / *img)\ | |
33 /* Lehmer mean */\ | |
34 X(LEHMER, lehmer, 2, ZERO_AND_PROCESS_FRAME,,\ | |
35 (*img += nnpow(*buf, *pows), *aux += nnpow(*buf, *pows - (TYPE… | |
36 /* power mean (Hölder mean) (m = 2 for root square mean; m = 3 … | |
37 X(POWER, power, 1, ZERO_AND_PROCESS_FRAME,, *img += nnpow(*buf, … | |
38 a = (TYPE)1 / (TYPE)frame, *img = a * nnpow(*img, (TYPE)1 / *p… | |
39 /* variance */\ | |
40 X(VARIANCE, variance, 2, ZERO_AND_PROCESS_FRAME,, (*img += *buf … | |
41 a = (TYPE)1 / (TYPE)frame, *img = (*img - *aux * *aux * a) * a) | |
42 | |
43 enum first_frame_action { | |
44 COPY_FRAME, | |
45 PROCESS_FRAME, | |
46 ZERO_AND_PROCESS_FRAME, | |
47 }; | |
48 | |
49 #define X(V, ...) V, | |
50 enum method { LIST_MEANS() }; | |
51 #undef X | |
52 | |
53 static void *powerbuf = NULL; | |
54 | |
55 #define MAKE_PROCESS(PIXFMT, TYPE,\ | |
56 _1, NAME, _3, _4, PRE_PROCESS, PROCESS_SUBCELL, PRE… | |
57 static void\ | |
58 process_##PIXFMT##_##NAME(struct stream *stream, void *buffer, v… | |
59 {\ | |
60 TYPE *buf = buffer, *img = image, a, *pows = powerbuf;\ | |
61 TYPE *aux = (TYPE *)(((char *)image) + stream->frame_siz… | |
62 size_t x, y, z;\ | |
63 if (!buf) {\ | |
64 PRE_FINALISE;\ | |
65 for (z = 0; z < stream->n_chan; z++)\ | |
66 for (y = 0; y < stream->height; y++)\ | |
67 for (x = 0; x < stream->width; x… | |
68 FINALISE_SUBCELL;\ | |
69 } else {\ | |
70 PRE_PROCESS;\ | |
71 for (z = 0; z < stream->n_chan; z++)\ | |
72 for (y = 0; y < stream->height; y++)\ | |
73 for (x = 0; x < stream->width; x… | |
74 PROCESS_SUBCELL;\ | |
75 }\ | |
76 }\ | |
77 (void) aux, (void) a, (void) pows, (void) frame;\ | |
78 } | |
79 #define X(...) MAKE_PROCESS(lf, double, __VA_ARGS__) | |
80 LIST_MEANS(double) | |
81 #undef X | |
82 #define X(...) MAKE_PROCESS(f, float, __VA_ARGS__) | |
83 LIST_MEANS(float) | |
84 #undef X | |
85 #undef MAKE_PROCESS | |
86 | |
87 #define X(ID, NAME, ...) [ID] = process_lf_##NAME, | |
88 static const process_func process_functions_lf[] = { LIST_MEANS() }; | |
89 #undef X | |
90 | |
91 #define X(ID, NAME, ...) [ID] = process_f_##NAME, | |
92 static const process_func process_functions_f[] = { LIST_MEANS() }; | |
93 #undef X | |
94 | |
95 int | |
96 main(int argc, char *argv[]) | |
97 { | |
98 struct stream stream, power; | |
99 void *buf, *img; | |
100 process_func process; | |
101 size_t frames, images; | |
102 enum method method = ARITHMETIC; | |
103 enum first_frame_action first_frame_action; | |
104 const char *power_file = NULL; | |
105 | |
106 ARGBEGIN { | |
107 case 'd': | |
108 method = STANDARD_DEVIATION; | |
109 break; | |
110 case 'g': | |
111 method = GEOMETRIC; | |
112 break; | |
113 case 'h': | |
114 method = HARMONIC; | |
115 break; | |
116 case 'l': | |
117 method = LEHMER; | |
118 power_file = UARGF(); | |
119 break; | |
120 case 'p': | |
121 method = POWER; | |
122 power_file = UARGF(); | |
123 break; | |
124 case 'v': | |
125 method = VARIANCE; | |
126 break; | |
127 default: | |
128 usage(); | |
129 } ARGEND; | |
130 | |
131 if (argc) | |
132 usage(); | |
133 | |
134 #define X(ID, _2, IMAGES, FIRST_FRAME_ACTION, ...)\ | |
135 case ID:\ | |
136 images = IMAGES;\ | |
137 first_frame_action = FIRST_FRAME_ACTION;\ | |
138 break; | |
139 switch (method) { | |
140 LIST_MEANS() | |
141 default: | |
142 abort(); | |
143 } | |
144 #undef X | |
145 | |
146 eopen_stream(&stream, NULL); | |
147 if (power_file != NULL) { | |
148 eopen_stream(&power, power_file); | |
149 echeck_compat(&stream, &power); | |
150 powerbuf = emalloc(power.frame_size); | |
151 if (!eread_frame(&power, powerbuf)) | |
152 eprintf("%s is no frames\n", power_file); | |
153 } | |
154 | |
155 if (stream.encoding == DOUBLE) | |
156 process = process_functions_lf[method]; | |
157 else if (stream.encoding == FLOAT) | |
158 process = process_functions_f[method]; | |
159 else | |
160 eprintf("pixel format %s is not supported, try xyza\n", … | |
161 | |
162 stream.frames = 1; | |
163 echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); | |
164 fprint_stream_head(stdout, &stream); | |
165 efflush(stdout, "<stdout>"); | |
166 buf = emalloc(stream.frame_size); | |
167 if (first_frame_action == ZERO_AND_PROCESS_FRAME) | |
168 img = ecalloc(images, stream.frame_size); | |
169 else | |
170 img = emalloc2(images, stream.frame_size); | |
171 | |
172 frames = 0; | |
173 if (first_frame_action == COPY_FRAME) { | |
174 if (!eread_frame(&stream, img)) | |
175 eprintf("video is no frames\n"); | |
176 frames++; | |
177 } | |
178 for (; eread_frame(&stream, buf); frames++) | |
179 process(&stream, buf, img, frames); | |
180 if (!frames) | |
181 eprintf("video has no frames\n"); | |
182 process(&stream, NULL, img, frames); | |
183 | |
184 ewriteall(STDOUT_FILENO, img, stream.frame_size, "<stdout>"); | |
185 free(buf); | |
186 free(img); | |
187 free(powerbuf); | |
188 return 0; | |
189 } |