blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

commit ffeba5cae6ebf01f421e11eee2c4d050da0bb3f3
parent bd8018a737281770159231c060f3bfd30788a430
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:
TODO | 2--
man/blind-mean.1 | 52++++++++++++++++++++++++++++++----------------------
man/blind-spatial-mean.1 | 24+++++++++++++++---------
man/blind-temporal-mean.1 | 29+++++++++++++++++++----------
src/blind-mean.c | 53+++++++++++++++++++++++++++++++++--------------------
src/blind-spatial-mean.c | 52+++++++++++++++++++++++++++++++++++-----------------
src/blind-temporal-mean.c | 60+++++++++++++++++++++++++++++++++++++-----------------------
7 files changed, 169 insertions(+), 103 deletions(-)

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 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. 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. 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 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; } 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); 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; }