Add blind-mean - blind - suckless command-line video editing utility | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit bd8018a737281770159231c060f3bfd30788a430 | |
parent 835df7bd1e81852062dd70ce1a054fc9b510e50f | |
Author: Mattias Andrée <[email protected]> | |
Date: Wed, 26 Jul 2017 00:24:39 +0200 | |
Add blind-mean | |
Signed-off-by: Mattias Andrée <[email protected]> | |
Diffstat: | |
M Makefile | 1 + | |
M README | 3 +++ | |
M TODO | 9 ++------- | |
M man/blind-arithm.1 | 1 + | |
A man/blind-mean.1 | 87 +++++++++++++++++++++++++++++… | |
M man/blind-spatial-arithm.1 | 1 + | |
M man/blind-spatial-mean.1 | 3 ++- | |
M man/blind-temporal-arithm.1 | 1 + | |
M man/blind-temporal-mean.1 | 1 + | |
M man/blind.7 | 3 +++ | |
A src/blind-mean.c | 171 +++++++++++++++++++++++++++++… | |
M src/blind-spatial-mean.c | 2 +- | |
M src/blind-temporal-mean.c | 2 +- | |
13 files changed, 275 insertions(+), 10 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
@@ -53,6 +53,7 @@ BIN =\ | |
blind-matrix-shear\ | |
blind-matrix-translate\ | |
blind-matrix-transpose\ | |
+ blind-mean\ | |
blind-mosaic\ | |
blind-mosaic-corners\ | |
blind-mosaic-edges\ | |
diff --git a/README b/README | |
@@ -156,6 +156,9 @@ UTILITIES | |
blind-matrix-transpose(1) | |
Create an affine 2D-transformation matrix for transposition | |
+ blind-mean(1) | |
+ Calcuate the mean over videos for each pixel in each frame | |
+ | |
blind-mosaic(1) | |
Redraw each frame in video as a mosaic | |
diff --git a/TODO b/TODO | |
@@ -1,3 +1,5 @@ | |
+blind-*-mean: replace power with power-stream | |
+ | |
blind-transform affine transformation by matrix multiplication,… | |
improve quality on downscaling (pixels' neighb… | |
blind-apply-map remap pixels (distortion) using the X and Y val… | |
@@ -24,13 +26,6 @@ blind-roberts-cross https://en.wikipedia.org/wiki/Rob… | |
--- https://en.wikipedia.org/wiki/Canny_edge_detector | |
--- https://en.wikipedia.org/wiki/Deriche_edge_detector | |
--- https://en.wikipedia.org/wiki/Edge_detection | |
-blind-mean mean of multiple streams | |
- means from blind-temporal-mean | |
- https://en.wikipedia.org/wiki/Heinz_mean | |
- https://en.wikipedia.org/wiki/Heronian_mean | |
- https://en.wikipedia.org/wiki/Identric_mean | |
- https://en.wikipedia.org/wiki/Logarithmic_mean | |
- https://en.wikipedia.org/wiki/Stolarsky_mean | |
blind-apply-icc apply ICC profile to video | |
blind-convex-gradient create a gradient in the shape of a convex lens | |
blind-concave-gradient create a gradient in the shape of a concave lens | |
diff --git a/man/blind-arithm.1 b/man/blind-arithm.1 | |
@@ -100,6 +100,7 @@ Do not modify the Z channel (the third channel). | |
.BR blind-spatial-arithm (1), | |
.BR blind-temporal-mean (1), | |
.BR blind-temporal-arithm (1), | |
+.BR blind-mean (1), | |
.BR blind-single-colour (1), | |
.BR blind-set-alpha (1), | |
.BR blind-set-luma (1), | |
diff --git a/man/blind-mean.1 b/man/blind-mean.1 | |
@@ -0,0 +1,87 @@ | |
+.TH BLIND-MEAN 1 blind | |
+.SH NAME | |
+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 | |
+| -L | -p | |
+.I power | |
+| -s | |
+.I power | |
+| -v | -z | |
+.IR power ] | |
+.I stream-1 | |
+.IR stream-2 \ ... | |
+.SH DESCRIPTION | |
+.B blind-mean | |
+reads videos from | |
+.I stream-1 | |
+and the files specified in all succeeding | |
+arguments, and for each pixel in each frame, | |
+calculates the mean of the videos, and prints | |
+the resulting video to stdout. | |
+.P | |
+Unless otherwise specified, the arithmetic mean | |
+is calculated. | |
+.SH OPTIONS | |
+.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 . | |
+.TP | |
+.B -L | |
+Calculate the logarithmic mean. | |
+No arguments after | |
+.I stream-2 | |
+are allowed if this flag is used. | |
+.TP | |
+.BR -p \ \fIpower\fP | |
+Calculate the power mean (Hölder mean) with | |
+the specified | |
+.IR power . | |
+.TP | |
+.BR -s \ \fIpower\fP | |
+Calculate the Stolarsky mean with | |
+the specified | |
+.IR power . | |
+No arguments after | |
+.I stream-2 | |
+are allowed if this flag is used. | |
+.TP | |
+.B -v | |
+Calculate the variance. | |
+.TP | |
+.BR -z \ \fIpower\fP | |
+Calculate the Heinz meanw ith | |
+the specified | |
+.IR power . | |
+No arguments after | |
+.I stream-2 | |
+are allowed if this flag is used. | |
+.SH SEE ALSO | |
+.BR blind (7), | |
+.BR blind-temporal-mean (1), | |
+.BR blind-spatial-mean (1), | |
+.BR blind-temporal-arithm (1), | |
+.BR blind-spatial-arithm (1), | |
+.BR blind-arithm (1), | |
+.BR blind-rewrite-head (1) | |
+.SH AUTHORS | |
+Mattias Andrée | |
+.RI < [email protected] > | |
diff --git a/man/blind-spatial-arithm.1 b/man/blind-spatial-arithm.1 | |
@@ -29,6 +29,7 @@ Select the highest operand. | |
.BR blind-arithm (1), | |
.BR blind-spatial-mean (1), | |
.BR blind-temporal-mean (1), | |
+.BR blind-mean (1), | |
.BR blind-rewrite-head (1) | |
.SH AUTHORS | |
Mattias Andrée | |
diff --git a/man/blind-spatial-mean.1 b/man/blind-spatial-mean.1 | |
@@ -38,10 +38,11 @@ the specified | |
Calculate the variance. | |
.SH SEE ALSO | |
.BR blind (7), | |
+.BR blind-temporal-mean (1), | |
+.BR blind-mean (1), | |
.BR blind-temporal-arithm (1), | |
.BR blind-spatial-arithm (1), | |
.BR blind-arithm (1), | |
-.BR blind-temporal-mean (1), | |
.BR blind-rewrite-head (1) | |
.SH AUTHORS | |
Mattias Andrée | |
diff --git a/man/blind-temporal-arithm.1 b/man/blind-temporal-arithm.1 | |
@@ -33,6 +33,7 @@ A frame requires 32 bytes per pixel it contains. | |
.BR blind-spatial-arithm (1), | |
.BR blind-spatial-mean (1), | |
.BR blind-arithm (1), | |
+.BR blind-mean (1), | |
.BR blind-rewrite-head (1) | |
.SH AUTHORS | |
Mattias Andrée | |
diff --git a/man/blind-temporal-mean.1 b/man/blind-temporal-mean.1 | |
@@ -54,6 +54,7 @@ is optimised for simplicity rather than memory usage. | |
.BR blind-spatial-arithm (1), | |
.BR blind-arithm (1), | |
.BR blind-spatial-mean (1), | |
+.BR blind-mean (1), | |
.BR blind-rewrite-head (1) | |
.SH AUTHORS | |
Mattias Andrée | |
diff --git a/man/blind.7 b/man/blind.7 | |
@@ -174,6 +174,9 @@ Create an affine 2D-transformation matrix for translation | |
.BR blind-matrix-transpose (1) | |
Create an affine 2D-transformation matrix for transposition | |
.TP | |
+.BR blind-mean (1) | |
+Calcuate the mean over videos for each pixel in each frame | |
+.TP | |
.BR blind-mosaic (1) | |
Redraw each frame in video as a mosaic | |
.TP | |
diff --git a/src/blind-mean.c b/src/blind-mean.c | |
@@ -0,0 +1,171 @@ | |
+/* 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 powe… | |
+/* TODO add [-w weight-stream] for [-ghlpv] */ | |
+ | |
+/* Because the syntax for a function returning a function pointer is disgustin… | |
+typedef void (*process_func)(struct stream *streams, size_t n_streams, size_t … | |
+ | |
+/* | |
+ * 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, sn = (TYPE)1 / sn, 0, img += val, img *= sn)… | |
+ /* geometric mean */\ | |
+ X(GEOMETRIC, geometric, sn = (TYPE)1 / sn, 1, img *= val, img = nnpow(… | |
+ /* harmonic mean */\ | |
+ X(HARMONIC, harmonic,, 0, img += (TYPE)1 / val, img = sn / img)\ | |
+ /* Heronian mean */\ | |
+ X(HERONIAN, heronian,, 0, auxs[j] = val,\ | |
+ img = (auxs[0] + sqrt(auxs[0] * auxs[1]) + auxs[1]) / (TYPE)3)\ | |
+ /* identric mean */\ | |
+ X(IDENTRIC, identric, a = (TYPE)(1. / M_E), 0, auxs[j] = val,\ | |
+ img = auxs[0] == auxs[1] ? auxs[0] :\ | |
+ nnpow(nnpow(auxs[0], auxs[0]) / nnpow(auxs[1], auxs[1]), auxs[… | |
+ /* Lehmer mean */\ | |
+ X(LEHMER, lehmer, (a = (TYPE)power, b = a - (TYPE)1), 0,\ | |
+ (img += nnpow(val, a), aux += nnpow(val, b)), img /= aux)\ | |
+ /* logarithmic mean */\ | |
+ X(LOGARITHMIC, logarithmic,, 0, auxs[j] = val,\ | |
+ img = auxs[0] == auxs[1] ? auxs[0] : (!auxs[0] || !auxs[1]) ? (TYPE)… | |
+ (auxs[1] - auxs[0]) / log(auxs[1] / auxs[0]))\ | |
+ /* power mean (Hölder mean) (m = 2 for root square mean; m = 3 for cu… | |
+ X(POWER, power, (a = (TYPE)power, b = (TYPE)(1. / power), sn = (TYPE)1… | |
+ img += nnpow(val, a), img = nnpow(img, b) * sn)\ | |
+ /* Stolarsky mean */\ | |
+ X(STOLARSKY, stolarsky, (a = (TYPE)power, b = (TYPE)(1. / (power - 1.)… | |
+ img = auxs[0] == auxs[1] ? auxs[0] :\ | |
+ nnpow((nnpow(auxs[0], auxs[0]) - nnpow(auxs[1], auxs[1])) /\ | |
+ (a * (auxs[0] - auxs[1])), b))\ | |
+ /* variance */\ | |
+ X(VARIANCE, variance, sn = (TYPE)1 / sn, 0, (img += val * val, aux += … | |
+ 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) * n… | |
+ | |
+#define X(V, ...) V, | |
+enum method { LIST_MEANS() }; | |
+#undef X | |
+ | |
+static double power; | |
+ | |
+#define aux (*auxs) | |
+#define MAKE_PROCESS(PIXFMT, TYPE,\ | |
+ _1, NAME, INIT, INITIAL, PROCESS_SUBCELL, FINALISE_SUBCELL)\ | |
+ static void\ | |
+ process_##PIXFMT##_##NAME(struct stream *streams, size_t n_streams, si… | |
+ {\ | |
+ size_t i, j;\ | |
+ TYPE img, auxs[2], val, a, b, sn = (TYPE)n_streams;\ | |
+ INIT;\ | |
+ for (i = 0; i < n; i += sizeof(TYPE)) {\ | |
+ img = auxs[0] = auxs[1] = INITIAL;\ | |
+ for (j = 0; j < n_streams; j++) {\ | |
+ val = *(TYPE *)(streams[j].buf + i);\ | |
+ PROCESS_SUBCELL;\ | |
+ }\ | |
+ FINALISE_SUBCELL;\ | |
+ *(TYPE *)(streams->buf + i) = img;\ | |
+ }\ | |
+ (void) aux, (void) a, (void) b, (void) sn;\ | |
+ } | |
+#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 | |
+#undef aux | |
+ | |
+#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 *streams; | |
+ process_func process; | |
+ size_t frames = SIZE_MAX, tmp; | |
+ enum method method = ARITHMETIC; | |
+ int i, two = 0; | |
+ | |
+ ARGBEGIN { | |
+ case 'g': | |
+ method = GEOMETRIC; | |
+ break; | |
+ case 'h': | |
+ method = HARMONIC; | |
+ break; | |
+ case 'H': | |
+ method = HERONIAN; | |
+ two = 1; | |
+ break; | |
+ case 'i': | |
+ method = IDENTRIC; | |
+ two = 1; | |
+ break; | |
+ case 'l': | |
+ method = LEHMER; | |
+ power = etolf_flag('l', UARGF()); | |
+ break; | |
+ case 'L': | |
+ method = LOGARITHMIC; | |
+ two = 1; | |
+ break; | |
+ case 'p': | |
+ method = POWER; | |
+ power = etolf_flag('p', UARGF()); | |
+ break; | |
+ case 's': | |
+ method = STOLARSKY; | |
+ two = 1; | |
+ power = etolf_flag('s', UARGF()); | |
+ break; | |
+ case 'v': | |
+ method = VARIANCE; | |
+ break; | |
+ case 'z': | |
+ method = HEINZ; | |
+ two = 1; | |
+ power = etolf_flag('z', UARGF()); | |
+ break; | |
+ default: | |
+ usage(); | |
+ } ARGEND; | |
+ | |
+ if (argc < 2 || (argc > 2 && two)) | |
+ usage(); | |
+ | |
+ streams = alloca((size_t)argc * 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 (streams->encoding == DOUBLE) | |
+ process = process_functions_lf[method]; | |
+ else | |
+ process = process_functions_f[method]; | |
+ | |
+ tmp = streams->frames, streams->frames = frames; | |
+ fprint_stream_head(stdout, streams); | |
+ efflush(stdout, "<stdout>"); | |
+ streams->frames = tmp; | |
+ process_multiple_streams(streams, (size_t)argc, STDOUT_FILENO, "<stdou… | |
+ return 0; | |
+} | |
diff --git a/src/blind-spatial-mean.c b/src/blind-spatial-mean.c | |
@@ -2,7 +2,7 @@ | |
#include "common.h" | |
USAGE("[-g | -h | -l power | -p power | -v]") | |
-/* TODO add [-w weight-stream] for -l */ | |
+/* TODO add [-w weight-stream] for [-ghlpv] */ | |
/* Because the syntax for a function returning a function pointer is disgustin… | |
typedef void (*process_func)(struct stream *stream); | |
diff --git a/src/blind-temporal-mean.c b/src/blind-temporal-mean.c | |
@@ -2,7 +2,7 @@ | |
#include "common.h" | |
USAGE("[-g | -h | -l power | -p power | -v]") | |
-/* TODO add [-w weight-stream] for -l */ | |
+/* TODO add [-w weight-stream] for [-ghlpv] */ | |
/* Because the syntax for a function returning a function pointer is disgustin… | |
typedef void (*process_func)(struct stream *stream, void *buffer, void *image,… |