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