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