URI: 
       Add blind-mean - 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 bd8018a737281770159231c060f3bfd30788a430
   DIR parent 835df7bd1e81852062dd70ce1a054fc9b510e50f
  HTML Author: Mattias Andrée <maandree@kth.se>
       Date:   Wed, 26 Jul 2017 00:24:39 +0200
       
       Add blind-mean
       
       Signed-off-by: Mattias Andrée <maandree@kth.se>
       
       Diffstat:
         M Makefile                            |       1 +
         M README                              |       3 +++
         M TODO                                |       9 ++-------
         M man/blind-arithm.1                  |       1 +
         A man/blind-mean.1                    |      87 +++++++++++++++++++++++++++++++
         M man/blind-spatial-arithm.1          |       1 +
         M man/blind-spatial-mean.1            |       3 ++-
         M man/blind-temporal-arithm.1         |       1 +
         M man/blind-temporal-mean.1           |       1 +
         M man/blind.7                         |       3 +++
         A src/blind-mean.c                    |     171 +++++++++++++++++++++++++++++++
         M src/blind-spatial-mean.c            |       2 +-
         M src/blind-temporal-mean.c           |       2 +-
       
       13 files changed, 275 insertions(+), 10 deletions(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       @@ -53,6 +53,7 @@ BIN =\
                blind-matrix-shear\
                blind-matrix-translate\
                blind-matrix-transpose\
       +        blind-mean\
                blind-mosaic\
                blind-mosaic-corners\
                blind-mosaic-edges\
   DIR diff --git a/README b/README
       @@ -156,6 +156,9 @@ UTILITIES
               blind-matrix-transpose(1)
                      Create an affine 2D-transformation matrix for transposition
        
       +       blind-mean(1)
       +              Calcuate the mean over videos for each pixel in each frame
       +
               blind-mosaic(1)
                      Redraw each frame in video as a mosaic
        
   DIR diff --git a/TODO b/TODO
       @@ -1,3 +1,5 @@
       +blind-*-mean: replace power with power-stream
       +
        blind-transform                affine transformation by matrix multiplication, -[xy] for tiling, -s for
                                        improve quality on downscaling (pixels' neighbours must not change)
        blind-apply-map                remap pixels (distortion) using the X and Y values, -[xy] for tiling, -s for
       @@ -24,13 +26,6 @@ blind-roberts-cross        https://en.wikipedia.org/wiki/Roberts_cross
        ---                        https://en.wikipedia.org/wiki/Canny_edge_detector
        ---                        https://en.wikipedia.org/wiki/Deriche_edge_detector
        ---                        https://en.wikipedia.org/wiki/Edge_detection
       -blind-mean                mean of multiple streams
       -                        means from blind-temporal-mean
       -                        https://en.wikipedia.org/wiki/Heinz_mean
       -                        https://en.wikipedia.org/wiki/Heronian_mean
       -                        https://en.wikipedia.org/wiki/Identric_mean
       -                        https://en.wikipedia.org/wiki/Logarithmic_mean
       -                        https://en.wikipedia.org/wiki/Stolarsky_mean
        blind-apply-icc                apply ICC profile to video
        blind-convex-gradient        create a gradient in the shape of a convex lens
        blind-concave-gradient        create a gradient in the shape of a concave lens
   DIR diff --git a/man/blind-arithm.1 b/man/blind-arithm.1
       @@ -100,6 +100,7 @@ Do not modify the Z channel (the third channel).
        .BR blind-spatial-arithm (1),
        .BR blind-temporal-mean (1),
        .BR blind-temporal-arithm (1),
       +.BR blind-mean (1),
        .BR blind-single-colour (1),
        .BR blind-set-alpha (1),
        .BR blind-set-luma (1),
   DIR diff --git a/man/blind-mean.1 b/man/blind-mean.1
       @@ -0,0 +1,87 @@
       +.TH BLIND-MEAN 1 blind
       +.SH NAME
       +blind-mean - Calcuate the mean over videos for each pixel in each frame
       +.SH SYNOPSIS
       +.B blind-mean
       +[-g | -h | -H | -i | -l
       +.I power
       +| -L | -p
       +.I power
       +| -s
       +.I power
       +| -v | -z
       +.IR power ]
       +.I stream-1
       +.IR stream-2 \ ...
       +.SH DESCRIPTION
       +.B blind-mean
       +reads videos from
       +.I stream-1
       +and the files specified in all succeeding
       +arguments, and for each pixel in each frame,
       +calculates the mean of the videos, and prints
       +the resulting video to stdout.
       +.P
       +Unless otherwise specified, the arithmetic mean
       +is calculated.
       +.SH OPTIONS
       +.TP
       +.B -g
       +Calculate the geometric mean.
       +.TP
       +.B -h
       +Calculate the harmonic mean.
       +.TP
       +.B -i
       +Calculate the identric mean.
       +.TP
       +.B -H
       +Calculate the Heronian mean.
       +No arguments after
       +.I stream-2
       +are allowed if this flag is used.
       +.TP
       +.BR -l \ \fIpower\fP
       +Calculate the Lehmer mean with the specified
       +.IR power .
       +.TP
       +.B -L
       +Calculate the logarithmic mean.
       +No arguments after
       +.I stream-2
       +are allowed if this flag is used.
       +.TP
       +.BR -p \ \fIpower\fP
       +Calculate the power mean (Hölder mean) with
       +the specified
       +.IR power .
       +.TP
       +.BR -s \ \fIpower\fP
       +Calculate the Stolarsky mean with
       +the specified
       +.IR power .
       +No arguments after
       +.I stream-2
       +are allowed if this flag is used.
       +.TP
       +.B -v
       +Calculate the variance.
       +.TP
       +.BR -z \ \fIpower\fP
       +Calculate the Heinz meanw ith
       +the specified
       +.IR power .
       +No arguments after
       +.I stream-2
       +are allowed if this flag is used.
       +.SH SEE ALSO
       +.BR blind (7),
       +.BR blind-temporal-mean (1),
       +.BR blind-spatial-mean (1),
       +.BR blind-temporal-arithm (1),
       +.BR blind-spatial-arithm (1),
       +.BR blind-arithm (1),
       +.BR blind-rewrite-head (1)
       +.SH AUTHORS
       +Mattias Andrée
       +.RI < maandree@kth.se >
   DIR diff --git a/man/blind-spatial-arithm.1 b/man/blind-spatial-arithm.1
       @@ -29,6 +29,7 @@ Select the highest operand.
        .BR blind-arithm (1),
        .BR blind-spatial-mean (1),
        .BR blind-temporal-mean (1),
       +.BR blind-mean (1),
        .BR blind-rewrite-head (1)
        .SH AUTHORS
        Mattias Andrée
   DIR diff --git a/man/blind-spatial-mean.1 b/man/blind-spatial-mean.1
       @@ -38,10 +38,11 @@ the specified
        Calculate the variance.
        .SH SEE ALSO
        .BR blind (7),
       +.BR blind-temporal-mean (1),
       +.BR blind-mean (1),
        .BR blind-temporal-arithm (1),
        .BR blind-spatial-arithm (1),
        .BR blind-arithm (1),
       -.BR blind-temporal-mean (1),
        .BR blind-rewrite-head (1)
        .SH AUTHORS
        Mattias Andrée
   DIR diff --git a/man/blind-temporal-arithm.1 b/man/blind-temporal-arithm.1
       @@ -33,6 +33,7 @@ A frame requires 32 bytes per pixel it contains.
        .BR blind-spatial-arithm (1),
        .BR blind-spatial-mean (1),
        .BR blind-arithm (1),
       +.BR blind-mean (1),
        .BR blind-rewrite-head (1)
        .SH AUTHORS
        Mattias Andrée
   DIR diff --git a/man/blind-temporal-mean.1 b/man/blind-temporal-mean.1
       @@ -54,6 +54,7 @@ is optimised for simplicity rather than memory usage.
        .BR blind-spatial-arithm (1),
        .BR blind-arithm (1),
        .BR blind-spatial-mean (1),
       +.BR blind-mean (1),
        .BR blind-rewrite-head (1)
        .SH AUTHORS
        Mattias Andrée
   DIR diff --git a/man/blind.7 b/man/blind.7
       @@ -174,6 +174,9 @@ Create an affine 2D-transformation matrix for translation
        .BR blind-matrix-transpose (1)
        Create an affine 2D-transformation matrix for transposition
        .TP
       +.BR blind-mean (1)
       +Calcuate the mean over videos for each pixel in each frame
       +.TP
        .BR blind-mosaic (1)
        Redraw each frame in video as a mosaic
        .TP
   DIR diff --git a/src/blind-mean.c b/src/blind-mean.c
       @@ -0,0 +1,171 @@
       +/* See LICENSE file for copyright and license details. */
       +#include "common.h"
       +
       +USAGE("[-g | -h | -H | -i | -l power | -L | -p power | -s power | -v | -z power] stream-1 stream-2 ...")
       +/* TODO add [-w weight-stream] for [-ghlpv] */
       +
       +/* Because the syntax for a function returning a function pointer is disgusting. */
       +typedef void (*process_func)(struct stream *streams, size_t n_streams, size_t n);
       +
       +/*
       + * X-parameter 1: method enum value
       + * X-parameter 2: identifier-friendly name
       + * X-parameter 3: initial assignments
       + * X-parameter 4: initial value
       + * X-parameter 5: subcell processing
       + * X-parameter 6: subcell finalisation
       + */
       +#define LIST_MEANS(TYPE)\
       +        /* [default] arithmetic mean */\
       +        X(ARITHMETIC, arithmetic, sn = (TYPE)1 / sn, 0, img += val, img *= sn) \
       +        /* geometric mean */\
       +        X(GEOMETRIC, geometric, sn = (TYPE)1 / sn, 1, img *= val, img = nnpow(img, sn))\
       +        /* harmonic mean */\
       +        X(HARMONIC, harmonic,, 0, img += (TYPE)1 / val, img = sn / img)\
       +        /* Heronian mean */\
       +        X(HERONIAN, heronian,, 0, auxs[j] = val,\
       +          img = (auxs[0] + sqrt(auxs[0] * auxs[1]) + auxs[1]) / (TYPE)3)\
       +        /* identric mean */\
       +        X(IDENTRIC, identric, a = (TYPE)(1. / M_E), 0, auxs[j] = val,\
       +          img = auxs[0] == auxs[1] ? auxs[0] :\
       +                nnpow(nnpow(auxs[0], auxs[0]) / nnpow(auxs[1], auxs[1]), auxs[0] - auxs[1]) * a)\
       +        /* Lehmer mean */\
       +        X(LEHMER, lehmer, (a = (TYPE)power, b = a - (TYPE)1), 0,\
       +          (img += nnpow(val, a), aux += nnpow(val, b)), img /= aux)\
       +        /* logarithmic mean */\
       +        X(LOGARITHMIC, logarithmic,, 0, auxs[j] = val,\
       +          img = auxs[0] == auxs[1] ? auxs[0] : (!auxs[0] || !auxs[1]) ? (TYPE)0 :\
       +                (auxs[1] - auxs[0]) / log(auxs[1] / auxs[0]))\
       +        /* power mean (Hölder mean) (m = 2 for root square mean; m = 3 for cubic mean) */\
       +        X(POWER, power, (a = (TYPE)power, b = (TYPE)(1. / power), sn = (TYPE)1 / sn), 0,\
       +          img += nnpow(val, a), img = nnpow(img, b) * sn)\
       +        /* Stolarsky mean */\
       +        X(STOLARSKY, stolarsky, (a = (TYPE)power, b = (TYPE)(1. / (power - 1.))), 0, auxs[j] = val,\
       +          img = auxs[0] == auxs[1] ? auxs[0] :\
       +                nnpow((nnpow(auxs[0], auxs[0]) - nnpow(auxs[1], auxs[1])) /\
       +                      (a * (auxs[0] - auxs[1])), b))\
       +        /* variance */\
       +        X(VARIANCE, variance, sn = (TYPE)1 / sn, 0, (img += val * val, aux += val),\
       +          img = (img - aux * aux * sn) * sn)\
       +        /* Heinz mean */\
       +        X(HEINZ, heinz, (a = (TYPE)power, b = (TYPE)1 - a), 0, auxs[j] = val,\
       +          img = (nnpow(auxs[0], a) * nnpow(auxs[1], b) + nnpow(auxs[0], b) * nnpow(auxs[1], 0)) / (TYPE)2)
       +
       +#define X(V, ...) V,
       +enum method { LIST_MEANS() };
       +#undef X
       +
       +static double power;
       +
       +#define aux (*auxs)
       +#define MAKE_PROCESS(PIXFMT, TYPE,\
       +          _1, NAME, INIT, INITIAL, PROCESS_SUBCELL, FINALISE_SUBCELL)\
       +        static void\
       +        process_##PIXFMT##_##NAME(struct stream *streams, size_t n_streams, size_t n)\
       +        {\
       +                size_t i, j;\
       +                TYPE img, auxs[2], val, a, b, sn = (TYPE)n_streams;\
       +                INIT;\
       +                for (i = 0; i < n; i += sizeof(TYPE)) {\
       +                        img = auxs[0] = auxs[1] = INITIAL;\
       +                        for (j = 0; j < n_streams; j++) {\
       +                                val = *(TYPE *)(streams[j].buf + i);\
       +                                PROCESS_SUBCELL;\
       +                        }\
       +                        FINALISE_SUBCELL;\
       +                        *(TYPE *)(streams->buf + i) = img;\
       +                }\
       +                (void) aux, (void) a, (void) b, (void) sn;\
       +        }
       +#define X(...) MAKE_PROCESS(lf, double, __VA_ARGS__)
       +LIST_MEANS(double)
       +#undef X
       +#define X(...) MAKE_PROCESS(f, float, __VA_ARGS__)
       +LIST_MEANS(float)
       +#undef X
       +#undef MAKE_PROCESS
       +#undef aux
       +
       +#define X(ID, NAME, ...) [ID] = process_lf_##NAME,
       +static const process_func process_functions_lf[] = { LIST_MEANS() };
       +#undef X
       +
       +#define X(ID, NAME, ...) [ID] = process_f_##NAME,
       +static const process_func process_functions_f[] = { LIST_MEANS() };
       +#undef X
       +
       +int
       +main(int argc, char *argv[])
       +{
       +        struct stream *streams;
       +        process_func process;
       +        size_t frames = SIZE_MAX, tmp;
       +        enum method method = ARITHMETIC;
       +        int i, two = 0;
       +
       +        ARGBEGIN {
       +        case 'g':
       +                method = GEOMETRIC;
       +                break;
       +        case 'h':
       +                method = HARMONIC;
       +                break;
       +        case 'H':
       +                method = HERONIAN;
       +                two = 1;
       +                break;
       +        case 'i':
       +                method = IDENTRIC;
       +                two = 1;
       +                break;
       +        case 'l':
       +                method = LEHMER;
       +                power = etolf_flag('l', UARGF());
       +                break;
       +        case 'L':
       +                method = LOGARITHMIC;
       +                two = 1;
       +                break;
       +        case 'p':
       +                method = POWER;
       +                power = etolf_flag('p', UARGF());
       +                break;
       +        case 's':
       +                method = STOLARSKY;
       +                two = 1;
       +                power = etolf_flag('s', UARGF());
       +                break;
       +        case 'v':
       +                method = VARIANCE;
       +                break;
       +        case 'z':
       +                method = HEINZ;
       +                two = 1;
       +                power = etolf_flag('z', UARGF());
       +                break;
       +        default:
       +                usage();
       +        } ARGEND;
       +
       +        if (argc < 2 || (argc > 2 && two))
       +                usage();
       +
       +        streams = alloca((size_t)argc * sizeof(*streams));
       +        for (i = 0; i < argc; i++) {
       +                eopen_stream(streams + i, argv[i]);
       +                if (streams[i].frames && streams[i].frames < frames)
       +                        frames = streams[i].frames;
       +        }
       +
       +        if (streams->encoding == DOUBLE)
       +                process = process_functions_lf[method];
       +        else
       +                process = process_functions_f[method];
       +
       +        tmp = streams->frames, streams->frames = frames;
       +        fprint_stream_head(stdout, streams);
       +        efflush(stdout, "<stdout>");
       +        streams->frames = tmp;
       +        process_multiple_streams(streams, (size_t)argc, STDOUT_FILENO, "<stdout>", 1, process);
       +        return 0;
       +}
   DIR diff --git a/src/blind-spatial-mean.c b/src/blind-spatial-mean.c
       @@ -2,7 +2,7 @@
        #include "common.h"
        
        USAGE("[-g | -h | -l power | -p power | -v]")
       -/* TODO add [-w weight-stream] for -l */
       +/* TODO add [-w weight-stream] for [-ghlpv] */
        
        /* Because the syntax for a function returning a function pointer is disgusting. */
        typedef void (*process_func)(struct stream *stream);
   DIR diff --git a/src/blind-temporal-mean.c b/src/blind-temporal-mean.c
       @@ -2,7 +2,7 @@
        #include "common.h"
        
        USAGE("[-g | -h | -l power | -p power | -v]")
       -/* TODO add [-w weight-stream] for -l */
       +/* TODO add [-w weight-stream] for [-ghlpv] */
        
        /* Because the syntax for a function returning a function pointer is disgusting. */
        typedef void (*process_func)(struct stream *stream, void *buffer, void *image, size_t frame);