blind-make-kernel.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-make-kernel.c (3372B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include "common.h"
3
4 USAGE("[-d denominator] ... [-nxyza] [-- value ...] ...")
5
6 static void
7 new_row(double **kernel, size_t *col, size_t *rows, size_t *cols)
8 {
9 if (!*col)
10 return;
11 if (*rows && *col != *cols)
12 eprintf("the rows in the matrix do not have the same number of columns\n");
13 *kernel = erealloc3(*kernel, 1 + ++*rows, *cols = *col, sizeof(**kernel));
14 *col = 0;
15 }
16
17 static void
18 new_col(char *arg, double **kernel, size_t *col, size_t *rows, size_t *cols)
19 {
20 if (*rows && *col >= *cols)
21 eprintf("the rows in the matrix do not have the same number of columns\n");
22 if (!*rows)
23 *kernel = erealloc2(*kernel, *col + 1, sizeof(**kernel));
24 if (tolf(arg, &(*kernel)[*rows * *cols + (*col)++]))
25 eprintf("matrix cell values must be floating-point values\n");
26 }
27
28 static void
29 finalise(double **kernel, size_t col, size_t *rows, size_t *cols)
30 {
31 if (col)
32 new_row(kernel, &col, rows, cols);
33 if (!*rows)
34 eprintf("the matrix cannot be null-sized\n");
35 }
36
37 static double *
38 read_matrix_cmdline(char *args[], size_t *rows, size_t *cols)
39 {
40 size_t col = 0;
41 double *kernel = NULL;
42 *rows = *cols = 0;
43 for (; *args; args++) {
44 if (!strcmp(*args, "--"))
45 new_row(&kernel, &col, rows, cols);
46 else
47 new_col(*args, &kernel, &col, rows, cols);
48 }
49 finalise(&kernel, col, rows, cols);
50 return kernel;
51 }
52
53 static double *
54 read_matrix_stdin(size_t *rows, size_t *cols)
55 {
56 char *line = NULL, *p, *q;
57 size_t size = 0, col = 0;
58 double *kernel = NULL;
59 ssize_t len;
60 *rows = *cols = 0;
61 while ((len = getline(&line, &size, stdin)) >= 0) {
62 col = 0;
63 for (p = line;; p = q) {
64 while (*p && isspace(*p)) p++;
65 if (!*(q = p))
66 break;
67 while (*q && !isspace(*q)) q++;
68 *q++ = '\0';
69 new_col(p, &kernel, &col, rows, cols);
70 }
71 new_row(&kernel, &col, rows, cols);
72 }
73 free(line);
74 if (ferror(stdout))
75 eprintf("getline:");
76 finalise(&kernel, col, rows, cols);
77 return kernel;
78 }
79
80 int
81 main(int argc, char *argv[])
82 {
83 int normalise = 0;
84 double denominator = 1;
85 int id_x = 1, id_y = 1, id_z = 1, id_a = 1;
86 size_t rows, cols, y, x, n;
87 double *kernel, *kern, sum = 0, value;
88 double *buffer, *buf, id_val;
89
90 ARGBEGIN {
91 case 'd':
92 denominator *= etolf_flag('d', UARGF());
93 break;
94 case 'n':
95 normalise = 1;
96 break;
97 case 'x':
98 id_x = 0;
99 break;
100 case 'y':
101 id_y = 0;
102 break;
103 case 'z':
104 id_z = 0;
105 break;
106 case 'a':
107 id_a = 0;
108 break;
109 default:
110 usage();
111 } ARGEND;
112
113 if (id_x && id_y && id_z && id_a)
114 id_x = id_y = id_z = id_a = 0;
115
116 if (argc)
117 kernel = read_matrix_cmdline(argv, &rows, &cols);
118 else
119 kernel = read_matrix_stdin(&rows, &cols);
120
121 FPRINTF_HEAD(stdout, (size_t)1, cols, rows, "xyza");
122 efflush(stdout, "<stdout>");
123
124 buffer = emalloc2(cols, 4 * sizeof(double));
125 n = cols * 4 * sizeof(double);
126
127 if (normalise) {
128 kern = kernel;
129 for (y = 0; y < rows; y++)
130 for (x = 0; x < cols; x++)
131 sum += *kern++;
132 denominator *= sum;
133 }
134
135 kern = kernel;
136 for (y = 0; y < rows; y++) {
137 buf = buffer;
138 for (x = 0; x < cols; x++) {
139 id_val = (x == cols / 2 && y == rows / 2) ? 1. : 0.;
140 value = *kern++ / denominator;
141 buf[0] = id_x ? id_val : value;
142 buf[1] = id_y ? id_val : value;
143 buf[2] = id_z ? id_val : value;
144 buf[3] = id_a ? id_val : value;
145 buf += 4;
146 }
147 ewriteall(STDOUT_FILENO, buffer, n, "<stdout>");
148 }
149
150 free(kernel);
151 free(buffer);
152 return 0;
153 }