Introduction
Introduction Statistics Contact Development Disclaimer Help
blind-kernel.c - blind - suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log
Files
Refs
README
LICENSE
---
blind-kernel.c (9972B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include "common.h"
3
4 USAGE("[-xyza] kernel [parameter] ...")
5
6 #define SUBUSAGE(FORMAT) "usage: %s [-xyza] " FORMAT "\n", argv0
7 #define STRCASEEQ3(A, B1, B2, B3) (!strcasecmp(A, B1) || !strcasecmp(A, …
8 #define STRCASEEQ2(A, B1, B2) (!strcasecmp(A, B1) || !strcasecmp(A, …
9
10 #define LIST_KERNELS\
11 X(kernel_kirsch, "kirsch")\
12 X(kernel_gradient, "gradient")\
13 X(kernel_sobel, "sobel")\
14 X(kernel_emboss, "emboss")\
15 X(kernel_box_blur, "box blur")\
16 X(kernel_sharpen, "sharpen")\
17 X(kernel_gaussian, "gaussian")
18
19 static const double *
20 kernel_kirsch(int argc, char *argv[], size_t *rows, size_t *cols, double…
21 {
22 static const double matrices[][9] = {
23 { 5, 5, 5, -3, 0, -3, -3, -3, -3},
24 { 5, 5, -3, 5, 0, -3, -3, -3, -3},
25 { 5, -3, -3, 5, 0, -3, 5, -3, -3},
26 {-3, -3, -3, 5, 0, -3, 5, 5, -3},
27 {-3, -3, -3, -3, 0, -3, 5, 5, 5},
28 {-3, -3, -3, -3, 0, 5, -3, 5, 5},
29 {-3, -3, 5, -3, 0, 5, -3, -3, 5},
30 {-3, 5, 5, -3, 0, 5, -3, -3, -3},
31 };
32 *free_this = NULL;
33 *rows = *cols = 3;
34 if (argc != 1)
35 eprintf(SUBUSAGE("'kirsch' direction"));
36 if (STRCASEEQ3(argv[0], "1", "N", "N")) return matrices[0];
37 if (STRCASEEQ3(argv[0], "2", "NW", "WN")) return matrices[1];
38 if (STRCASEEQ3(argv[0], "3", "W", "W")) return matrices[2];
39 if (STRCASEEQ3(argv[0], "4", "SW", "WS")) return matrices[3];
40 if (STRCASEEQ3(argv[0], "5", "S", "S")) return matrices[4];
41 if (STRCASEEQ3(argv[0], "6", "SE", "ES")) return matrices[5];
42 if (STRCASEEQ3(argv[0], "7", "E", "E")) return matrices[6];
43 if (STRCASEEQ3(argv[0], "8", "NE", "EN")) return matrices[7];
44 eprintf("unrecognised direction: %s\n", argv[0]);
45 return NULL;
46 }
47
48 static const double *
49 kernel_gradient(int argc, char *argv[], size_t *rows, size_t *cols, doub…
50 {
51 static const double matrices[][9] = {
52 { 1, 1, 1, 0, 0, 0, -1, -1, -1},
53 { 1, 1, 0, 1, 0, -1, 0, -1, -1},
54 { 1, 0, -1, 1, 0, -1, 1, 0, -1},
55 { 0, -1, -1, 1, 0, -1, 1, 1, 0},
56 {-1, -1, -1, 0, 0, 0, 1, 1, 1},
57 {-1, -1, 0, -1, 0, 1, 0, 1, 1},
58 {-1, 0, 1, -1, 0, 1, -1, 0, 1},
59 { 0, 1, 1, -1, 0, 1, -1, -1, 0},
60 };
61 *free_this = NULL;
62 *rows = *cols = 3;
63 if (argc != 1)
64 eprintf(SUBUSAGE("'gradient' direction"));
65 if (STRCASEEQ2(argv[0], "N", "N")) return matrices[0];
66 if (STRCASEEQ2(argv[0], "NW", "WN")) return matrices[1];
67 if (STRCASEEQ2(argv[0], "W", "W")) return matrices[2];
68 if (STRCASEEQ2(argv[0], "SW", "WS")) return matrices[3];
69 if (STRCASEEQ2(argv[0], "S", "H")) return matrices[4];
70 if (STRCASEEQ2(argv[0], "SE", "ES")) return matrices[5];
71 if (STRCASEEQ2(argv[0], "E", "V")) return matrices[6];
72 if (STRCASEEQ2(argv[0], "NE", "EN")) return matrices[7];
73 eprintf("unrecognised direction: %s\n", argv[0]);
74 return NULL;
75 }
76
77 static const double *
78 kernel_sobel(int argc, char *argv[], size_t *rows, size_t *cols, double …
79 {
80 static const double matrices[][9] = {
81 { 1, 2, 1, 0, 0, 0, -1, -2, -1},
82 { 2, 1, 0, 1, 0, -1, 0, -1, -2},
83 { 1, 0, -1, 2, 0, -2, 1, 0, -1},
84 { 0, -1, -2, 1, 0, -1, 2, 1, 0},
85 {-1, -2, -1, 0, 0, 0, 1, 2, 1},
86 {-2, -1, 0, -1, 0, 1, 0, 1, 2},
87 {-1, 0, 1, -2, 0, 2, -1, 0, 1},
88 { 0, 1, 2, -1, 0, 1, -2, -1, 0},
89 };
90 *free_this = NULL;
91 *rows = *cols = 3;
92 if (argc != 1)
93 eprintf(SUBUSAGE("'sobel' direction"));
94 if (STRCASEEQ2(argv[0], "N", "H")) return matrices[0];
95 if (STRCASEEQ2(argv[0], "NW", "WN")) return matrices[1];
96 if (STRCASEEQ2(argv[0], "W", "V")) return matrices[2];
97 if (STRCASEEQ2(argv[0], "SW", "WS")) return matrices[3];
98 if (STRCASEEQ2(argv[0], "S", "S")) return matrices[4];
99 if (STRCASEEQ2(argv[0], "SE", "ES")) return matrices[5];
100 if (STRCASEEQ2(argv[0], "E", "E")) return matrices[6];
101 if (STRCASEEQ2(argv[0], "NE", "EN")) return matrices[7];
102 eprintf("unrecognised direction: %s\n", argv[0]);
103 return NULL;
104 }
105
106 static const double *
107 kernel_emboss(int argc, char *argv[], size_t *rows, size_t *cols, double…
108 {
109 static const double matrices[][9] = {
110 { 1, 2, 1, 0, 1, 0, -1, -2, -1},
111 { 2, 1, 0, 1, 1, -1, 0, -1, -2},
112 { 1, 0, -1, 2, 1, -2, 1, 0, -1},
113 { 0, -1, -2, 1, 1, -1, 2, 1, 0},
114 {-1, -2, -1, 0, 1, 0, 1, 2, 1},
115 {-2, -1, 0, -1, 1, 1, 0, 1, 2},
116 {-1, 0, 1, -2, 1, 2, -1, 0, 1},
117 { 0, 1, 2, -1, 1, 1, -2, -1, 0},
118 };
119 *free_this = NULL;
120 *rows = *cols = 3;
121 if (argc > 1)
122 eprintf(SUBUSAGE("'emboss' [direction]"));
123 if (!argc)
124 return matrices[5];
125 if (STRCASEEQ2(argv[0], "N", "N")) return matrices[0];
126 if (STRCASEEQ2(argv[0], "NW", "WN")) return matrices[1];
127 if (STRCASEEQ2(argv[0], "W", "W")) return matrices[2];
128 if (STRCASEEQ2(argv[0], "SW", "WS")) return matrices[3];
129 if (STRCASEEQ2(argv[0], "S", "S")) return matrices[4];
130 if (STRCASEEQ2(argv[0], "SE", "ES")) return matrices[5];
131 if (STRCASEEQ2(argv[0], "E", "E")) return matrices[6];
132 if (STRCASEEQ2(argv[0], "NE", "EN")) return matrices[7];
133 eprintf("unrecognised direction: %s\n", argv[0]);
134 return NULL;
135 }
136
137 static const double *
138 kernel_box_blur(int argc, char *argv[], size_t *rows, size_t *cols, doub…
139 {
140 size_t sx = 1, sy = 1, i, n;
141 double *cells, value, weight = 0;
142 int have_weight = 0;
143 char *arg;
144 *free_this = NULL;
145 *rows = *cols = 3;
146
147 #define argv0 arg
148 argc++, argv--;
149 ARGBEGIN {
150 case 'w':
151 if (!(arg = ARGF()))
152 goto usage;
153 weight = etolf_flag('w', arg);
154 have_weight = 1;
155 break;
156 default:
157 goto usage;
158 } ARGEND;
159 #undef argv0
160
161 if (argc == 1) {
162 sx = sy = etozu_arg("spread", argv[0], 0, SIZE_MAX / 2);
163 } else if (argc == 2) {
164 sx = etozu_arg("x-spread", argv[0], 0, SIZE_MAX / 2);
165 sy = etozu_arg("y-spread", argv[1], 0, SIZE_MAX / 2);
166 } else if (argc) {
167 goto usage;
168 }
169
170 *rows = 2 * sy + 1;
171 *cols = 2 * sx + 1;
172 *free_this = cells = emalloc3(*rows, *cols, sizeof(double));
173
174 n = (2 * sy + 1) * (2 * sx + 1);
175 value = 1 / (double)n;
176 if (have_weight)
177 value = (1.0 - weight) / (double)(n - 1);
178 for (i = 0; i < n; i++)
179 cells[i] = value;
180 if (have_weight)
181 cells[sy * *cols + sx] = weight;
182 return cells;
183
184 usage:
185 eprintf(SUBUSAGE("'box blur' [-w weight] [spread | x-spread y-sp…
186 return NULL;
187 }
188
189 static const double *
190 kernel_sharpen(int argc, char *argv[], size_t *rows, size_t *cols, doubl…
191 {
192 static const double matrices[][9] = {
193 { 0, -1, 0, -1, 5, -1, 0, -1, 0},
194 {-1, -1, -1, -1, 9, -1, -1, -1, -1}
195 };
196 char *arg;
197 int intensified = 0;
198 *free_this = NULL;
199 *rows = *cols = 3;
200
201 #define argv0 arg
202 (void) arg;
203 argc++, argv--;
204 ARGBEGIN {
205 case 'i':
206 intensified = 1;
207 break;
208 default:
209 goto usage;
210 } ARGEND;
211 #undef argv0
212 if (argc)
213 goto usage;
214
215 return matrices[intensified];
216 usage:
217 eprintf(SUBUSAGE("'sharpen' [-i]"));
218 return NULL;
219 }
220
221 static const double *
222 kernel_gaussian(int argc, char *argv[], size_t *rows, size_t *cols, doub…
223 {
224 size_t spread = 0, y, x;
225 ssize_t xx, yy;
226 int unsharpen = 0, glow = 0;
227 double sigma, value, c, k;
228 char *arg;
229
230 #define argv0 arg
231 argc++, argv--;
232 ARGBEGIN {
233 case 'g':
234 glow = 1;
235 break;
236 case 's':
237 if (!(arg = ARGF()))
238 goto usage;
239 spread = etozu_flag('s', arg, 1, SIZE_MAX / 2);
240 break;
241 case 'u':
242 unsharpen = 1;
243 break;
244 default:
245 goto usage;
246 } ARGEND;
247 #undef argv0
248
249 if (argc != 1 || (unsharpen && glow))
250 goto usage;
251
252 sigma = etolf_arg("standard-deviation", argv[0]);
253
254 if (!spread)
255 spread = (size_t)(sigma * 3.0 + 0.5);
256 *rows = *cols = spread * 2 + 1;
257
258 *free_this = emalloc3(*rows, *cols, sizeof(double));
259
260 k = sigma * sigma * 2.;
261 c = M_PI * k;
262 c = 1.0 / c;
263 k = 1.0 / -k;
264 for (y = 0; y < 2 * spread + 1; y++) {
265 yy = (ssize_t)spread - (ssize_t)y, yy *= yy;
266 for (x = 0; x < 2 * spread + 1; x++) {
267 xx = (ssize_t)spread - (ssize_t)x, xx *= xx;
268 value = (double)(xx + yy) * k;
269 value = exp(value) * c;
270 (*free_this)[y * *cols + x] = value;
271 }
272 }
273
274 if (unsharpen)
275 (*free_this)[spread * *cols + spread] -= 2.0;
276 if (glow)
277 (*free_this)[spread * *cols + spread] += 1;
278
279 return *free_this;
280
281 usage:
282 eprintf(SUBUSAGE("'gaussian' [-s spread] [-g | -u] standard-devi…
283 return NULL;
284 }
285
286 /* TODO more kernels:
287 Edge detection: MATRIX( 1, 0, -1, 0, 0, 0, -1, 0, 1)
288 Edge detection: MATRIX( 0, 1, 0, 1, -4, 1, 0, 1, 0)
289 Edge detection: MATRIX(-1, -1, -1, -1, 8, -1, -1, -1, -1)
290 Edge detection: MATRIX( 0, 0, 0, -1, 2, -1, 0, 0, 0) [H]
291 Edge detection: MATRIX( 0, -1, 0, 0, 2, 0, 0, -1, 0) [V]
292 Edge enhance: MATRIX( 0, 0, 0, -1, 1, 0, 0, 0, 0)
293 */
294
295 int
296 main(int argc, char *argv[])
297 {
298 int id_x = 1, id_y = 1, id_z = 1, id_a = 1;
299 size_t rows, cols, y, x, n;
300 const double *kernel, *kern;
301 double *buffer, *buf, *free_this, id_val;
302
303 ARGBEGIN {
304 case 'x':
305 id_x = 0;
306 break;
307 case 'y':
308 id_y = 0;
309 break;
310 case 'z':
311 id_z = 0;
312 break;
313 case 'a':
314 id_a = 0;
315 break;
316 default:
317 usage();
318 } ARGEND;
319
320 if (!argc)
321 usage();
322
323 if (id_x && id_y && id_z && id_a)
324 id_x = id_y = id_z = id_a = 0;
325
326 if (0);
327 #define X(FUNC, NAME)\
328 else if (!strcmp(argv[0], NAME))\
329 kernel = FUNC(argc - 1, argv + 1, &rows, &cols, &free_th…
330 LIST_KERNELS
331 #undef X
332 else
333 eprintf("unrecognised kernel: %s\n", argv[0]);
334
335 FPRINTF_HEAD(stdout, (size_t)1, cols, rows, "xyza");
336 efflush(stdout, "<stdout>");
337
338 buffer = emalloc2(cols, 4 * sizeof(double));
339 n = cols * 4 * sizeof(double);
340
341 kern = kernel;
342 for (y = 0; y < rows; y++) {
343 buf = buffer;
344 for (x = 0; x < cols; x++) {
345 id_val = (x == cols / 2 && y == rows / 2) ? 1. :…
346 buf[0] = id_x ? id_val : *kern;
347 buf[1] = id_y ? id_val : *kern;
348 buf[2] = id_z ? id_val : *kern;
349 buf[3] = id_a ? id_val : *kern;
350 buf += 4;
351 kern++;
352 }
353 ewriteall(STDOUT_FILENO, buffer, n, "<stdout>");
354 }
355
356 free(buffer);
357 free(free_this);
358 return 0;
359 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.