aboutsummaryrefslogtreecommitdiffstats
path: root/src/blind-spatial-mean.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2017-07-25 22:12:23 +0200
committerMattias Andrée <maandree@kth.se>2017-07-25 22:12:23 +0200
commit835df7bd1e81852062dd70ce1a054fc9b510e50f (patch)
treede418467fc318adfcf5e3fdd8e75ea2a055386c9 /src/blind-spatial-mean.c
parentAdd ability to choose korn shell implementation (diff)
downloadblind-835df7bd1e81852062dd70ce1a054fc9b510e50f.tar.gz
blind-835df7bd1e81852062dd70ce1a054fc9b510e50f.tar.bz2
blind-835df7bd1e81852062dd70ce1a054fc9b510e50f.tar.xz
Fix blind-kernel and blind-temporal-mean,d add blind-{spatial,temporal}-arithm and blind-spatial-mean, and add support for multiple streams in blind-arithm
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rw-r--r--src/blind-spatial-mean.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/blind-spatial-mean.c b/src/blind-spatial-mean.c
new file mode 100644
index 0000000..848af2d
--- /dev/null
+++ b/src/blind-spatial-mean.c
@@ -0,0 +1,142 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-g | -h | -l power | -p power | -v]")
+/* TODO add [-w weight-stream] for -l */
+
+/* Because the syntax for a function returning a function pointer is disgusting. */
+typedef void (*process_func)(struct stream *stream);
+
+/*
+ * 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,, 0, img[j & 3] += *buf, img[j & 3] /= pixels)\
+ /* geometric mean */\
+ X(GEOMETRIC, geometric,, 1, img[j & 3] *= *buf, img[j & 3] = nnpow(img[j & 3], 1 / pixels))\
+ /* harmonic mean */\
+ X(HARMONIC, harmonic,, 0, img[j & 3] += (TYPE)1 / *buf, img[j & 3] = pixels / img[j & 3])\
+ /* 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])\
+ /* 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)\
+ /* 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)
+
+#define X(V, ...) V,
+enum method { LIST_MEANS() };
+#undef X
+
+static double power;
+
+#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 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);\
+ for (i = 0; i < n; i++, buf++, j++, j %= m) {\
+ if (!j) {\
+ if (!first) {\
+ for (j = 0; j < ELEMENTSOF(img); j++)\
+ FINALISE_SUBCELL;\
+ j = 0;\
+ ewriteall(STDOUT_FILENO, img, sizeof(img), "<stdout>");\
+ }\
+ first = 0;\
+ img[0] = aux[0] = INITIAL;\
+ img[1] = aux[1] = INITIAL;\
+ img[2] = aux[2] = INITIAL;\
+ img[3] = aux[3] = INITIAL;\
+ }\
+ PROCESS_SUBCELL;\
+ }\
+ n *= sizeof(TYPE);\
+ memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
+ } while (eread_stream(stream, SIZE_MAX));\
+ if (!first) {\
+ for (j = 0; j < ELEMENTSOF(img); j++)\
+ FINALISE_SUBCELL;\
+ ewriteall(STDOUT_FILENO, img, sizeof(img), "<stdout>");\
+ }\
+ (void) aux, (void) a, (void) b, (void) pixels;\
+ }
+#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
+
+#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 stream;
+ process_func process;
+ enum method method = ARITHMETIC;
+
+ ARGBEGIN {
+ case 'g':
+ method = GEOMETRIC;
+ break;
+ case 'h':
+ method = HARMONIC;
+ break;
+ case 'l':
+ method = LEHMER;
+ power = etolf_flag('l', UARGF());
+ break;
+ case 'p':
+ method = POWER;
+ power = etolf_flag('p', UARGF());
+ break;
+ case 'v':
+ method = VARIANCE;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ 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);
+ if (stream.ptr)
+ eprintf("%s: incomplete frame\n", stream.file);
+ return 0;
+}