commit ccd26e2affb0fb4a10b7261a85cb85b2525e5d9e
parent 698481451a63e0bd81aeb1ad3bf794ce7aaadef2
Author: Mattias Andrée <maandree@kth.se>
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 <maandree@kth.se>
Diffstat:
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 0) $(./blind-colour-srgb -ld1 0 0 1)"
+ ./blind-from-image < in.png | ./blind-affine-colour -al <(./blind-colour-matrix $RGB) | \
+ ./blind-affine-colour -al <(./blind-colour-matrix $RGB | ./blind-invert-matrix -ae) | \
+ ./blind-to-image | convert - out.png
+
+
+
blind-transform affine transformation by matrix multiplication, -[xy] for tiling, -s for
improve quality on downscaling (pixels' neighbours must not change)
-blind-primary-key replace a primary with transparency, -g for greyscaled images
blind-apply-map remap pixels (distortion) using the X and Y values, -[xy] for tiling, -s for
improve quality on downscaling (pixels' neighbours must not change)
blind-find-frame a graphical tool for locating frames, should highlight key frames, and
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' '\n/'):${PATH}"
+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" >&2
+ 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-named -a blind-${pid}-invmat) | \
+ blind-repeat inf -)
+ }
+ unconvert () {
+ blind-affine-colour -al \
+ <(blind-from-named -a blind-${pid}-invmat blind-repeat inf -)
+ }
+fi
+
+if test $grey = 0; then
+ finalise () { unconvert; }
+else
+ finalise () {
+ unconvert | blind-set-saturation <(blind-single-colour -f inf -w $width -h $height 0)
+ }
+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 < maandree@kth.se >
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 < maandree@kth.se >
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 < maandree@kth.se >
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 < maandree@kth.se >
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 * matrix->row_size))
break;
- if (!per_pixel)
+ if (!per_pixel) {
+ if (!y) {
+ mat = (TYPE *)mbuf;
+ for (i = 0; i < dim; i++, mat += w)
+ for (j = 0; j < dim; j++)
+ M[i][j] = mat[j * matrix->n_chan + 1]
+ * mat[(j + 1) * matrix->n_chan - 1];
+ }
y = (y + 1) % colour->height;
+ }
}
if (per_pixel) {
mat = (TYPE *)(mbuf + x * dim * matrix->pixel_size);
for (i = 0; i < dim; i++, mat += w)
for (j = 0; j < dim; j++)
- M[i][j] = mat[j * matrix->n_chan + 1] * mat[(j + 1) * matrix->n_chan - 1];
+ M[i][j] = mat[j * matrix->n_chan + 1]
+ * mat[(j + 1) * matrix->n_chan - 1];
}
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 Y2 Z2 X3 Y3 Z3 [white-X white-Y white-Z])")
+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])")
+
+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 3\n");
+ for (i = 0; i < 6; i++)
+ t = M[r1][i], M[r1][i] = M[r2][i], M[r2][i] = t;
+ }
+ 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 3\n");
- for (i = 0; i < 6; i++)
- t = M[r1][i], M[r1][i] = M[r2][i], M[r2][i] = t;
- }
- 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_t *restrict 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) {