blind-colour-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-colour-matrix.c (3441B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include "common.h"
            3 
            4 USAGE("[-F pixel-format] (-z x1 y1 x2 y2 x3 y3 [white-x white-y] | X1 Y1 Z1 X2 Y2 Z2 X3 Y3 Z3 [white-X white-Y white-Z])")
            5 
            6 static void
            7 invert(double M[3][6])
            8 {
            9         size_t r1, r2, i;
           10         double t;
           11         for (r1 = 0; r1 < 3; r1++) {
           12                 if (!M[r1][r1]) {
           13                         for (r2 = r1 + 1; r2 < 3 && !M[r2][r1]; r2++);
           14                         if (r2 >= 3)
           15                                 eprintf("the colour space's rank is less than 3\n");
           16                         for (i = 0; i < 6; i++)
           17                                 t = M[r1][i], M[r1][i] = M[r2][i], M[r2][i] = t;
           18                 }
           19                 t = 1. / M[r1][r1];
           20                 for (i = 0; i < 6; i++)
           21                         M[r1][i] *= t;
           22                 for (r2 = r1 + 1; r2 < 3; r2++)
           23                         for (i = 0, t = M[r2][r1]; i < 6; i++)
           24                                 M[r2][i] -= M[r1][i] * t;
           25         }
           26         for (r1 = 3; --r1;)
           27                 for (r2 = r1; r2--;)
           28                         for (i = 0, t = M[r2][r1]; i < 6; i++)
           29                                 M[r2][i] -= M[r1][i] * t;
           30 }
           31 
           32 int
           33 main(int argc, char *argv[])
           34 {
           35         static struct stream stream = { .width = 3, .height = 3, .frames = 1 };
           36         const char *pixfmt = "xyza";
           37         int ciexyy = 0;
           38         double x[4], y[4], z[4], M[3][6], t;
           39         double Mlf[9 * 4];
           40         float Mf[9 * 4];
           41         size_t i, j;
           42 
           43         ARGBEGIN {
           44         case 'F':
           45                 pixfmt = UARGF();
           46                 break;
           47         case 'z':
           48                 ciexyy = 1;
           49                 break;
           50         default:
           51                 usage();
           52         } ARGEND;
           53 
           54         if (argc != (3 - ciexyy) * 3 && argc != (3 - ciexyy) * 4)
           55                 usage();
           56 
           57         if (ciexyy) {
           58                 x[0] = etolf_arg("x1", argv[0]);
           59                 y[0] = etolf_arg("y1", argv[1]);
           60                 x[1] = etolf_arg("x2", argv[2]);
           61                 y[1] = etolf_arg("y2", argv[3]);
           62                 x[2] = etolf_arg("x3", argv[4]);
           63                 y[2] = etolf_arg("y3", argv[5]);
           64                 x[3] = argc > 6 ? etolf_arg("white-x", argv[6]) : D65_XYY_X;
           65                 y[3] = argc > 6 ? etolf_arg("white-y", argv[7]) : D65_XYY_Y;
           66                 for (i = 0; i < 4; i++) {
           67                         if (y[i]) {
           68                                 z[i] = (1. - x[i] - y[i]) / y[i];
           69                                 x[i] /= y[i];
           70                                 y[i] = 1.;
           71                         } else {
           72                                 x[i] = y[i] = z[i] = 1.;
           73                         }
           74                 }
           75         } else {
           76                 x[0] = etolf_arg("X1", argv[0]);
           77                 y[0] = etolf_arg("Y1", argv[1]);
           78                 z[0] = etolf_arg("Z1", argv[2]);
           79                 x[1] = etolf_arg("X2", argv[3]);
           80                 y[1] = etolf_arg("Y2", argv[4]);
           81                 z[1] = etolf_arg("Z2", argv[5]);
           82                 x[2] = etolf_arg("X3", argv[6]);
           83                 y[2] = etolf_arg("Y3", argv[7]);
           84                 z[2] = etolf_arg("Z3", argv[8]);
           85                 x[3] = argc > 9 ? etolf_arg("white-X", argv[9])  : D65_XYZ_X;
           86                 y[3] = argc > 9 ? etolf_arg("white-Y", argv[10]) : 1;
           87                 z[3] = argc > 9 ? etolf_arg("white-Z", argv[11]) : D65_XYZ_Z;
           88         }
           89 
           90         for (i = 0; i < 3; i++) {
           91                 M[0][i] = x[i];
           92                 M[1][i] = y[i];
           93                 M[2][i] = z[i];
           94                 M[i][3] = M[i][4] = M[i][5] = 0.;
           95                 M[i][3 + i] = 1.;
           96         }
           97 
           98         invert(M);
           99 
          100         for (i = 0; i < 3; i++) {
          101                 t = M[i][3] * x[3] + M[i][4] * y[3] + M[i][5] * z[3];
          102                 M[0][i] = t * x[i];
          103                 M[1][i] = t * y[i];
          104                 M[2][i] = t * z[i];
          105         }
          106 
          107         for (i = 0; i < 3; i++) {
          108                 M[i][3] = M[i][4] = M[i][5] = 0.;
          109                 M[i][3 + i] = 1.;
          110         }
          111 
          112         invert(M);
          113 
          114         eset_pixel_format(&stream, pixfmt);
          115         fprint_stream_head(stdout, &stream);
          116         efflush(stdout, "<stdout>");
          117 
          118         for (i = 0; i < 3; i++) {
          119                 for (j = 0; j < 3; j++) {
          120                         Mlf[i * 12 + j * 4 + 0] = M[i][3 + j];
          121                         Mlf[i * 12 + j * 4 + 1] = M[i][3 + j];
          122                         Mlf[i * 12 + j * 4 + 2] = M[i][3 + j];
          123                         Mlf[i * 12 + j * 4 + 3] = 1.;
          124                 }
          125         }
          126 
          127         CHECK_ALPHA_CHAN(&stream);
          128         CHECK_COLOUR_SPACE(&stream, CIEXYZ);
          129         if (stream.encoding == DOUBLE) {
          130                 ewriteall(STDOUT_FILENO, Mlf, sizeof(Mlf), "<stdout>");
          131         } else if (stream.encoding == FLOAT) {
          132                 for (i = 0; i < ELEMENTSOF(Mlf); i++)
          133                         Mf[i] = (float)Mlf[i];
          134                 ewriteall(STDOUT_FILENO, Mf, sizeof(Mf), "<stdout>");
          135         } else {
          136                 eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
          137         }
          138 
          139         return 0;
          140 }