commit ccd26e2affb0fb4a10b7261a85cb85b2525e5d9e
Author:     Mattias Andrée <[email protected]>
AuthorDate: Sun Jul 23 20:48:18 2017 +0200
Commit:     Mattias Andrée <[email protected]>
CommitDate: Sun Jul 23 20:48:18 2017 +0200

    Fix some errors, add manual for blind-colour-matrix and add 
blind-primary-key
    
    Signed-off-by: Mattias Andrée <[email protected]>

diff --git a/.gitignore b/.gitignore
index 7c536da..c9f0f51 100644
--- 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
index 67d5766..a19e7bf 100644
--- 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
index 62ba6e6..8da87c7 100644
--- 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
index 5fe296c..6e37c53 100644
--- 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
new file mode 100755
index 0000000..d298af5
--- /dev/null
+++ 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
index f185226..70f6902 100644
--- 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
new file mode 100644
index 0000000..a976260
--- /dev/null
+++ 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
index f951d10..fcbb967 100644
--- 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
new file mode 100644
index 0000000..6203592
--- /dev/null
+++ 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
index 1f6b77b..acc4bb5 100644
--- 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
index 7be9ab6..654345f 100644
--- 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
index e4ff869..7387beb 100644
--- 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
index 8290bc5..04c6e91 100644
--- 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
index 3e03b67..3fc3716 100644
--- 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) {

Reply via email to