aboutsummaryrefslogtreecommitdiffstats
path: root/src/blind-spatial-mean.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2017-07-26 16:26:05 +0200
committerMattias Andrée <maandree@kth.se>2017-07-26 16:26:05 +0200
commitffeba5cae6ebf01f421e11eee2c4d050da0bb3f3 (patch)
tree937c4e5d67df787bd86135d56b5e62c3b59b7db8 /src/blind-spatial-mean.c
parentAdd blind-mean (diff)
downloadblind-ffeba5cae6ebf01f421e11eee2c4d050da0bb3f3.tar.gz
blind-ffeba5cae6ebf01f421e11eee2c4d050da0bb3f3.tar.bz2
blind-ffeba5cae6ebf01f421e11eee2c4d050da0bb3f3.tar.xz
blind*-mean: add -d and replace power with power-stream
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src/blind-spatial-mean.c')
-rw-r--r--src/blind-spatial-mean.c52
1 files changed, 35 insertions, 17 deletions
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);