blind-invert-matrix.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-invert-matrix.c (3905B)
---
1 /* See LICENSE file for copyright and license details. */
2 #ifndef TYPE
3 #include "common.h"
4
5 USAGE("[-aexyz]")
6
7 static int equal = 0;
8 static int skip_ch[] = {0, 0, 0, 0};
9 static size_t first_included = 0;
10
11 #define FILE "blind-invert-matrix.c"
12 #include "define-functions.h"
13
14 int
15 main(int argc, char *argv[])
16 {
17 struct stream stream;
18 size_t width, x, y, i, row_size;
19 char *buf, *one, *p, *q;
20 void (*process)(struct stream *stream, void *buf);
21
22 ARGBEGIN {
23 case 'a':
24 skip_ch[3] = 1;
25 break;
26 case 'e':
27 equal = 1;
28 break;
29 case 'x':
30 skip_ch[0] = 1;
31 break;
32 case 'y':
33 skip_ch[1] = 1;
34 break;
35 case 'z':
36 skip_ch[2] = 1;
37 break;
38 default:
39 usage();
40 } ARGEND;
41
42 if (argc)
43 usage();
44
45 while (first_included < ELEMENTSOF(skip_ch) && skip_ch[first_included])
46 first_included++;
47 if (first_included == ELEMENTSOF(skip_ch))
48 equal = 0;
49
50 eopen_stream(&stream, NULL);
51 echeck_dimensions(&stream, WIDTH | HEIGHT, NULL);
52 width = stream.width;
53 if (stream.width < stream.height)
54 eprintf("<stdin>: the video must be at least as wide as it is tall\n");
55 else if (stream.width > stream.height)
56 stream.width -= stream.height;
57 fprint_stream_head(stdout, &stream);
58 stream.width = width;
59 efflush(stdout, "<stdout>");
60
61 if (skip_ch[3] && stream.alpha_chan != -1)
62 CHECK_ALPHA_CHAN(&stream);
63 CHECK_N_CHAN(&stream, 1, 4);
64 one = alloca(stream.pixel_size);
65 if (stream.encoding == DOUBLE) {
66 *(double *)one = 1;
67 process = process_lf;
68 } else if (stream.encoding == FLOAT) {
69 *(float *)one = 1;
70 process = process_f;
71 } else {
72 eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
73 }
74
75 for (i = 1; i < stream.n_chan; i++)
76 memcpy(one + i * stream.chan_size, one, stream.chan_size);
77
78 width = stream.width > stream.height ? stream.width : 2 * stream.height;
79 buf = emalloc2(width, stream.col_size);
80 row_size = width * stream.pixel_size;
81
82 while (eread_frame(&stream, buf)) {
83 if (stream.width == stream.height) {
84 for (y = stream.height; y--;) {
85 memmove(buf + y * row_size, buf + y * stream.row_size, stream.row_size);
86 memset(buf + y * row_size + stream.row_size, 0, stream.row_size);
87 memcpy(buf + y * row_size + stream.row_size + y * stream.pixel_size, one, stream.pixel_size);
88 }
89 }
90 if (equal) {
91 process(&stream, buf + first_included * stream.chan_size);
92 for (y = 0; y < stream.height; y++) {
93 for (x = 0; x < stream.width; x++) {
94 p = buf + y * row_size + x * stream.pixel_size + stream.col_size;
95 q = p + first_included * stream.chan_size;
96 for (i = 0; i < stream.n_chan; i++, p += stream.chan_size)
97 if (i != first_included && !skip_ch[i])
98 memcpy(p, q, stream.chan_size);
99 }
100 }
101 } else {
102 for (i = 0; i < stream.n_chan; i++)
103 if (!skip_ch[i])
104 process(&stream, buf + i * stream.chan_size);
105 }
106 for (y = 0; y < stream.height; y++)
107 ewriteall(STDOUT_FILENO, buf + y * row_size + stream.col_size, row_size - stream.col_size, "<stdout>");
108 }
109
110 free(buf);
111 return 0;
112 }
113
114 #else
115
116 #define SUB_ROWS()\
117 do {\
118 p2 = matrix + r2 * cn;\
119 t = p2[r1][0];\
120 for (c = 0; c < cn; c++)\
121 p2[c][0] -= p1[c][0] * t;\
122 } while (0)
123
124 static void
125 PROCESS(struct stream *stream, void *buf)
126 {
127 typedef TYPE pixel_t[4];
128 size_t rn = stream->height, r1, r2, c;
129 size_t cn = stream->width > rn ? stream->width : 2 * rn;
130 pixel_t *matrix = buf, *p1, *p2;
131 TYPE t;
132
133 for (r1 = 0; r1 < rn; r1++) {
134 p1 = matrix + r1 * cn;
135 if (!p1[r1][0]) {
136 for (r2 = r1 + 1; r2 < rn; r2++) {
137 p2 = matrix + r2 * cn;
138 if (p2[r1][0])
139 break;
140 }
141 if (r2 >= rn)
142 eprintf("matrix is not invertable\n");
143 for (c = 0; c < cn; c++)
144 t = p1[c][0], p1[c][0] = p2[c][0], p2[c][0] = t;
145 }
146 t = 1 / p1[r1][0];
147 for (c = 0; c < cn; c++)
148 p1[c][0] *= t;
149 for (r2 = r1 + 1; r2 < rn; r2++)
150 SUB_ROWS();
151 }
152
153 for (r1 = rn; r1--;) {
154 p1 = matrix + r1 * cn;
155 for (r2 = r1; r2--;)
156 SUB_ROWS();
157 }
158 }
159
160 #undef SUB_ROWS
161 #endif