commit ffeba5cae6ebf01f421e11eee2c4d050da0bb3f3
Author:     Mattias Andrée <[email protected]>
AuthorDate: Wed Jul 26 16:26:05 2017 +0200
Commit:     Mattias Andrée <[email protected]>
CommitDate: Wed Jul 26 16:26:05 2017 +0200

    blind*-mean: add -d and replace power with power-stream
    
    Signed-off-by: Mattias Andrée <[email protected]>

diff --git a/TODO b/TODO
index f9cfc0c..50615d1 100644
--- 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
diff --git a/man/blind-mean.1 b/man/blind-mean.1
index cd2b331..e9de415 100644
--- 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.
diff --git a/man/blind-spatial-mean.1 b/man/blind-spatial-mean.1
index 315da1f..9bf9eac 100644
--- 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.
diff --git a/man/blind-temporal-mean.1 b/man/blind-temporal-mean.1
index 167c6c4..ef7d3dd 100644
--- 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
diff --git a/src/blind-mean.c b/src/blind-mean.c
index f445d25..8b7e97c 100644
--- 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;
 }
diff --git a/src/blind-spatial-mean.c b/src/blind-spatial-mean.c
index b4e54e5..5511a3f 100644
--- 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);
diff --git a/src/blind-temporal-mean.c b/src/blind-temporal-mean.c
index 8c442d0..4633d75 100644
--- 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;
 }

Reply via email to