Add blind-colour-matrix, and blind-invert-matrix: fix -e and add -axyz - blind … | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 698481451a63e0bd81aeb1ad3bf794ce7aaadef2 | |
parent ebe2e88b44f46e59bdefef1eb585078d5fa6d4d4 | |
Author: Mattias Andrée <[email protected]> | |
Date: Sun, 23 Jul 2017 12:00:07 +0200 | |
Add blind-colour-matrix, and blind-invert-matrix: fix -e and add -axyz | |
Signed-off-by: Mattias Andrée <[email protected]> | |
Diffstat: | |
M Makefile | 1 + | |
M README | 5 ++++- | |
M TODO | 1 - | |
M man/blind-colour-ciexyz.1 | 1 + | |
M man/blind-colour-srgb.1 | 3 ++- | |
M man/blind-invert-matrix.1 | 14 +++++++++++++- | |
M man/blind.7 | 5 +++++ | |
A src/blind-colour-matrix.c | 130 +++++++++++++++++++++++++++++… | |
M src/blind-invert-matrix.c | 38 ++++++++++++++++++++++++-----… | |
9 files changed, 186 insertions(+), 12 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
@@ -11,6 +11,7 @@ BIN =\ | |
blind-cat-rows\ | |
blind-chroma-key\ | |
blind-colour-ciexyz\ | |
+ blind-colour-matrix\ | |
blind-colour-srgb\ | |
blind-compress\ | |
blind-concat\ | |
diff --git a/README b/README | |
@@ -36,8 +36,11 @@ UTILITIES | |
blind-colour-ciexyz(1) | |
Convert CIE XYZ for use with blind-single-colour(1) | |
+ blind-colour-matrix(1) | |
+ Create colour space conversion matrix | |
+ | |
blind-colour-srgb(1) | |
- Convert sRGB for use with blind-single-colour(1) | |
+ Convert sRGB for use with blind-single-colour(1) and colour-colo… | |
blind-concat(1) | |
Concatenate videos | |
diff --git a/TODO b/TODO | |
@@ -1,7 +1,6 @@ | |
blind-transform affine transformation by matrix multiplication,… | |
improve quality on downscaling (pixels' neighb… | |
blind-primary-key replace a primary with transparency, -g for greyscale… | |
-blind-colour-matrix create colour space conversion matrix | |
blind-apply-map remap pixels (distortion) using the X and Y val… | |
improve quality on downscaling (pixels' neighb… | |
blind-find-frame a graphical tool for locating frames, should highlight… | |
diff --git a/man/blind-colour-ciexyz.1 b/man/blind-colour-ciexyz.1 | |
@@ -24,6 +24,7 @@ with a luminosity of | |
.SH SEE ALSO | |
.BR blind (7), | |
.BR blind-single-colour (1), | |
+.BR blind-colour-matrix (1), | |
.BR blind-colour-srgb (1) | |
.SH AUTHORS | |
Mattias Andrée | |
diff --git a/man/blind-colour-srgb.1 b/man/blind-colour-srgb.1 | |
@@ -1,6 +1,6 @@ | |
.TH BLIND-COLOUR-SRGB 1 blind | |
.SH NAME | |
-blind-colour-srgb - Convert sRGB for use with blind-single-colour(1) | |
+blind-colour-srgb - Convert sRGB for use with blind-single-colour(1) and blind… | |
.SH SYNOPSIS | |
.B blind-colour-srgb | |
[-d | |
@@ -49,6 +49,7 @@ the sRGB transfer function. | |
.SH SEE ALSO | |
.BR blind (7), | |
.BR blind-single-colour (1), | |
+.BR blind-colour-matrix (1), | |
.BR blind-colour-ciexyz (1) | |
.SH AUTHORS | |
Mattias Andrée | |
diff --git a/man/blind-invert-matrix.1 b/man/blind-invert-matrix.1 | |
@@ -3,7 +3,7 @@ | |
blind-invert-matrix - Invert matrix-vidoes | |
.SH SYNOPSIS | |
.B blind-invert-matrix | |
-[-e] | |
+[-aexyz] | |
.SH DESCRIPTION | |
.B blind-invert-matrix | |
reads a video representing a matrix from | |
@@ -18,9 +18,21 @@ eliminated to the identity matrix and the | |
resuling augment is printed. | |
.SH OPTIONS | |
.TP | |
+.B -a | |
+Ignore the alpha channel. | |
+.TP | |
.B -e | |
Apply optimisation that assumes all channels | |
are identical. | |
+.TP | |
+.B -x | |
+Ignore the first channel (the X channel). | |
+.TP | |
+.B -y | |
+Ignore the second channel (the Y channel). | |
+.TP | |
+.B -z | |
+Ignore the third channel (the Z channel). | |
.SH SEE ALSO | |
.BR blind (7), | |
.BR blind-multiply-matrices (1), | |
diff --git a/man/blind.7 b/man/blind.7 | |
@@ -44,9 +44,14 @@ Replace a colour range with transparency | |
Convert CIE XYZ for use with | |
.BR blind-single-colour (1) | |
.TP | |
+.BR blind-colour-matrix(1) | |
+Create colour space conversion matrix | |
+.TP | |
.BR blind-colour-srgb (1) | |
Convert sRGB for use with | |
.BR blind-single-colour (1) | |
+and | |
+.BR colour-colour-matrix (1) | |
.TP | |
.BR blind-compress (1) | |
Compress a video for network transmission | |
diff --git a/src/blind-colour-matrix.c b/src/blind-colour-matrix.c | |
@@ -0,0 +1,130 @@ | |
+/* See LICENSE file for copyright and license details. */ | |
+#include "common.h" | |
+ | |
+USAGE("[-F pixel-format] (-z x1 y1 x2 y2 x3 y3 white-x white-y | X1 Y1 Z1 X2 Y… | |
+ | |
+int | |
+main(int argc, char *argv[]) | |
+{ | |
+ static struct stream stream = { .width = 3, .height = 3, .frames = 1 }; | |
+ const char *pixfmt = "xyza"; | |
+ int ciexyy = 0; | |
+ double x[4], y[4], z[4], M[3][6], t; | |
+ double Mlf[9 * 4]; | |
+ float Mf[9 * 4]; | |
+ size_t i, j, r1, r2; | |
+ | |
+ ARGBEGIN { | |
+ case 'F': | |
+ pixfmt = UARGF(); | |
+ break; | |
+ case 'z': | |
+ ciexyy = 1; | |
+ break; | |
+ default: | |
+ usage(); | |
+ } ARGEND; | |
+ | |
+ if (argc != (3 - ciexyy) * 3 && argc != (3 - ciexyy) * 4) | |
+ usage(); | |
+ | |
+ if (ciexyy) { | |
+ x[0] = etolf_arg("x1", argv[0]); | |
+ y[0] = etolf_arg("y1", argv[1]); | |
+ x[1] = etolf_arg("x2", argv[2]); | |
+ y[1] = etolf_arg("y2", argv[3]); | |
+ x[2] = etolf_arg("x3", argv[4]); | |
+ y[2] = etolf_arg("y3", argv[5]); | |
+ x[3] = argc > 6 ? etolf_arg("white-x", argv[6]) : D65_XYY_X; | |
+ y[3] = argc > 6 ? etolf_arg("white-y", argv[7]) : D65_XYY_Y; | |
+ for (i = 0; i < 4; i++) { | |
+ if (y[i]) { | |
+ z[i] = (1. - x[i] - y[i]) / y[i]; | |
+ x[i] /= y[i]; | |
+ y[i] = 1.; | |
+ } else { | |
+ x[i] = y[i] = z[i] = 1.; | |
+ } | |
+ } | |
+ } else { | |
+ x[0] = etolf_arg("X1", argv[0]); | |
+ y[0] = etolf_arg("Y1", argv[1]); | |
+ z[0] = etolf_arg("Z1", argv[2]); | |
+ x[1] = etolf_arg("X2", argv[3]); | |
+ y[1] = etolf_arg("Y2", argv[4]); | |
+ z[1] = etolf_arg("Z2", argv[5]); | |
+ x[2] = etolf_arg("X3", argv[6]); | |
+ y[2] = etolf_arg("Y3", argv[7]); | |
+ z[2] = etolf_arg("Z3", argv[8]); | |
+ x[3] = argc > 9 ? etolf_arg("white-X", argv[9]) : D65_XYZ_X; | |
+ y[3] = argc > 9 ? etolf_arg("white-Y", argv[10]) : 1; | |
+ z[3] = argc > 9 ? etolf_arg("white-Z", argv[11]) : D65_XYZ_Z; | |
+ for (i = 0; i < 4; i++) { | |
+ if (y[i] && y[i] != 1.) { | |
+ x[i] /= y[i]; | |
+ z[i] /= y[i]; | |
+ y[i] = 1.; | |
+ } else if (!y[i]) { | |
+ x[i] = y[i] = z[i] = 0.; | |
+ } | |
+ } | |
+ } | |
+ | |
+ for (i = 0; i < 3; i++) { | |
+ M[0][i] = x[i]; | |
+ M[1][i] = y[i]; | |
+ M[2][i] = z[i]; | |
+ M[i][3] = M[i][4] = M[i][5] = 0.; | |
+ M[i][3 + i] = 1.; | |
+ } | |
+ | |
+ for (r1 = 0; r1 < 3; r1++) { | |
+ if (!M[r1][r1]) { | |
+ for (r2 = r1 + 1; r2 < 3 && !M[r2][r1]; r2++); | |
+ if (r2 >= 3) | |
+ eprintf("the colour space's rank is less than … | |
+ for (i = 0; i < 6; i++) | |
+ t = M[r1][i], M[r1][i] = M[r2][i], M[r2][i] = … | |
+ } | |
+ t = 1. / M[r1][r1]; | |
+ for (i = 0; i < 6; i++) | |
+ M[r1][i] *= t; | |
+ for (r2 = r1; r2--;) | |
+ for (i = 0, t = M[r2][r1]; i < 6; i++) | |
+ M[r2][i] -= M[r1][i] * t; | |
+ } | |
+ for (r1 = 3; r1--;) | |
+ for (r2 = r1; r2--;) | |
+ for (i = 0, t = M[r2][r1]; i < 6; i++) | |
+ M[r2][i] -= M[r1][i] * t; | |
+ | |
+ for (i = 0; i < 3; i++) { | |
+ t = M[i][3] * x[3] + M[i][4] * y[3] + M[i][5] * z[3]; | |
+ M[0][i] = t * x[i]; | |
+ M[1][i] = t * y[i]; | |
+ M[2][i] = t * z[i]; | |
+ } | |
+ | |
+ eset_pixel_format(&stream, pixfmt); | |
+ fprint_stream_head(stdout, &stream); | |
+ efflush(stdout, "<stdout>"); | |
+ | |
+ for (i = 0; i < 3; i++) { | |
+ for (j = 0; j < 3; j++) { | |
+ Mlf[i * 12 + j * 4 + 0] = M[i][j]; | |
+ Mlf[i * 12 + j * 4 + 1] = M[i][j]; | |
+ Mlf[i * 12 + j * 4 + 2] = M[i][j]; | |
+ Mlf[i * 12 + j * 4 + 3] = 1.; | |
+ } | |
+ } | |
+ | |
+ if (stream.encoding == DOUBLE) { | |
+ ewriteall(STDOUT_FILENO, Mlf, sizeof(Mlf), "<stdout>"); | |
+ } else { | |
+ for (i = 0; i < ELEMENTSOF(Mlf); i++) | |
+ Mf[i] = (float)Mlf[i]; | |
+ ewriteall(STDOUT_FILENO, Mf, sizeof(Mf), "<stdout>"); | |
+ } | |
+ | |
+ return 0; | |
+} | |
diff --git a/src/blind-invert-matrix.c b/src/blind-invert-matrix.c | |
@@ -2,9 +2,11 @@ | |
#ifndef TYPE | |
#include "common.h" | |
-USAGE("") | |
+USAGE("[-aexyz]") | |
static int equal = 0; | |
+static int skip_ch[] = {0, 0, 0, 0}; | |
+static size_t first_included = 0; | |
#define FILE "blind-invert-matrix.c" | |
#include "define-functions.h" | |
@@ -14,13 +16,25 @@ main(int argc, char *argv[]) | |
{ | |
struct stream stream; | |
size_t width, x, y, i, row_size; | |
- char *buf, *one, *p; | |
+ char *buf, *one, *p, *q; | |
void (*process)(struct stream *stream, void *buf); | |
ARGBEGIN { | |
+ case 'a': | |
+ skip_ch[3] = 1; | |
+ break; | |
case 'e': | |
equal = 1; | |
break; | |
+ case 'x': | |
+ skip_ch[0] = 1; | |
+ break; | |
+ case 'y': | |
+ skip_ch[1] = 1; | |
+ break; | |
+ case 'z': | |
+ skip_ch[2] = 1; | |
+ break; | |
default: | |
usage(); | |
} ARGEND; | |
@@ -28,6 +42,11 @@ main(int argc, char *argv[]) | |
if (argc) | |
usage(); | |
+ while (first_included < ELEMENTSOF(skip_ch) && skip_ch[first_included]) | |
+ first_included++; | |
+ if (first_included == ELEMENTSOF(skip_ch)) | |
+ equal = 0; | |
+ | |
eopen_stream(&stream, NULL); | |
echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); | |
width = stream.width; | |
@@ -66,17 +85,20 @@ main(int argc, char *argv[]) | |
} | |
} | |
if (equal) { | |
- process(&stream, buf); | |
+ process(&stream, buf + first_included * stream.chan_si… | |
for (y = 0; y < stream.height; y++) { | |
for (x = 0; x < stream.width; x++) { | |
- p = buf + y * row_size + x * stream.pi… | |
- for (i = 1; i < stream.n_chan; i++) | |
- memcpy(p + i * stream.chan_siz… | |
+ p = buf + y * row_size + x * stream.pi… | |
+ q = p + first_included * stream.chan_s… | |
+ for (i = 0; i < stream.n_chan; i++, p … | |
+ if (i != first_included && !sk… | |
+ memcpy(p, q, stream.ch… | |
} | |
} | |
} else { | |
for (i = 0; i < stream.n_chan; i++) | |
- process(&stream, buf + i * stream.chan_size); | |
+ if (!skip_ch[i]) | |
+ process(&stream, buf + i * stream.chan… | |
} | |
for (y = 0; y < stream.height; y++) | |
ewriteall(STDOUT_FILENO, buf + y * row_size + stream.c… | |
@@ -107,7 +129,7 @@ PROCESS(struct stream *stream, void *buf) | |
for (r1 = 0; r1 < rn; r1++) { | |
p1 = matrix + r1 * cn; | |
- if (!p1[r1][0]) { | |
+ if (!p1[r1][0]) { | |
for (r2 = r1 + 1; r2 < rn; r2++) { | |
p2 = matrix + r2 * cn; | |
if (p2[r1][0]) |