Fix some errors, add manual for blind-colour-matrix and add blind-primary-key -… | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit ccd26e2affb0fb4a10b7261a85cb85b2525e5d9e | |
parent 698481451a63e0bd81aeb1ad3bf794ce7aaadef2 | |
Author: Mattias Andrée <[email protected]> | |
Date: Sun, 23 Jul 2017 20:48:18 +0200 | |
Fix some errors, add manual for blind-colour-matrix and add blind-primary-key | |
Signed-off-by: Mattias Andrée <[email protected]> | |
Diffstat: | |
M .gitignore | 1 + | |
M Makefile | 1 + | |
M README | 3 +++ | |
M TODO | 10 +++++++++- | |
A blind-primary-key | 114 +++++++++++++++++++++++++++++… | |
M man/blind-chroma-key.1 | 3 ++- | |
A man/blind-colour-matrix.1 | 76 +++++++++++++++++++++++++++++… | |
M man/blind-dual-key.1 | 3 ++- | |
A man/blind-primary-key.1 | 84 +++++++++++++++++++++++++++++… | |
M man/blind.7 | 3 +++ | |
M src/blind-affine-colour.c | 13 +++++++++++-- | |
M src/blind-colour-matrix.c | 72 +++++++++++++++++------------… | |
M src/blind-from-named.c | 4 +--- | |
M src/util.c | 6 ++++-- | |
14 files changed, 350 insertions(+), 43 deletions(-) | |
--- | |
diff --git a/.gitignore b/.gitignore | |
@@ -13,3 +13,4 @@ | |
!/blind-rotate-90 | |
!/blind-rotate-180 | |
!/blind-rotate-270 | |
+!/blind-primary-key | |
diff --git a/Makefile b/Makefile | |
@@ -106,6 +106,7 @@ BIN =\ | |
# blind-temporal-mean | |
SCRIPTS =\ | |
+ blind-primary-key\ | |
blind-rotate-90\ | |
blind-rotate-180\ | |
blind-rotate-270 | |
diff --git a/README b/README | |
@@ -174,6 +174,9 @@ UTILITIES | |
blind-premultiply(1) | |
Premultiply the alpha channel of a video | |
+ blind-primary-key(1) | |
+ Replace a primary with transparency | |
+ | |
blind-quaternion-product(1) | |
Calculate the quaternion product of colours in a video | |
diff --git a/TODO b/TODO | |
@@ -1,6 +1,14 @@ | |
+This command should not noticeably change the image: | |
+ | |
+ RGB="$(./blind-colour-srgb -ld1 1 0 0) $(./blind-colour-srgb -ld1 0 1 … | |
+ ./blind-from-image < in.png | ./blind-affine-colour -al <(./blind-colo… | |
+ ./blind-affine-colour -al <(./blind-colour-matrix $RGB | ./bli… | |
+ ./blind-to-image | convert - out.png | |
+ | |
+ | |
+ | |
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-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/blind-primary-key b/blind-primary-key | |
@@ -0,0 +1,114 @@ | |
+#!/bin/bash | |
+ | |
+set -e | |
+ | |
+if printf '%s\n' "$0" | grep / >/dev/null 2>/dev/null; then | |
+ export PATH="$(printf '%s\n' "$0" | tr '/\n' '\n/' | sed \$d | tr '/\n' '\… | |
+fi | |
+ | |
+pid=$$ | |
+o='0 0 0 0' | |
+E='1 1 1 1' | |
+ | |
+x=x; y=y; z=z | |
+ciexyy=0 | |
+zflag= | |
+grey=0 | |
+ | |
+usage () { | |
+ xyy="-z x1 y1 x2 y2 x3 y3 [white-x white-y]" | |
+ xyz="X1 Y1 Z1 X2 Y2 Z2 X3 Y3 Z3 [white-X white-Y white-Z]" | |
+ printf 'usage: %s [-1 | -2 | -3] [-g] [%s | %s]\n' "$0" "$xyy" "$xyz" … | |
+ exit 1 | |
+} | |
+ | |
+while ! test $# = 0; do | |
+ if test "$1" = --; then | |
+ shift 1 | |
+ break | |
+ elif test "${1::1}" = -; then | |
+ arg="${1:1}" | |
+ shift 1 | |
+ while test -n "${arg::1}"; do | |
+ flag="${arg::1}" | |
+ arg="${arg:1}" | |
+ if test "$flag" = 1; then | |
+ x=x; y=y; z=z | |
+ elif test "$flag" = 2; then | |
+ x=y; y=z; z=x | |
+ elif test "$flag" = 3; then | |
+ x=z; y=x; z=y | |
+ elif test "$flag" = g; then | |
+ grey=1 | |
+ elif test "$flag" = z; then | |
+ ciexyy=1 | |
+ else | |
+ usage | |
+ fi | |
+ done | |
+ else | |
+ break | |
+ fi | |
+done | |
+ | |
+a=$(( ( 3 - $ciexyy ) * 3 )) | |
+b=$(( ( 3 - $ciexyy ) * 4 )) | |
+if test $# != 0 && test $# != $a && test $# != $b; then | |
+ usage | |
+elif test $ciexyy = 1 && test $# = 0; then | |
+ usage | |
+fi | |
+ | |
+read frames width height pixfmt < <(blind-read-head) | |
+ | |
+if test $# = 0; then | |
+ convert () { cat; } | |
+ unconvert () { cat; } | |
+else | |
+ if test $ciexyy = 1; then | |
+ zflag=-z | |
+ fi | |
+ convert () { | |
+ blind-affine-colour -al \ | |
+ <(blind-colour-matrix -F "$pixfmt" $zflag -- "$@" | \ | |
+ blind-tee \ | |
+ >(blind-invert-matrix -ae | \blind-to-… | |
+ blind-repeat inf -) | |
+ } | |
+ unconvert () { | |
+ blind-affine-colour -al \ | |
+ <(blind-from-named -a blind-${pid}-invmat blind-repeat… | |
+ } | |
+fi | |
+ | |
+if test $grey = 0; then | |
+ finalise () { unconvert; } | |
+else | |
+ finalise () { | |
+ unconvert | blind-set-saturation <(blind-single-colour -f inf … | |
+ } | |
+fi | |
+ | |
+(blind-write-head $frames $width $height "$pixfmt" ; cat) | \ | |
+ convert "$@" | \ | |
+ blind-split-chans -c \ | |
+ >(blind-to-named -a blind-${pid}-x) \ | |
+ >(blind-to-named -a blind-${pid}-y) \ | |
+ >(blind-to-named -a blind-${pid}-z) \ | |
+ - | \ | |
+ blind-arithm mul \ | |
+ <(blind-single-colour -f inf -w $width -h $height 0 0 0 1 | \ | |
+ blind-arithm sub \ | |
+ <(blind-from-named -a blind-${pid}-$x \ | |
+ blind-affine-colour -l \ | |
+ <(printf '%s %s %s %s\n' \ | |
+ 1 4 4 xyza \ | |
+ $o $o $o $o \ | |
+ $o $o $o $o \ | |
+ $o $o $o $o \ | |
+ $E $E $E $o | \ | |
+ blind-from-text | \ | |
+ blind-repeat inf -))) … | |
+ blind-from-named -f 8 -a blind-${pid}-$y blind-arithm add /dev/fd/8 | \ | |
+ blind-from-named -f 9 -a blind-${pid}-$z blind-arithm add /dev/fd/9 | \ | |
+ finalise | |
diff --git a/man/blind-chroma-key.1 b/man/blind-chroma-key.1 | |
@@ -33,7 +33,8 @@ colour, twos alpha values are inverted. | |
.BR blind-from-text (1), | |
.BR blind-colour-ciexyz (1), | |
.BR blind-colour-srgb (1), | |
-.BR blind-dual-key (1) | |
+.BR blind-dual-key (1), | |
+.BR blind-primary-key (1) | |
.SH AUTHORS | |
Mattias Andrée | |
.RI < [email protected] > | |
diff --git a/man/blind-colour-matrix.1 b/man/blind-colour-matrix.1 | |
@@ -0,0 +1,76 @@ | |
+.TH BLIND-COLOUR-MATRIX 1 blind | |
+.SH NAME | |
+blind-colour-matrix - Create colour space conversion matrix | |
+.SH SYNOPSIS | |
+.B blind-colour-matrix | |
+[-F | |
+.IR pixel-format ] | |
+(-z | |
+.I x1 | |
+.I y1 | |
+.I x2 | |
+.I y2 | |
+.I x3 | |
+.I y3 | |
+.RI [ white-x | |
+.IR white-y ] | |
+| | |
+.I X1 | |
+.I Y1 | |
+.I Z1 | |
+.I X2 | |
+.I Y2 | |
+.I Z2 | |
+.I X3 | |
+.I Y3 | |
+.I Z3 | |
+.RI [ white-X | |
+.I white-Y | |
+.IR white-Z ]) | |
+.SH DESCRIPTION | |
+.B blind-colour-matrix | |
+creates a colour conversion matrix, that is | |
+printed as blind video to stdout, for conversion | |
+from the colour space used by blind to a colour | |
+space with the primaries whose CIE XYZ values are | |
+.RI ( X1 | |
+.I Y1 | |
+.IR Z1 ), | |
+.RI ( X2 | |
+.I Y2 | |
+.IR Z2 ), | |
+and | |
+.RI ( X3 | |
+.I Y3 | |
+.IR Z3 ) | |
+and whose white point is the colour whose | |
+CIE XYZ values are | |
+.RI ( white-X | |
+.I white-Y | |
+.IR white-Z ). | |
+If the white point is not specified, | |
+CIE Standard Illuminant D65 is used. | |
+.SH OPTIONS | |
+.TP | |
+.BR -F " "\fIpixel-format\fP | |
+Select pixel format, see | |
+.BR blind-convert (1) | |
+for more information. | |
+.TP | |
+.B -z | |
+Parse arguments as CIE XYY instead of CIE XYZ. | |
+.SH NOTES | |
+.B blind-colour-matrix | |
+may be changed in the future to use some other colour model, | |
+therefore, it is recommended to also use | |
+.BR blind-colour-ciexyz (1) | |
+if you are specifying the colour in CIE XYZ. | |
+.SH SEE ALSO | |
+.BR blind (7), | |
+.BR blind-colour-ciexyz (1), | |
+.BR blind-colour-srgb (1), | |
+.BR blind-invert-matrix (1), | |
+.BR blind-affine-colour (1) | |
+.SH AUTHORS | |
+Mattias Andrée | |
+.RI < [email protected] > | |
diff --git a/man/blind-dual-key.1 b/man/blind-dual-key.1 | |
@@ -50,7 +50,8 @@ example black and white or green and magenta. | |
.BR blind (7), | |
.BR blind-colour-ciexyz (1), | |
.BR blind-colour-srgb (1), | |
-.BR blind-chroma-key (1) | |
+.BR blind-chroma-key (1), | |
+.BR blind-primary-key (1) | |
.SH AUTHORS | |
Mattias Andrée | |
.RI < [email protected] > | |
diff --git a/man/blind-primary-key.1 b/man/blind-primary-key.1 | |
@@ -0,0 +1,84 @@ | |
+.TH BLIND-PRIMARY-KEY 1 blind | |
+.SH NAME | |
+blind-primary-key - Replace a primary with transparency | |
+.SH SYNOPSIS | |
+.B blind-primary-key | |
+[-1 | -2 | -3] [-g] (-z | |
+.I x1 | |
+.I y1 | |
+.I x2 | |
+.I y2 | |
+.I x3 | |
+.I y3 | |
+.RI [ white-x | |
+.IR white-y ] | |
+| | |
+.I X1 | |
+.I Y1 | |
+.I Z1 | |
+.I X2 | |
+.I Y2 | |
+.I Z2 | |
+.I X3 | |
+.I Y3 | |
+.I Z3 | |
+.RI [ white-X | |
+.I white-Y | |
+.IR white-Z ]) | |
+.SH DESCRIPTION | |
+.B blind-primary-key | |
+reads a video from stdin and replaces a primary | |
+with transparency and prints the resulting video | |
+to stdout. | |
+.B blind-primary-key | |
+internally converts colour space to the one | |
+with the primaries whose CIE XYZ values are | |
+.RI ( X1 | |
+.I Y1 | |
+.IR Z1 ), | |
+.RI ( X2 | |
+.I Y2 | |
+.IR Z2 ), | |
+and | |
+.RI ( X3 | |
+.I Y3 | |
+.IR Z3 ) | |
+and whose white point is the colour whose | |
+CIE XYZ values are | |
+.RI ( white-X | |
+.I white-Y | |
+.IR white-Z ), | |
+and replaces the first primary with transparency. | |
+If the white point is not specified, | |
+CIE Standard Illuminant D65 is used. | |
+.P | |
+If the colour space is specified, no conversion | |
+is done internally. | |
+.SH OPTIONS | |
+.TP | |
+.B -1 | |
+Replace the the first primary with transparency. (Default.) | |
+.TP | |
+.B -2 | |
+Replace the the second primary, instead | |
+of the first primary, with transparency. | |
+.TP | |
+.B -3 | |
+Replace the the third primary, instead | |
+of the first primary, with transparency. | |
+.TP | |
+.B -g | |
+The video is, with the exception of the keyed primary, | |
+greyscale and the output video shall remain greyscale. | |
+.TP | |
+.B -z | |
+Parse arguments as CIE XYY instead of CIE XYZ. | |
+.SH SEE ALSO | |
+.BR blind (7), | |
+.BR blind-colour-ciexyz (1), | |
+.BR blind-colour-srgb (1), | |
+.BR blind-invert-matrix (1), | |
+.BR blind-affine-colour (1) | |
+.SH AUTHORS | |
+Mattias Andrée | |
+.RI < [email protected] > | |
diff --git a/man/blind.7 b/man/blind.7 | |
@@ -192,6 +192,9 @@ Calculate the norm of colours in a video | |
.BR blind-premultiply (1) | |
Premultiply the alpha channel of a video | |
.TP | |
+.BR blind-primary-key (1) | |
+Replace a primary with transparency | |
+.TP | |
.BR blind-quaternion-product (1) | |
Calculate the quaternion product of colours in a video | |
.TP | |
diff --git a/src/blind-affine-colour.c b/src/blind-affine-colour.c | |
@@ -88,14 +88,23 @@ PROCESS(struct stream *colour, struct stream *matrix) | |
if (!x) { | |
if (!y && !eread_segment(matrix, mbuf, dim * m… | |
break; | |
- if (!per_pixel) | |
+ if (!per_pixel) { | |
+ if (!y) { | |
+ mat = (TYPE *)mbuf; | |
+ for (i = 0; i < dim; i++, mat … | |
+ for (j = 0; j < dim; j… | |
+ M[i][j] = mat[… | |
+ * mat[… | |
+ } | |
y = (y + 1) % colour->height; | |
+ } | |
} | |
if (per_pixel) { | |
mat = (TYPE *)(mbuf + x * dim * matrix->pixel_… | |
for (i = 0; i < dim; i++, mat += w) | |
for (j = 0; j < dim; j++) | |
- M[i][j] = mat[j * matrix->n_ch… | |
+ M[i][j] = mat[j * matrix->n_ch… | |
+ * mat[(j + 1) * matrix… | |
} | |
pixel = (TYPE *)(colour->buf + ptr); | |
for (i = 0; i < dim; i++) { | |
diff --git a/src/blind-colour-matrix.c b/src/blind-colour-matrix.c | |
@@ -1,7 +1,33 @@ | |
/* 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… | |
+USAGE("[-F pixel-format] (-z x1 y1 x2 y2 x3 y3 [white-x white-y] | X1 Y1 Z1 X2… | |
+ | |
+static void | |
+invert(double M[3][6]) | |
+{ | |
+ size_t r1, r2, i; | |
+ double t; | |
+ 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 + 1; r2 < 3; 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; | |
+} | |
int | |
main(int argc, char *argv[]) | |
@@ -12,7 +38,7 @@ main(int argc, char *argv[]) | |
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; | |
+ size_t i, j; | |
ARGBEGIN { | |
case 'F': | |
@@ -59,15 +85,6 @@ main(int argc, char *argv[]) | |
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++) { | |
@@ -78,25 +95,7 @@ main(int argc, char *argv[]) | |
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; | |
+ invert(M); | |
for (i = 0; i < 3; i++) { | |
t = M[i][3] * x[3] + M[i][4] * y[3] + M[i][5] * z[3]; | |
@@ -105,15 +104,22 @@ main(int argc, char *argv[]) | |
M[2][i] = t * z[i]; | |
} | |
+ for (i = 0; i < 3; i++) { | |
+ M[i][3] = M[i][4] = M[i][5] = 0.; | |
+ M[i][3 + i] = 1.; | |
+ } | |
+ | |
+ invert(M); | |
+ | |
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 + 0] = M[i][3 + j]; | |
+ Mlf[i * 12 + j * 4 + 1] = M[i][3 + j]; | |
+ Mlf[i * 12 + j * 4 + 2] = M[i][3 + j]; | |
Mlf[i * 12 + j * 4 + 3] = 1.; | |
} | |
} | |
diff --git a/src/blind-from-named.c b/src/blind-from-named.c | |
@@ -107,9 +107,7 @@ retry: | |
eprintf("execvp %s:", argv[0]); | |
} | |
- while ((n = read(fd, buf, sizeof(buf))) > 0) | |
+ while ((n = eread(fd, buf, sizeof(buf), "<received file>"))) | |
ewriteall(STDOUT_FILENO, buf, (size_t)n, "<stdout>"); | |
- if (n < 0) | |
- eprintf("read <received file>:"); | |
return 0; | |
} | |
diff --git a/src/util.c b/src/util.c | |
@@ -158,16 +158,18 @@ getfile(int fd, void *buffer, size_t *restrict ptr, size_… | |
{ | |
char *restrict *restrict buf = buffer; | |
void *new; | |
+ size_t new_size; | |
ssize_t r; | |
for (;;) { | |
if (*ptr == *size) { | |
- if (!(new = realloc(*buf, *size << 1))) { | |
+ new_size = *size ? *size << 1 : BUFSIZ; | |
+ if (!(new = realloc(*buf, new_size))) { | |
errno = ENOMEM; | |
return -1; | |
} | |
*buf = new; | |
- *size <<= 1; | |
+ *size = new_size; | |
} | |
r = read(fd, *buf + *ptr, *size - *ptr); | |
if (r <= 0) { |