blind-invert-matrix.c - blind - suckless command-line video editing utility | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
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_inc… | |
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 … | |
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", … | |
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… | |
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 * st… | |
86 memset(buf + y * row_size + stream.row_s… | |
87 memcpy(buf + y * row_size + stream.row_s… | |
88 } | |
89 } | |
90 if (equal) { | |
91 process(&stream, buf + first_included * stream.c… | |
92 for (y = 0; y < stream.height; y++) { | |
93 for (x = 0; x < stream.width; x++) { | |
94 p = buf + y * row_size + x * str… | |
95 q = p + first_included * stream.… | |
96 for (i = 0; i < stream.n_chan; i… | |
97 if (i != first_included … | |
98 memcpy(p, q, str… | |
99 } | |
100 } | |
101 } else { | |
102 for (i = 0; i < stream.n_chan; i++) | |
103 if (!skip_ch[i]) | |
104 process(&stream, buf + i * strea… | |
105 } | |
106 for (y = 0; y < stream.height; y++) | |
107 ewriteall(STDOUT_FILENO, buf + y * row_size + st… | |
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]… | |
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 |