URI: 
       blind*-mean: add -d and replace power with power-stream - 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 ffeba5cae6ebf01f421e11eee2c4d050da0bb3f3
   DIR parent bd8018a737281770159231c060f3bfd30788a430
  HTML Author: Mattias Andrée <maandree@kth.se>
       Date:   Wed, 26 Jul 2017 16:26:05 +0200
       
       blind*-mean: add -d and replace power with power-stream
       
       Signed-off-by: Mattias Andrée <maandree@kth.se>
       
       Diffstat:
         M TODO                                |       2 --
         M man/blind-mean.1                    |      52 ++++++++++++++++++-------------
         M man/blind-spatial-mean.1            |      24 +++++++++++++++---------
         M man/blind-temporal-mean.1           |      29 +++++++++++++++++++----------
         M src/blind-mean.c                    |      53 +++++++++++++++++++------------
         M src/blind-spatial-mean.c            |      52 +++++++++++++++++++++----------
         M src/blind-temporal-mean.c           |      60 +++++++++++++++++++------------
       
       7 files changed, 169 insertions(+), 103 deletions(-)
       ---
   DIR diff --git a/TODO b/TODO
       @@ -1,5 +1,3 @@
       -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
   DIR diff --git a/man/blind-mean.1 b/man/blind-mean.1
       @@ -3,14 +3,14 @@
        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
       +[-d | -g | -h | -H | -i | -l
       +.I power-stream
        | -L | -p
       -.I power
       +.I power-stream
        | -s
       -.I power
       +.I power-stream
        | -v | -z
       -.IR power ]
       +.IR power-stream ]
        .I stream-1
        .IR stream-2 \ ...
        .SH DESCRIPTION
       @@ -26,24 +26,29 @@ Unless otherwise specified, the arithmetic mean
        is calculated.
        .SH OPTIONS
        .TP
       +.B -d
       +Calculate the standard deviation.
       +.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 .
       +.B -i
       +Calculate the identric mean.
       +.TP
       +.BR -l \ \fIpower-stream\fP
       +Calculate the Lehmer mean with the power
       +specified in the same frame and pixel in
       +the video
       +.IR power-stream .
        .TP
        .B -L
        Calculate the logarithmic mean.
       @@ -51,15 +56,17 @@ No arguments after
        .I stream-2
        are allowed if this flag is used.
        .TP
       -.BR -p \ \fIpower\fP
       +.BR -p \ \fIpower-stream\fP
        Calculate the power mean (Hölder mean) with
       -the specified
       -.IR power .
       +the power specified in the same frame and
       +pixel in the video
       +.IR power-stream .
        .TP
       -.BR -s \ \fIpower\fP
       -Calculate the Stolarsky mean with
       -the specified
       -.IR power .
       +.BR -s \ \fIpower-stream\fP
       +Calculate the Stolarsky mean with the power
       +specified in the same frame and pixel in
       +the video
       +.IR power-stream .
        No arguments after
        .I stream-2
        are allowed if this flag is used.
       @@ -67,10 +74,11 @@ are allowed if this flag is used.
        .B -v
        Calculate the variance.
        .TP
       -.BR -z \ \fIpower\fP
       -Calculate the Heinz meanw ith
       -the specified
       -.IR power .
       +.BR -z \ \fIpower-stream\fP
       +Calculate the Heinz mean with the power
       +specified in the same frame and pixel in
       +the video
       +.IR power-stream .
        No arguments after
        .I stream-2
        are allowed if this flag is used.
   DIR diff --git a/man/blind-spatial-mean.1 b/man/blind-spatial-mean.1
       @@ -3,10 +3,10 @@
        blind-spatial-mean - Calculate the mean over all pixel for each frame in a video
        .SH SYNOPSIS
        .B blind-spatial-mean
       -[-g | -h | -l
       -.I power
       +[-d | -g | -h | -l
       +.I power-stream
        | -p
       -.I power
       +.I power-stream
        | -v]
        .SH DESCRIPTION
        .B blind-spatial-mean
       @@ -19,20 +19,26 @@ Unless otherwise specified, the arithmetic mean
        is calculated.
        .SH OPTIONS
        .TP
       +.B -d
       +Calculate the standard deviation.
       +.TP
        .B -g
        Calculate the geometric mean.
        .TP
        .B -h
        Calculate the harmonic mean.
        .TP
       -.BR -l \ \fIpower\fP
       -Calculate the Lehmer mean with the specified
       -.IR power .
       +.BR -l \ \fIpower-stream\fP
       +Calculate the Lehmer mean with the power
       +specified in the same single-pixel frame
       +in the video
       +.IR power-stream .
        .TP
       -.BR -p \ \fIpower\fP
       +.BR -p \ \fIpower-stream\fP
        Calculate the power mean (Hölder mean) with
       -the specified
       -.IR power .
       +the power specified in the same single-pixel
       +frame in the video
       +.IR power-stream .
        .TP
        .B -v
        Calculate the variance.
   DIR diff --git a/man/blind-temporal-mean.1 b/man/blind-temporal-mean.1
       @@ -3,10 +3,10 @@
        blind-temporal-mean - Calculate the mean over all frames in a video for each pixel
        .SH SYNOPSIS
        .B blind-temporal-mean
       -[-g | -h | -l
       -.I power
       +[-d | -g | -h | -l
       +.I power-stream
        | -p
       -.I power
       +.I power-stream
        | -v]
        .SH DESCRIPTION
        .B blind-temporal-mean
       @@ -19,20 +19,26 @@ Unless otherwise specified, the arithmetic mean
        is calculated.
        .SH OPTIONS
        .TP
       +.B -d
       +Calculate the standard deviation.
       +.TP
        .B -g
        Calculate the geometric mean.
        .TP
        .B -h
        Calculate the harmonic mean.
        .TP
       -.BR -l \ \fIpower\fP
       -Calculate the Lehmer mean with the specified
       -.IR power .
       +.BR -l \ \fIpower-stream\fP
       +Calculate the Lehmer mean with the power
       +specified in the same pixel in the single-frame
       +video
       +.IR power-stream .
        .TP
       -.BR -p \ \fIpower\fP
       +.BR -p \ \fIpower-stream\fP
        Calculate the power mean (Hölder mean) with
       -the specified
       -.IR power .
       +the power specified in the same pixel in the
       +single-frame video
       +.IR power-stream .
        .TP
        .B -v
        Calculate the variance.
       @@ -40,10 +46,13 @@ Calculate the variance.
        .B blind-temporal-mean
        requires enough free memory to load two full frames memory.
        A frame requires 32 bytes per pixel it contains. If
       -.B -l
       +.B -p
        or
        .B -v
        is used, enough free memory to load three full frames
       +memory is required. If
       +.B -l
       +is used, enough free memory to load four full frames
        memory is required.
        .P
        .B blind-temporal-mean
   DIR diff --git a/src/blind-mean.c b/src/blind-mean.c
       @@ -1,7 +1,7 @@
        /* 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 ...")
       +USAGE("[-d | -g | -h | -H | -i | -l power-stream | -L | -p power-stream | -s power-stream | -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. */
       @@ -18,6 +18,9 @@ typedef void (*process_func)(struct stream *streams, size_t n_streams, size_t n)
        #define LIST_MEANS(TYPE)\
                /* [default] arithmetic mean */\
                X(ARITHMETIC, arithmetic, sn = (TYPE)1 / sn, 0, img += val, img *= sn) \
       +        /* standard deviation */\
       +        X(STANDARD_DEVIATION, sd, sn = (TYPE)1 / sn, 0, (img += val * val, aux += val),\
       +          img = nnpow((img - aux * aux * sn) * sn, (TYPE)0.5))\
                /* geometric mean */\
                X(GEOMETRIC, geometric, sn = (TYPE)1 / sn, 1, img *= val, img = nnpow(img, sn))\
                /* harmonic mean */\
       @@ -30,32 +33,32 @@ typedef void (*process_func)(struct stream *streams, size_t n_streams, size_t n)
                  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)\
       +        X(LEHMER, lehmer,, 0, (img += nnpow(val, *pows), aux += nnpow(val, *pows - (TYPE)1)), 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)\
       +        X(POWER, power, sn = (TYPE)1 / sn, 0,\
       +          img += nnpow(val, *pows), img = nnpow(img, (TYPE)1 / *pows) * sn)\
                /* Stolarsky mean */\
       -        X(STOLARSKY, stolarsky, (a = (TYPE)power, b = (TYPE)(1. / (power - 1.))), 0, auxs[j] = val,\
       +        X(STOLARSKY, stolarsky,, 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))\
       +                nnpow((nnpow(auxs[0], *pows) - nnpow(auxs[1], *pows)) /\
       +                      (*pows * (auxs[0] - auxs[1])), (TYPE)1 / (*pows - (TYPE)1)))\
                /* 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)
       +        X(HEINZ, heinz,, 0, auxs[j] = val,\
       +          img = (nnpow(auxs[0], *pows) * nnpow(auxs[1], (TYPE)1 - *pows) +\
       +                 nnpow(auxs[0], (TYPE)1 - *pows) * nnpow(auxs[1], *pows)) / (TYPE)2)
        
        #define X(V, ...) V,
        enum method { LIST_MEANS() };
        #undef X
        
       -static double power;
       +static const char *power_file = NULL;
        
        #define aux (*auxs)
        #define MAKE_PROCESS(PIXFMT, TYPE,\
       @@ -64,9 +67,12 @@ static double power;
                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;\
       +                TYPE img, auxs[2], val, a, sn;\
       +                TYPE *pows = power_file ? (TYPE *)(streams[n_streams - 1].buf) : NULL;\
       +                n_streams -= (size_t)!!power_file;\
       +                sn = (TYPE)n_streams;\
                        INIT;\
       -                for (i = 0; i < n; i += sizeof(TYPE)) {\
       +                for (i = 0; i < n; i += sizeof(TYPE), pows++) {\
                                img = auxs[0] = auxs[1] = INITIAL;\
                                for (j = 0; j < n_streams; j++) {\
                                        val = *(TYPE *)(streams[j].buf + i);\
       @@ -75,7 +81,7 @@ static double power;
                                FINALISE_SUBCELL;\
                                *(TYPE *)(streams->buf + i) = img;\
                        }\
       -                (void) aux, (void) a, (void) b, (void) sn;\
       +                (void) aux, (void) a, (void) pows, (void) sn;\
                }
        #define X(...) MAKE_PROCESS(lf, double, __VA_ARGS__)
        LIST_MEANS(double)
       @@ -103,7 +109,11 @@ main(int argc, char *argv[])
                enum method method = ARITHMETIC;
                int i, two = 0;
        
       +
                ARGBEGIN {
       +        case 'd':
       +                method = STANDARD_DEVIATION;
       +                break;
                case 'g':
                        method = GEOMETRIC;
                        break;
       @@ -120,7 +130,7 @@ main(int argc, char *argv[])
                        break;
                case 'l':
                        method = LEHMER;
       -                power = etolf_flag('l', UARGF());
       +                power_file = UARGF();
                        break;
                case 'L':
                        method = LOGARITHMIC;
       @@ -128,12 +138,12 @@ main(int argc, char *argv[])
                        break;
                case 'p':
                        method = POWER;
       -                power = etolf_flag('p', UARGF());
       +                power_file = UARGF();
                        break;
                case 's':
                        method = STOLARSKY;
                        two = 1;
       -                power = etolf_flag('s', UARGF());
       +                power_file = UARGF();
                        break;
                case 'v':
                        method = VARIANCE;
       @@ -141,7 +151,7 @@ main(int argc, char *argv[])
                case 'z':
                        method = HEINZ;
                        two = 1;
       -                power = etolf_flag('z', UARGF());
       +                power_file = UARGF();
                        break;
                default:
                        usage();
       @@ -150,12 +160,14 @@ main(int argc, char *argv[])
                if (argc < 2 || (argc > 2 && two))
                        usage();
        
       -        streams = alloca((size_t)argc * sizeof(*streams));
       +        streams = alloca((size_t)(argc + !!power_file) * 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 (power_file != NULL)
       +                eopen_stream(streams + argc, power_file);
        
                if (streams->encoding == DOUBLE)
                        process = process_functions_lf[method];
       @@ -166,6 +178,7 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, streams);
                efflush(stdout, "<stdout>");
                streams->frames = tmp;
       -        process_multiple_streams(streams, (size_t)argc, STDOUT_FILENO, "<stdout>", 1, process);
       +        process_multiple_streams(streams, (size_t)(argc + !!power_file),
       +                                 STDOUT_FILENO, "<stdout>", 1, process);
                return 0;
        }
   DIR diff --git a/src/blind-spatial-mean.c b/src/blind-spatial-mean.c
       @@ -1,12 +1,13 @@
        /* See LICENSE file for copyright and license details. */
        #include "common.h"
        
       -USAGE("[-g | -h | -l power | -p power | -v]")
       +USAGE("[-d | -g | -h | -l power-stream | -p power-stream | -v]")
        /* 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);
        
       +#define C (j & 3)
        /*
         * X-parameter 1: method enum value
         * X-parameter 2: identifier-friendly name
       @@ -17,37 +18,41 @@ typedef void (*process_func)(struct stream *stream);
         */
        #define LIST_MEANS(TYPE)\
                /* [default] arithmetic mean */\
       -        X(ARITHMETIC, arithmetic,, 0, img[j & 3] += *buf, img[j & 3] /= pixels)\
       +        X(ARITHMETIC, arithmetic,, 0, img[C] += *buf, img[C] /= pixels)\
       +        /* standard deviation */\
       +        X(STANDARD_DEVIATION, sd,, 0, (img[C] += *buf * *buf, aux[C] += *buf),\
       +          img[C] = nnpow((img[C] - aux[C] * aux[C] / pixels) / pixels, (TYPE)0.5)) \
                /* geometric mean */\
       -        X(GEOMETRIC, geometric,, 1, img[j & 3] *= *buf, img[j & 3] = nnpow(img[j & 3], 1 / pixels))\
       +        X(GEOMETRIC, geometric,, 1, img[C] *= *buf, img[C] = nnpow(img[C], 1 / pixels))\
                /* harmonic mean */\
       -        X(HARMONIC, harmonic,, 0, img[j & 3] += (TYPE)1 / *buf, img[j & 3] = pixels / img[j & 3])\
       +        X(HARMONIC, harmonic,, 0, img[C] += (TYPE)1 / *buf, img[C] = pixels / img[C])\
                /* Lehmer mean */\
       -        X(LEHMER, lehmer, (a = (TYPE)power, b = a - (TYPE)1), 0,\
       -          (img[j & 3] += nnpow(*buf, a), aux[j & 3] += nnpow(*buf, b)), img[j & 3] /= aux[j & 3])\
       +        X(LEHMER, lehmer, (a[0] = powers[0] - (TYPE)1, a[1] = powers[1] - (TYPE)1,\
       +                           a[2] = powers[2] - (TYPE)1, a[3] = powers[3] - (TYPE)1), 0,\
       +          (img[C] += nnpow(*buf, powers[C]), aux[C] += nnpow(*buf, a[C])), img[C] /= aux[C])\
                /* power mean (Hölder mean) (m = 2 for root square mean; m = 3 for cubic mean) */\
       -        X(POWER, power, a = (TYPE)power, 0, img[j & 3] += nnpow(*buf, a),\
       -          img[j & 3] = nnpow(img[j & 3], (TYPE)(1. / power)) / pixels)\
       +        X(POWER, power,, 0, img[C] += nnpow(*buf, powers[C]),\
       +          img[C] = nnpow(img[C], (TYPE)1 / powers[C]) / pixels)\
                /* variance */\
       -        X(VARIANCE, variance,, 0, (img[j & 3] += *buf * *buf, aux[j & 3] += *buf),\
       -          img[j & 3] = (img[j & 3] - aux[j & 3] * aux[j & 3] / pixels) / pixels)
       +        X(VARIANCE, variance,, 0, (img[C] += *buf * *buf, aux[C] += *buf),\
       +          img[C] = (img[C] - aux[C] * aux[C] / pixels) / pixels)
        
        #define X(V, ...) V,
        enum method { LIST_MEANS() };
        #undef X
        
       -static double power;
       +static struct stream power;
       +static const char *power_file = NULL;
        
        #define MAKE_PROCESS(PIXFMT, TYPE,\
                             _1, NAME, INIT, INITIAL, PROCESS_SUBCELL, FINALISE_SUBCELL)\
                static void\
                process_##PIXFMT##_##NAME(struct stream *stream)\
                {\
       -                TYPE img[4], aux[4], *buf, a, b;\
       +                TYPE img[4], aux[4], *buf, a[4], powers[4];\
                        TYPE pixels = (TYPE)(stream->frame_size / sizeof(img));\
                        size_t i, n, j = 0, m = stream->frame_size / sizeof(*img);\
                        int first = 1;\
       -                INIT;\
                        do {\
                                n = stream->ptr / stream->pixel_size * stream->n_chan;\
                                buf = (TYPE *)(stream->buf);\
       @@ -60,6 +65,9 @@ static double power;
                                                        ewriteall(STDOUT_FILENO, img, sizeof(img), "<stdout>");\
                                                }\
                                                first = 0;\
       +                                        if (power_file && !eread_frame(&power, powers))\
       +                                                return;\
       +                                        INIT;\
                                                img[0] = aux[0] = INITIAL;\
                                                img[1] = aux[1] = INITIAL;\
                                                img[2] = aux[2] = INITIAL;\
       @@ -75,7 +83,7 @@ static double power;
                                        FINALISE_SUBCELL;\
                                ewriteall(STDOUT_FILENO, img, sizeof(img), "<stdout>");\
                        }\
       -                (void) aux, (void) a, (void) b, (void) pixels;\
       +                (void) aux, (void) a, (void) powers, (void) pixels;\
                }
        #define X(...) MAKE_PROCESS(lf, double, __VA_ARGS__)
        LIST_MEANS(double)
       @@ -84,6 +92,7 @@ LIST_MEANS(double)
        LIST_MEANS(float)
        #undef X
        #undef MAKE_PROCESS
       +#undef C
        
        #define X(ID, NAME, ...) [ID] = process_lf_##NAME,
        static const process_func process_functions_lf[] = { LIST_MEANS() };
       @@ -101,6 +110,9 @@ main(int argc, char *argv[])
                enum method method = ARITHMETIC;
        
                ARGBEGIN {
       +        case 'd':
       +                method = STANDARD_DEVIATION;
       +                break;
                case 'g':
                        method = GEOMETRIC;
                        break;
       @@ -109,11 +121,11 @@ main(int argc, char *argv[])
                        break;
                case 'l':
                        method = LEHMER;
       -                power = etolf_flag('l', UARGF());
       +                power_file = UARGF();
                        break;
                case 'p':
                        method = POWER;
       -                power = etolf_flag('p', UARGF());
       +                power_file = UARGF();
                        break;
                case 'v':
                        method = VARIANCE;
       @@ -126,13 +138,19 @@ main(int argc, char *argv[])
                        usage();
        
                eopen_stream(&stream, NULL);
       +        if (power_file != NULL) {
       +                eopen_stream(&power, power_file);
       +                if (power.width != 1 || power.height != 1)
       +                        eprintf("%s: videos do not have the 1x1 geometry\n", power_file);
       +                if (strcmp(power.pixfmt, stream.pixfmt))
       +                        eprintf("videos use incompatible pixel formats\n");
       +        }
        
                if (stream.encoding == DOUBLE)
                        process = process_functions_lf[method];
                else
                        process = process_functions_f[method];
        
       -
                if (DPRINTF_HEAD(STDOUT_FILENO, stream.frames, 1, 1, stream.pixfmt) < 0)
                        eprintf("dprintf:");
                process(&stream);
   DIR diff --git a/src/blind-temporal-mean.c b/src/blind-temporal-mean.c
       @@ -1,7 +1,7 @@
        /* See LICENSE file for copyright and license details. */
        #include "common.h"
        
       -USAGE("[-g | -h | -l power | -p power | -v]")
       +USAGE("[-d | -g | -h | -l power-stream | -p power-stream | -v]")
        /* TODO add [-w weight-stream] for [-ghlpv] */
        
        /* Because the syntax for a function returning a function pointer is disgusting. */
       @@ -19,24 +19,26 @@ typedef void (*process_func)(struct stream *stream, void *buffer, void *image, s
         */
        #define LIST_MEANS(TYPE)\
                /* [default] arithmetic mean */\
       -        X(ARITHMETIC, arithmetic, 1, COPY_FRAME,, *img1 += *buf,\
       -          a = (TYPE)1 / (TYPE)frame, *img1 *= a)\
       +        X(ARITHMETIC, arithmetic, 1, COPY_FRAME,, *img += *buf,\
       +          a = (TYPE)1 / (TYPE)frame, *img *= a)\
       +        /* standard deviation */\
       +        X(STANDARD_DEVIATION, sd, 2, ZERO_AND_PROCESS_FRAME,, (*img += *buf * *buf, *aux += *buf),\
       +          a = (TYPE)1 / (TYPE)frame, *img = nnpow((*img - *aux * *aux * a) * a, (TYPE)0.5))\
                /* geometric mean */\
       -        X(GEOMETRIC, geometric, 1, COPY_FRAME,, *img1 *= *buf,\
       -          a = (TYPE)1 / (TYPE)frame, *img1 = nnpow(*img1, a))\
       +        X(GEOMETRIC, geometric, 1, COPY_FRAME,, *img *= *buf,\
       +          a = (TYPE)1 / (TYPE)frame, *img = nnpow(*img, a))\
                /* harmonic mean */\
       -        X(HARMONIC, harmonic, 1, ZERO_AND_PROCESS_FRAME,, *img1 += (TYPE)1 / *buf,\
       -          a = (TYPE)frame, *img1 = a / *img1)\
       +        X(HARMONIC, harmonic, 1, ZERO_AND_PROCESS_FRAME,, *img += (TYPE)1 / *buf,\
       +          a = (TYPE)frame, *img = a / *img)\
                /* Lehmer mean */\
       -        X(LEHMER, lehmer, 2, ZERO_AND_PROCESS_FRAME, (a = (TYPE)power, b = a - (TYPE)1),\
       -          (*img1 += nnpow(*buf, a), *img2 += nnpow(*buf, b)),, *img1 /= *img2)\
       +        X(LEHMER, lehmer, 2, ZERO_AND_PROCESS_FRAME,,\
       +          (*img += nnpow(*buf, *pows), *aux += nnpow(*buf, *pows - (TYPE)1)),, *img /= *aux)\
                /* power mean (Hölder mean) (m = 2 for root square mean; m = 3 for cubic mean) */\
       -        X(POWER, power, 1, ZERO_AND_PROCESS_FRAME, a = (TYPE)power,\
       -          *img1 += nnpow(*buf, a), (a = (TYPE)1 / (TYPE)frame, b = (TYPE)(1. / power)), \
       -          *img1 = a * nnpow(*img1, b))\
       +        X(POWER, power, 1, ZERO_AND_PROCESS_FRAME,, *img += nnpow(*buf, *pows),\
       +          a = (TYPE)1 / (TYPE)frame, *img = a * nnpow(*img, (TYPE)1 / *pows))\
                /* variance */\
       -        X(VARIANCE, variance, 2, ZERO_AND_PROCESS_FRAME,, (*img1 += *buf * *buf, *img2 += *buf),\
       -          a = (TYPE)1 / (TYPE)frame, *img1 = (*img1 - *img2 * *img2 * a) * a)
       +        X(VARIANCE, variance, 2, ZERO_AND_PROCESS_FRAME,, (*img += *buf * *buf, *aux += *buf),\
       +          a = (TYPE)1 / (TYPE)frame, *img = (*img - *aux * *aux * a) * a)
        
        enum first_frame_action {
                COPY_FRAME,
       @@ -48,31 +50,31 @@ enum first_frame_action {
        enum method { LIST_MEANS() };
        #undef X
        
       -static double power;
       +static void *powerbuf = NULL;
        
        #define MAKE_PROCESS(PIXFMT, TYPE,\
                             _1, NAME, _3, _4, PRE_PROCESS, PROCESS_SUBCELL, PRE_FINALISE, FINALISE_SUBCELL)\
                static void\
                process_##PIXFMT##_##NAME(struct stream *stream, void *buffer, void *image, size_t frame)\
                {\
       -                TYPE *buf = buffer, *img1 = image, a, b;\
       -                TYPE *img2 = (TYPE *)(((char *)image) + stream->frame_size);\
       +                TYPE *buf = buffer, *img = image, a, *pows = powerbuf;\
       +                TYPE *aux = (TYPE *)(((char *)image) + stream->frame_size);\
                        size_t x, y, z;\
                        if (!buf) {\
                                PRE_FINALISE;\
                                for (z = 0; z < stream->n_chan; z++)\
                                        for (y = 0; y < stream->height; y++)\
       -                                        for (x = 0; x < stream->width; x++, img1++, img2++)\
       +                                        for (x = 0; x < stream->width; x++, img++, aux++, pows++)\
                                                        FINALISE_SUBCELL;\
                        } else {\
                                PRE_PROCESS;\
                                for (z = 0; z < stream->n_chan; z++)\
                                        for (y = 0; y < stream->height; y++)\
       -                                        for (x = 0; x < stream->width; x++, img1++, img2++, buf++) {\
       +                                        for (x = 0; x < stream->width; x++, img++, aux++, pows++, buf++) { \
                                                        PROCESS_SUBCELL;\
                                                }\
                        }\
       -                (void) img2, (void) a, (void) b, (void) frame;\
       +                (void) aux, (void) a, (void) pows, (void) frame;\
                }
        #define X(...) MAKE_PROCESS(lf, double, __VA_ARGS__)
        LIST_MEANS(double)
       @@ -93,14 +95,18 @@ static const process_func process_functions_f[] = { LIST_MEANS() };
        int
        main(int argc, char *argv[])
        {
       -        struct stream stream;
       +        struct stream stream, power;
                void *buf, *img;
                process_func process;
                size_t frames, images;
                enum method method = ARITHMETIC;
                enum first_frame_action first_frame_action;
       +        const char *power_file = NULL;
        
                ARGBEGIN {
       +        case 'd':
       +                method = STANDARD_DEVIATION;
       +                break;
                case 'g':
                        method = GEOMETRIC;
                        break;
       @@ -109,11 +115,11 @@ main(int argc, char *argv[])
                        break;
                case 'l':
                        method = LEHMER;
       -                power = etolf_flag('l', UARGF());
       +                power_file = UARGF();
                        break;
                case 'p':
                        method = POWER;
       -                power = etolf_flag('p', UARGF());
       +                power_file = UARGF();
                        break;
                case 'v':
                        method = VARIANCE;
       @@ -138,6 +144,13 @@ main(int argc, char *argv[])
        #undef X
        
                eopen_stream(&stream, NULL);
       +        if (power_file != NULL) {
       +                eopen_stream(&power, power_file);
       +                echeck_compat(&stream, &power);
       +                powerbuf = emalloc(power.frame_size);
       +                if (!eread_frame(&power, powerbuf))
       +                        eprintf("%s is no frames\n", power_file);
       +        }
        
                if (stream.encoding == DOUBLE)
                        process = process_functions_lf[method];
       @@ -169,5 +182,6 @@ main(int argc, char *argv[])
                ewriteall(STDOUT_FILENO, img, stream.frame_size, "<stdout>");
                free(buf);
                free(img);
       +        free(powerbuf);
                return 0;
        }