URI: 
       Fix some errors, add manual for blind-colour-matrix and add blind-primary-key - blind - suckless command-line video editing utility
  HTML git clone git://git.suckless.org/blind
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit ccd26e2affb0fb4a10b7261a85cb85b2525e5d9e
   DIR parent 698481451a63e0bd81aeb1ad3bf794ce7aaadef2
  HTML 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:
         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(-)
       ---
   DIR diff --git a/.gitignore b/.gitignore
       @@ -13,3 +13,4 @@
        !/blind-rotate-90
        !/blind-rotate-180
        !/blind-rotate-270
       +!/blind-primary-key
   DIR 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
   DIR 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
        
   DIR 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
   DIR 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
   DIR 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 >
   DIR 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 >
   DIR 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 >
   DIR 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 >
   DIR 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
   DIR 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++) {
   DIR 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.;
                        }
                }
   DIR 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;
        }
   DIR 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) {