Fix blind-kernel and blind-temporal-mean,d add blind-{spatial,temporal}-arithm … | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 835df7bd1e81852062dd70ce1a054fc9b510e50f | |
parent 12e20aecd0ef73523b344d4efc4c54d4174c3880 | |
Author: Mattias Andrée <[email protected]> | |
Date: Tue, 25 Jul 2017 22:12:23 +0200 | |
Fix blind-kernel and blind-temporal-mean,d add blind-{spatial,temporal}-arithm … | |
Signed-off-by: Mattias Andrée <[email protected]> | |
Diffstat: | |
M Makefile | 13 ++++++------- | |
M README | 15 +++++++++++++++ | |
M TODO | 3 --- | |
M man/blind-apply-kernel.1 | 1 + | |
M man/blind-arithm.1 | 16 +++++++++++++++- | |
M man/blind-gauss-blur.1 | 1 + | |
A man/blind-kernel.1 | 116 ++++++++++++++++++++++++++++++ | |
M man/blind-make-kernel.1 | 3 ++- | |
A man/blind-spatial-arithm.1 | 35 +++++++++++++++++++++++++++++… | |
A man/blind-spatial-mean.1 | 48 +++++++++++++++++++++++++++++… | |
A man/blind-temporal-arithm.1 | 39 +++++++++++++++++++++++++++++… | |
A man/blind-temporal-mean.1 | 60 +++++++++++++++++++++++++++++… | |
M man/blind.7 | 15 +++++++++++++++ | |
M src/blind-arithm.c | 115 +++++++++++++++++------------… | |
M src/blind-kernel.c | 36 ++++++++++++-----------------… | |
A src/blind-spatial-arithm.c | 94 +++++++++++++++++++++++++++++… | |
A src/blind-spatial-mean.c | 142 +++++++++++++++++++++++++++++… | |
M src/blind-stack.c | 1 + | |
A src/blind-temporal-arithm.c | 94 +++++++++++++++++++++++++++++… | |
M src/blind-temporal-mean.c | 63 +++++++++++++++++------------… | |
M src/stream.c | 2 +- | |
M src/util.c | 5 +++++ | |
22 files changed, 801 insertions(+), 116 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
@@ -43,6 +43,7 @@ BIN =\ | |
blind-interleave\ | |
blind-invert-luma\ | |
blind-invert-matrix\ | |
+ blind-kernel\ | |
blind-linear-gradient\ | |
blind-make-kernel\ | |
blind-matrix-orthoproject\ | |
@@ -76,6 +77,8 @@ BIN =\ | |
blind-sinc-wave\ | |
blind-sine-wave\ | |
blind-skip-pattern\ | |
+ blind-spatial-arithm\ | |
+ blind-spatial-mean\ | |
blind-spectrum\ | |
blind-spiral-gradient\ | |
blind-split\ | |
@@ -85,6 +88,8 @@ BIN =\ | |
blind-square-gradient\ | |
blind-stack\ | |
blind-tee\ | |
+ blind-temporal-arithm\ | |
+ blind-temporal-mean\ | |
blind-time-blur\ | |
blind-triangular-wave\ | |
blind-to-image\ | |
@@ -97,13 +102,7 @@ BIN =\ | |
blind-triangle-tessellation\ | |
blind-unpremultiply\ | |
blind-vector-projection\ | |
- blind-write-head\ | |
- blind-kernel\ | |
- blind-temporal-mean | |
- | |
-# TODO Not tested yet (and doesn't have any manpages): | |
-# blind-kernel | |
-# blind-temporal-mean | |
+ blind-write-head | |
SH_SCRIPTS =\ | |
blind-rotate-90\ | |
diff --git a/README b/README | |
@@ -126,6 +126,9 @@ UTILITIES | |
blind-invert-matrix(1) | |
Invert matrix-video | |
+ blind-kernel(1) | |
+ Create a convolution matrix | |
+ | |
blind-linear-gradient(1) | |
Generate a video with a linear gradient | |
@@ -240,6 +243,12 @@ UTILITIES | |
blind-skip-pattern(1) | |
Skips frames in a video according to pattern | |
+ blind-spatial-arithm(1) | |
+ Perform simple arithmetic over all pixels for each frame in a vi… | |
+ | |
+ blind-spatial-mean(1) | |
+ Calculate the mean over all pixel for each frame in a video | |
+ | |
blind-spectrum(1) | |
Transform a gradient into a spectrum | |
@@ -267,6 +276,12 @@ UTILITIES | |
blind-tee(1) | |
/dev/fd/ aware tee(1) implementation | |
+ blind-temporal-arithm(1) | |
+ Perform simple arithmetic over all frames in a video for each pi… | |
+ | |
+ blind-temporal-mean(1) | |
+ Calculate the mean over all frames in a video for each pixel | |
+ | |
blind-time-blur(1) | |
Draw new frames on top of old frames with partial alpha | |
diff --git a/TODO b/TODO | |
@@ -31,7 +31,6 @@ blind-mean mean of multiple streams | |
https://en.wikipedia.org/wiki/Identric_mean | |
https://en.wikipedia.org/wiki/Logarithmic_mean | |
https://en.wikipedia.org/wiki/Stolarsky_mean | |
-blind-temporal-arithm blind-arithm but over all frames in a video inste… | |
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 | |
@@ -51,8 +50,6 @@ blind-from-video: add options to: | |
blind-cone-gradient: add ability to make gradient superelliptic | |
-blind-arithm: add support for multiple streams | |
- | |
Add [-j jobs] to blind-from-video and blind-to-video. | |
long double is slightly faster than long. | |
diff --git a/man/blind-apply-kernel.1 b/man/blind-apply-kernel.1 | |
@@ -63,6 +63,7 @@ A frame or row requires 32 bytes per pixel it contains. | |
.SH SEE ALSO | |
.BR blind (7), | |
.BR blind-make-kernel (1), | |
+.BR blind-kernel (1), | |
.BR blind-gauss-blur (1) | |
.SH AUTHORS | |
Mattias Andrée | |
diff --git a/man/blind-arithm.1 b/man/blind-arithm.1 | |
@@ -5,7 +5,7 @@ blind-arithm - Perform simple arithmetic on a video | |
.B blind-arithm | |
[-axyz] | |
.I operation | |
-.I right-hand-stream | |
+.IR right-hand-stream \ ... | |
.SH DESCRIPTION | |
.B blind-arithm | |
reads left-hand operands from stdin, and right-hand | |
@@ -27,6 +27,16 @@ If stdin is shorter than | |
the remainder of | |
.I right-hand-stream | |
is ignored but may be partially read. | |
+.P | |
+IF multiple | |
+.I right-hand-stream | |
+are specified, they are applied from left to right, | |
+with the exception for if | |
+.I operation | |
+is | |
+.BR exp , | |
+in which case they are applied from right to left with | |
+stdin applied last. | |
.SH OPERATIONS | |
.TP | |
.B add | |
@@ -86,6 +96,10 @@ Do not modify the Z channel (the third channel). | |
.BR blind-cross-product (1), | |
.BR blind-quaternion-product (1), | |
.BR blind-vector-projection (1), | |
+.BR blind-spatial-mean (1), | |
+.BR blind-spatial-arithm (1), | |
+.BR blind-temporal-mean (1), | |
+.BR blind-temporal-arithm (1), | |
.BR blind-single-colour (1), | |
.BR blind-set-alpha (1), | |
.BR blind-set-luma (1), | |
diff --git a/man/blind-gauss-blur.1 b/man/blind-gauss-blur.1 | |
@@ -81,6 +81,7 @@ memory. A frame requires 32 bytes per pixel it contains. | |
.BR blind-single-colour (1), | |
.BR blind-time-blur (1), | |
.BR blind-make-kernel (1), | |
+.BR blind-kernel (1), | |
.BR blind-apply-kernel (1) | |
.SH AUTHORS | |
Mattias Andrée | |
diff --git a/man/blind-kernel.1 b/man/blind-kernel.1 | |
@@ -0,0 +1,116 @@ | |
+.TH BLIND-KERNEL 1 blind | |
+.SH NAME | |
+blind-kernel - Create a convolution matrix | |
+.SH SYNOPSIS | |
+.B blind-kernel | |
+[-xyza] | |
+.I kernel | |
+.RI [ parameter ]\ ... | |
+.SH DESCRIPTION | |
+.B blind-kernel | |
+creates a convolution matrix that can be applied to | |
+a video using | |
+.BR blind-apply-kernel (1). | |
+The convolution matrix is created from a set | |
+of standard formulae. The formula is selected | |
+using the | |
+.I kernel | |
+argument and is tuned with | |
+.IR kernel -specific | |
+.IR parameter s. | |
+.SH KERNELS | |
+.TP | |
+.BI kirsch\ direction | |
+Create a Kirsch kernel with the specified | |
+.IR direction . | |
+The | |
+.I direction | |
+must be | |
+.B 1 | |
+or | |
+.BR N ; | |
+.BR 2 , | |
+.BR NW , | |
+or | |
+.BR WN ; | |
+.BR 3 | |
+or | |
+.BR W ; | |
+.BR 4 , | |
+.BR SW , | |
+or | |
+.BR WS ; | |
+.BR 5 | |
+or | |
+.BR S ; | |
+.BR 6 , | |
+.BR SE , | |
+or | |
+.BR ES ; | |
+.BR 7 | |
+or | |
+.BR E ; | |
+or | |
+.BR 8 , | |
+.BR NE , | |
+or | |
+.BR EN . | |
+.TP | |
+.RI ' \fBbox\ blur\fP '\ [-w\ weight ]\ [ spread \ |\ x-spread \ y-spread ] | |
+Creates a box blur kernel. Unless | |
+.B -w | |
+is used, the kernel is unweighted, otherwise it has the specified | |
+.IR weight . | |
+The kernel will have the spread 1, the specified | |
+.IR spread , | |
+or | |
+.I x-spread | |
+as the horizontal spread and | |
+.I y-spread | |
+as the vertical spread. | |
+.TP | |
+.BR sharpen \ [-i] | |
+Creates a sharpen kernel. If | |
+.B -i | |
+is used, an intensified sharpen kernel is created. | |
+.TP | |
+.RI \fBgaussian\fP\ [-s\ spread ]\ [-u]\ standard-deviation | |
+Creates a Gaussian blur kernel with the standard deviation | |
+.IR standard-deviation . | |
+If | |
+.B -u | |
+is used, the a Gaussian unsharpen kernel is created. If | |
+.B -s | |
+is specified, the specified | |
+.I spread | |
+will be used, otherwise the spread will be selected automatically. | |
+.SH OPTIONS | |
+.TP | |
+.B -a | |
+Apply the values to the alpha channel, set the | |
+values for all unselected channels to zero. | |
+.TP | |
+.B -x | |
+Apply the values to the X channel, set the values | |
+for all unselected channels to zero. | |
+.TP | |
+.B -y | |
+Apply the values to the Y channel, set the values | |
+for all unselected channels to zero. | |
+.TP | |
+.B -z | |
+Apply the values to the Z channel, set the values | |
+for all unselected channels to zero. | |
+.SH NOTES | |
+.B blind-make-kernel | |
+Create a single frame, to that it can be stored to | |
+disc. When applying it to a video, you want to use | |
+.BR blind-repeat (1). | |
+.SH SEE ALSO | |
+.BR blind (7), | |
+.BR blind-apply-kernel (1), | |
+.BR blind-kernel (1), | |
+.BR blind-repeat (1) | |
+.SH AUTHORS | |
+Mattias Andrée | |
+.RI < [email protected] > | |
diff --git a/man/blind-make-kernel.1 b/man/blind-make-kernel.1 | |
@@ -73,11 +73,12 @@ for all unselected channels to zero. | |
.SH NOTES | |
.B blind-make-kernel | |
Create a single frame, to that it can be stored to | |
-disk. When applying it to a video, you want to use | |
+disc. When applying it to a video, you want to use | |
.BR blind-repeat (1). | |
.SH SEE ALSO | |
.BR blind (7), | |
.BR blind-apply-kernel (1), | |
+.BR blind-kernel (1), | |
.BR blind-repeat (1) | |
.SH AUTHORS | |
Mattias Andrée | |
diff --git a/man/blind-spatial-arithm.1 b/man/blind-spatial-arithm.1 | |
@@ -0,0 +1,35 @@ | |
+.TH BLIND-SPATIAL-ARITHM 1 blind | |
+.SH NAME | |
+blind-spatial-arithm - Perform simple arithmetic over all pixels for each fram… | |
+.SH SYNOPSIS | |
+.B blind-spatial-arithm | |
+.I operation | |
+.SH DESCRIPTION | |
+.B blind-spatial-arithm | |
+reads a video from stdin and applies an arithmetic | |
+operation over all pixels, for each frame in the | |
+video, and prints the resulting video, with one | |
+pixel in each frame, to stdout. | |
+.SH OPERATIONS | |
+.TP | |
+.B add | |
+Calculate the sum of the operands. | |
+.TP | |
+.B mul | |
+Calculate the product of the operands. | |
+.TP | |
+.B min | |
+Select the lowest operand. | |
+.TP | |
+.B max | |
+Select the highest operand. | |
+.SH SEE ALSO | |
+.BR blind (7), | |
+.BR blind-temporal-arithm (1), | |
+.BR blind-arithm (1), | |
+.BR blind-spatial-mean (1), | |
+.BR blind-temporal-mean (1), | |
+.BR blind-rewrite-head (1) | |
+.SH AUTHORS | |
+Mattias Andrée | |
+.RI < [email protected] > | |
diff --git a/man/blind-spatial-mean.1 b/man/blind-spatial-mean.1 | |
@@ -0,0 +1,48 @@ | |
+.TH BLIND-SPATIAL-MEAN 1 blind | |
+.SH NAME | |
+blind-spatial-mean - Calculate the mean over all pixel for each frame in a vid… | |
+.SH SYNOPSIS | |
+.B blind-spatial-mean | |
+[-g | -h | -l | |
+.I power | |
+| -p | |
+.I power | |
+| -v] | |
+.SH DESCRIPTION | |
+.B blind-spatial-mean | |
+reads a video from stdin and calculates the mean | |
+over all pixels for frames, and outputs a | |
+video with one pixel in each frame, to stdout with | |
+the mean for each frame. | |
+.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 | |
+.BR -l \ \fIpower\fP | |
+Calculate the Lehmer mean with the specified | |
+.IR power . | |
+.TP | |
+.BR -p \ \fIpower\fP | |
+Calculate the power mean (Hölder mean) with | |
+the specified | |
+.IR power . | |
+.TP | |
+.B -v | |
+Calculate the variance. | |
+.SH SEE ALSO | |
+.BR blind (7), | |
+.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 | |
+.RI < [email protected] > | |
diff --git a/man/blind-temporal-arithm.1 b/man/blind-temporal-arithm.1 | |
@@ -0,0 +1,39 @@ | |
+.TH BLIND-TEMPORAL-ARITHM 1 blind | |
+.SH NAME | |
+blind-temporal-arithm - Perform simple arithmetic over all frames in a video f… | |
+.SH SYNOPSIS | |
+.B blind-temporal-arithm | |
+.I operation | |
+.SH DESCRIPTION | |
+.B blind-temporal-arithm | |
+reads a video from stdin and applies an arithmetic | |
+operation over all frames in the video, for each | |
+pixel, and prints the resulting single-frame video | |
+to stdout. | |
+.SH OPERATIONS | |
+.TP | |
+.B add | |
+Calculate the sum of the operands. | |
+.TP | |
+.B mul | |
+Calculate the product of the operands. | |
+.TP | |
+.B min | |
+Select the lowest operand. | |
+.TP | |
+.B max | |
+Select the highest operand. | |
+.SH REQUIREMENTS | |
+.B blind-temporal-arithm | |
+requires enough free memory to load one full frames memory. | |
+A frame requires 32 bytes per pixel it contains. | |
+.SH SEE ALSO | |
+.BR blind (7), | |
+.BR blind-temporal-mean (1), | |
+.BR blind-spatial-arithm (1), | |
+.BR blind-spatial-mean (1), | |
+.BR blind-arithm (1), | |
+.BR blind-rewrite-head (1) | |
+.SH AUTHORS | |
+Mattias Andrée | |
+.RI < [email protected] > | |
diff --git a/man/blind-temporal-mean.1 b/man/blind-temporal-mean.1 | |
@@ -0,0 +1,60 @@ | |
+.TH BLIND-TEMPORAL-MEAN 1 blind | |
+.SH NAME | |
+blind-temporal-mean - Calculate the mean over all frames in a video for each p… | |
+.SH SYNOPSIS | |
+.B blind-temporal-mean | |
+[-g | -h | -l | |
+.I power | |
+| -p | |
+.I power | |
+| -v] | |
+.SH DESCRIPTION | |
+.B blind-temporal-mean | |
+reads a video from stdin and calculates the mean | |
+over all frames for each pixel, and outputs a | |
+single frame video to stdout with the mean for | |
+each pixel. | |
+.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 | |
+.BR -l \ \fIpower\fP | |
+Calculate the Lehmer mean with the specified | |
+.IR power . | |
+.TP | |
+.BR -p \ \fIpower\fP | |
+Calculate the power mean (Hölder mean) with | |
+the specified | |
+.IR power . | |
+.TP | |
+.B -v | |
+Calculate the variance. | |
+.SH REQUIREMENTS | |
+.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 | |
+or | |
+.B -v | |
+is used, enough free memory to load three full frames | |
+memory is required. | |
+.P | |
+.B blind-temporal-mean | |
+is optimised for simplicity rather than memory usage. | |
+.SH SEE ALSO | |
+.BR blind (7), | |
+.BR blind-temporal-arithm (1), | |
+.BR blind-spatial-arithm (1), | |
+.BR blind-arithm (1), | |
+.BR blind-spatial-mean (1), | |
+.BR blind-rewrite-head (1) | |
+.SH AUTHORS | |
+Mattias Andrée | |
+.RI < [email protected] > | |
diff --git a/man/blind.7 b/man/blind.7 | |
@@ -144,6 +144,9 @@ Invert the luminosity of a video | |
.BR blind-invert-matrix (1) | |
Invert matrix-video | |
.TP | |
+.BR blind-kernel (1) | |
+Create a convolution matrix | |
+.TP | |
.BR blind-linear-gradient (1) | |
Generate a video with a linear gradient | |
.TP | |
@@ -255,6 +258,12 @@ Apply sine-wave repetition to gradient | |
.BR blind-skip-pattern (1) | |
Skips frames in a video according to pattern | |
.TP | |
+.BR blind-spatial-arithm (1) | |
+Perform simple arithmetic over all pixels for each frame in a video | |
+.TP | |
+.BR blind-spatial-mean (1) | |
+Calculate the mean over all pixel for each frame in a video | |
+.TP | |
.BR blind-spectrum (1) | |
Transform a gradient into a spectrum | |
.TP | |
@@ -284,6 +293,12 @@ Overlay videos | |
.BR tee (1) | |
implementation | |
.TP | |
+.BR blind-temporal-arithm (1) | |
+Perform simple arithmetic over all frames in a video for each pixel | |
+.TP | |
+.BR blind-temporal-mean (1) | |
+Calculate the mean over all frames in a video for each pixel | |
+.TP | |
.BR blind-time-blur (1) | |
Draw new frames on top of old frames with partial alpha | |
.TP | |
diff --git a/src/blind-arithm.c b/src/blind-arithm.c | |
@@ -1,67 +1,71 @@ | |
/* See LICENSE file for copyright and license details. */ | |
#include "common.h" | |
-USAGE("[-axyz] operation right-hand-stream") | |
+USAGE("[-axyz] operation right-hand-stream ...") | |
-static int skip_a = 0; | |
-static int skip_x = 0; | |
-static int skip_y = 0; | |
-static int skip_z = 0; | |
+static int skip_ch[4] = {0, 0, 0, 0}; | |
/* Because the syntax for a function returning a function pointer is disgustin… | |
-typedef void (*process_func)(struct stream *left, struct stream *right, size_t… | |
+typedef void (*process_func)(struct stream *streams, size_t n_streams, size_t … | |
#define LIST_OPERATORS(PIXFMT, TYPE)\ | |
- X(add, *lh += rh, PIXFMT, TYPE)\ | |
- X(sub, *lh -= rh, PIXFMT, TYPE)\ | |
- X(mul, *lh *= rh, PIXFMT, TYPE)\ | |
- X(div, *lh /= rh, PIXFMT, TYPE)\ | |
- X(mod, *lh = posmod(*lh, rh), PIXFMT, TYPE)\ | |
- X(exp, *lh = pow(*lh, rh), PIXFMT, TYPE)\ | |
- X(log, *lh = log2(*lh) / log2(rh), PIXFMT, TYPE)\ | |
- X(min, *lh = MIN(*lh, rh), PIXFMT, TYPE)\ | |
- X(max, *lh = MAX(*lh, rh), PIXFMT, TYPE)\ | |
- X(abs, *lh = abs(*lh - rh) + rh, PIXFMT, TYPE) | |
+ X(add, 0, *lh += rh, PIXFMT, TYPE)\ | |
+ X(sub, 0, *lh -= rh, PIXFMT, TYPE)\ | |
+ X(mul, 0, *lh *= rh, PIXFMT, TYPE)\ | |
+ X(div, 0, *lh /= rh, PIXFMT, TYPE)\ | |
+ X(mod, 0, *lh = posmod(*lh, rh), PIXFMT, TYPE)\ | |
+ X(exp, 1, *lh = pow(*lh, rh), PIXFMT, TYPE)\ | |
+ X(log, 0, *lh = log2(*lh) / log2(rh), PIXFMT, TYPE)\ | |
+ X(min, 0, *lh = MIN(*lh, rh), PIXFMT, TYPE)\ | |
+ X(max, 0, *lh = MAX(*lh, rh), PIXFMT, TYPE)\ | |
+ X(abs, 0, *lh = abs(*lh - rh) + rh, PIXFMT, TYPE) | |
-#define C(CH, CHI, ALGO, TYPE)\ | |
- (!skip_##CH ? ((lh = ((TYPE *)(left->buf + i)) + (CHI),\ | |
- rh = ((TYPE *)(right->buf + i))[CHI],\ | |
- (ALGO)), 0) : 0) | |
+#define P(L, R, ALGO, TYPE)\ | |
+ (lh = (TYPE *)(streams[L].buf + k),\ | |
+ rh = *((TYPE *)(streams[R].buf + k)),\ | |
+ (ALGO)) | |
-#define X(NAME, ALGO, PIXFMT, TYPE)\ | |
+#define X(NAME, RTL, ALGO, PIXFMT, TYPE)\ | |
static void\ | |
- process_##PIXFMT##_##NAME(struct stream *left, struct stream *right, s… | |
+ process_##PIXFMT##_##NAME(struct stream *streams, size_t n_streams, si… | |
{\ | |
- size_t i;\ | |
+ size_t i, j, k;\ | |
TYPE *lh, rh;\ | |
- for (i = 0; i < n; i += 4 * sizeof(TYPE)) {\ | |
- C(x, 0, ALGO, TYPE);\ | |
- C(y, 1, ALGO, TYPE);\ | |
- C(z, 2, ALGO, TYPE);\ | |
- C(a, 3, ALGO, TYPE);\ | |
+ if (RTL) {\ | |
+ for (i = 0; i < streams->n_chan; i++)\ | |
+ if (!skip_ch[i])\ | |
+ for (j = n_streams; --j;)\ | |
+ for (k = i * sizeof(TYPE); k <… | |
+ P(j - 1, j, ALGO, TYPE… | |
+ } else {\ | |
+ for (i = 0; i < streams->n_chan; i++)\ | |
+ if (!skip_ch[i])\ | |
+ for (j = 1; j < n_streams; j++)\ | |
+ for (k = i * sizeof(TYPE); k <… | |
+ P(0, j, ALGO, TYPE);\ | |
}\ | |
} | |
-LIST_OPERATORS(xyza, double) | |
-LIST_OPERATORS(xyzaf, float) | |
+LIST_OPERATORS(lf, double) | |
+LIST_OPERATORS(f, float) | |
#undef X | |
static process_func | |
-get_process_xyza(const char *operation) | |
+get_process_lf(const char *operation) | |
{ | |
-#define X(NAME, ALGO, PIXFMT, TYPE)\ | |
+#define X(NAME, _RTL, _ALGO, PIXFMT, _TYPE)\ | |
if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME; | |
- LIST_OPERATORS(xyza, double) | |
+ LIST_OPERATORS(lf, double) | |
#undef X | |
eprintf("algorithm not recognised: %s\n", operation); | |
return NULL; | |
} | |
static process_func | |
-get_process_xyzaf(const char *operation) | |
+get_process_f(const char *operation) | |
{ | |
-#define X(NAME, ALGO, PIXFMT, TYPE)\ | |
+#define X(NAME, _RTL, _ALGO, PIXFMT, _TYPE)\ | |
if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME; | |
- LIST_OPERATORS(xyzaf, float) | |
+ LIST_OPERATORS(f, float) | |
#undef X | |
eprintf("algorithm not recognised: %s\n", operation); | |
return NULL; | |
@@ -70,41 +74,46 @@ get_process_xyzaf(const char *operation) | |
int | |
main(int argc, char *argv[]) | |
{ | |
- struct stream left, right; | |
+ struct stream *streams; | |
process_func process; | |
+ const char *operation; | |
+ size_t frames = SIZE_MAX, tmp; | |
+ int i; | |
ARGBEGIN { | |
case 'a': | |
- skip_a = 1; | |
+ skip_ch[3] = 1; | |
break; | |
case 'x': | |
- skip_x = 1; | |
- break; | |
case 'y': | |
- skip_y = 1; | |
- break; | |
case 'z': | |
- skip_z = 1; | |
+ skip_ch[ARGC() - 'x'] = 1; | |
break; | |
default: | |
usage(); | |
} ARGEND; | |
- if (argc != 2) | |
+ if (argc < 2) | |
usage(); | |
- eopen_stream(&left, NULL); | |
- eopen_stream(&right, argv[1]); | |
+ operation = *argv; | |
+ streams = alloca((size_t)argc * sizeof(*streams)); | |
+ *argv = NULL; | |
+ 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 (!strcmp(left.pixfmt, "xyza")) | |
- process = get_process_xyza(argv[0]); | |
- else if (!strcmp(left.pixfmt, "xyza f")) | |
- process = get_process_xyzaf(argv[0]); | |
+ if (streams->encoding == DOUBLE) | |
+ process = get_process_lf(operation); | |
else | |
- eprintf("pixel format %s is not supported, try xyza\n", left.p… | |
+ process = get_process_f(operation); | |
- fprint_stream_head(stdout, &left); | |
+ tmp = streams->frames, streams->frames = frames; | |
+ fprint_stream_head(stdout, streams); | |
efflush(stdout, "<stdout>"); | |
- process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process); | |
+ streams->frames = tmp; | |
+ process_multiple_streams(streams, (size_t)argc, STDOUT_FILENO, "<stdou… | |
return 0; | |
} | |
diff --git a/src/blind-kernel.c b/src/blind-kernel.c | |
@@ -3,7 +3,7 @@ | |
USAGE("[-xyza] kernel [parameter] ...") | |
-#define SUBUSAGE(FORMAT) "usage: %s [-xyza] " FORMAT, argv0 | |
+#define SUBUSAGE(FORMAT) "usage: %s [-xyza] " FORMAT "\n", argv0 | |
#define STRCASEEQ3(A, B1, B2, B3) (!strcasecmp(A, B1) || !strcasecmp(A, B2) ||… | |
#define LIST_KERNELS\ | |
@@ -37,7 +37,7 @@ kernel_kirsch(int argc, char *argv[], size_t *rows, size_t *c… | |
if (STRCASEEQ3(argv[0], "6", "SE", "ES")) return matrices[5]; | |
if (STRCASEEQ3(argv[0], "7", "E", "E")) return matrices[6]; | |
if (STRCASEEQ3(argv[0], "8", "NE", "EN")) return matrices[7]; | |
- eprintf("Unrecognised direction: %s\n", argv[0]); | |
+ eprintf("unrecognised direction: %s\n", argv[0]); | |
return NULL; | |
} | |
@@ -129,6 +129,7 @@ static const double * | |
kernel_gaussian(int argc, char *argv[], size_t *rows, size_t *cols, double **f… | |
{ | |
size_t spread = 0, y, x; | |
+ ssize_t xx, yy; | |
int unsharpen = 0; | |
double sigma, value, c, k; | |
char *arg; | |
@@ -160,29 +161,17 @@ kernel_gaussian(int argc, char *argv[], size_t *rows, siz… | |
*free_this = emalloc3(*rows, *cols, sizeof(double)); | |
- k = sigma * sigma * 2; | |
+ k = sigma * sigma * 2.; | |
c = M_PI * k; | |
- c = sqrt(c); | |
c = 1.0 / c; | |
k = 1.0 / -k; | |
- | |
- for (x = 0; x <= spread; x++) { | |
- value = (double)(spread - x); | |
- value *= value * k; | |
- value = exp(value) * c; | |
- for (y = 0; y < *rows; y++) { | |
+ for (y = 0; y < 2 * spread + 1; y++) { | |
+ yy = (ssize_t)spread - (ssize_t)y, yy *= yy; | |
+ for (x = 0; x < 2 * spread + 1; x++) { | |
+ xx = (ssize_t)spread - (ssize_t)x, xx *= xx; | |
+ value = (double)(xx + yy) * k; | |
+ value = exp(value) * c; | |
(*free_this)[y * *cols + x] = value; | |
- (*free_this)[y + 1 * *cols + *cols - 1 - x] = value; | |
- } | |
- } | |
- | |
- for (y = 0; y <= spread; y++) { | |
- value = (double)(spread - y); | |
- value *= value * k; | |
- value = exp(value) * c; | |
- for (x = 0; x < *cols; x++) { | |
- (*free_this)[y * *cols + x] *= value; | |
- (*free_this)[y + 1 * *cols + *cols - 1 - x] *= value; | |
} | |
} | |
@@ -235,13 +224,16 @@ main(int argc, char *argv[]) | |
usage(); | |
} ARGEND; | |
+ if (!argc) | |
+ usage(); | |
+ | |
if (null_x && null_y && null_z && null_a) | |
null_x = null_y = null_z = null_a = 0; | |
if (0); | |
#define X(FUNC, NAME)\ | |
else if (!strcmp(argv[0], NAME))\ | |
- kernel = FUNC(argc, argv + 1, &rows, &cols, &free_this); | |
+ kernel = FUNC(argc - 1, argv + 1, &rows, &cols, &free_this); | |
LIST_KERNELS | |
#undef X | |
else | |
diff --git a/src/blind-spatial-arithm.c b/src/blind-spatial-arithm.c | |
@@ -0,0 +1,94 @@ | |
+/* See LICENSE file for copyright and license details. */ | |
+#include "common.h" | |
+ | |
+USAGE("operation") | |
+ | |
+/* Because the syntax for a function returning a function pointer is disgustin… | |
+typedef void (*process_func)(struct stream *stream); | |
+ | |
+#define LIST_OPERATORS(PIXFMT, TYPE)\ | |
+ X(add, img[j & 3] + *buf, PIXFMT, TYPE)\ | |
+ X(mul, img[j & 3] * *buf, PIXFMT, TYPE)\ | |
+ X(min, MIN(img[j & 3], *buf), PIXFMT, TYPE)\ | |
+ X(max, MAX(img[j & 3], *buf), PIXFMT, TYPE) | |
+ | |
+#define X(NAME, ALGO, PIXFMT, TYPE)\ | |
+ static void\ | |
+ process_##PIXFMT##_##NAME(struct stream *stream)\ | |
+ {\ | |
+ TYPE img[4], *buf;\ | |
+ size_t i, n, j = 0, m = stream->frame_size / sizeof(*img);\ | |
+ int first = 1;\ | |
+ 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)\ | |
+ ewriteall(STDOUT_FILENO, img, … | |
+ first = 0;\ | |
+ img[0] = *buf++;\ | |
+ img[1] = *buf++;\ | |
+ img[2] = *buf++;\ | |
+ img[3] = *buf;\ | |
+ i += 3;\ | |
+ j = 3;\ | |
+ } else {\ | |
+ img[j & 3] = ALGO;\ | |
+ }\ | |
+ }\ | |
+ n *= sizeof(TYPE);\ | |
+ memmove(stream->buf, stream->buf + n, stream->ptr -= n… | |
+ } while (eread_stream(stream, SIZE_MAX));\ | |
+ if (!first)\ | |
+ ewriteall(STDOUT_FILENO, img, sizeof(img), "<stdout>")… | |
+ } | |
+LIST_OPERATORS(lf, double) | |
+LIST_OPERATORS(f, float) | |
+#undef X | |
+ | |
+static process_func | |
+get_process_lf(const char *operation) | |
+{ | |
+#define X(NAME, _ALGO, PIXFMT, TYPE)\ | |
+ if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME; | |
+ LIST_OPERATORS(lf, double) | |
+#undef X | |
+ eprintf("algorithm not recognised: %s\n", operation); | |
+ return NULL; | |
+} | |
+ | |
+static process_func | |
+get_process_f(const char *operation) | |
+{ | |
+#define X(NAME, _ALGO, PIXFMT, TYPE)\ | |
+ if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME; | |
+ LIST_OPERATORS(f, float) | |
+#undef X | |
+ eprintf("algorithm not recognised: %s\n", operation); | |
+ return NULL; | |
+} | |
+ | |
+int | |
+main(int argc, char *argv[]) | |
+{ | |
+ struct stream stream; | |
+ process_func process; | |
+ | |
+ UNOFLAGS(argc != 1); | |
+ | |
+ eopen_stream(&stream, NULL); | |
+ echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); | |
+ | |
+ if (stream.encoding == DOUBLE) | |
+ process = get_process_lf(argv[0]); | |
+ else | |
+ process = get_process_f(argv[0]); | |
+ | |
+ if (DPRINTF_HEAD(STDOUT_FILENO, stream.frames, 1, 1, stream.pixfmt) < … | |
+ eprintf("dprintf:"); | |
+ process(&stream); | |
+ if (stream.ptr) | |
+ eprintf("%s: incomplete frame\n", stream.file); | |
+ return 0; | |
+} | |
diff --git a/src/blind-spatial-mean.c 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 disgustin… | |
+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… | |
+ /* harmonic mean */\ | |
+ X(HARMONIC, harmonic,, 0, img[j & 3] += (TYPE)1 / *buf, img[j & 3] = p… | |
+ /* 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 … | |
+ /* power mean (Hölder mean) (m = 2 for root square mean; m = 3 for cu… | |
+ 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] += *b… | |
+ img[j & 3] = (img[j & 3] - aux[j & 3] * aux[j & 3] / pixels) / pixel… | |
+ | |
+#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_SUBCEL… | |
+ 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… | |
+ FINALISE_SUBCELL;\ | |
+ j = 0;\ | |
+ ewriteall(STDOUT_FILENO, img, … | |
+ }\ | |
+ 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) < … | |
+ eprintf("dprintf:"); | |
+ process(&stream); | |
+ if (stream.ptr) | |
+ eprintf("%s: incomplete frame\n", stream.file); | |
+ return 0; | |
+} | |
diff --git a/src/blind-stack.c b/src/blind-stack.c | |
@@ -52,6 +52,7 @@ main(int argc, char *argv[]) | |
break; | |
case 's': | |
shortest = 1; | |
+ frames = SIZE_MAX; | |
break; | |
default: | |
usage(); | |
diff --git a/src/blind-temporal-arithm.c b/src/blind-temporal-arithm.c | |
@@ -0,0 +1,94 @@ | |
+/* See LICENSE file for copyright and license details. */ | |
+#include "common.h" | |
+ | |
+USAGE("operation") | |
+ | |
+/* Because the syntax for a function returning a function pointer is disgustin… | |
+typedef void (*process_func)(struct stream *stream, void *image); | |
+ | |
+#define LIST_OPERATORS(PIXFMT, TYPE)\ | |
+ X(add, *img + *buf, PIXFMT, TYPE)\ | |
+ X(mul, *img * *buf, PIXFMT, TYPE)\ | |
+ X(min, MIN(*img, *buf), PIXFMT, TYPE)\ | |
+ X(max, MAX(*img, *buf), PIXFMT, TYPE) | |
+ | |
+#define X(NAME, ALGO, PIXFMT, TYPE)\ | |
+ static void\ | |
+ process_##PIXFMT##_##NAME(struct stream *stream, void *image)\ | |
+ {\ | |
+ TYPE *buf, *img = image;\ | |
+ size_t i, n, j = 0, m = stream->frame_size / sizeof(TYPE);\ | |
+ do {\ | |
+ n = stream->ptr / sizeof(TYPE);\ | |
+ buf = (TYPE *)(stream->buf);\ | |
+ for (i = 0; i < n; i++, buf++) {\ | |
+ *img = ALGO;\ | |
+ if (++j == m) {\ | |
+ j = 0;\ | |
+ img = image;\ | |
+ } else {\ | |
+ img++;\ | |
+ }\ | |
+ }\ | |
+ n *= sizeof(TYPE);\ | |
+ memmove(stream->buf, stream->buf + n, stream->ptr -= n… | |
+ } while (eread_stream(stream, SIZE_MAX));\ | |
+ } | |
+LIST_OPERATORS(lf, double) | |
+LIST_OPERATORS(f, float) | |
+#undef X | |
+ | |
+static process_func | |
+get_process_lf(const char *operation) | |
+{ | |
+#define X(NAME, _ALGO, PIXFMT, TYPE)\ | |
+ if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME; | |
+ LIST_OPERATORS(lf, double) | |
+#undef X | |
+ eprintf("algorithm not recognised: %s\n", operation); | |
+ return NULL; | |
+} | |
+ | |
+static process_func | |
+get_process_f(const char *operation) | |
+{ | |
+#define X(NAME, _ALGO, PIXFMT, TYPE)\ | |
+ if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME; | |
+ LIST_OPERATORS(f, float) | |
+#undef X | |
+ eprintf("algorithm not recognised: %s\n", operation); | |
+ return NULL; | |
+} | |
+ | |
+int | |
+main(int argc, char *argv[]) | |
+{ | |
+ struct stream stream; | |
+ process_func process; | |
+ char *img; | |
+ | |
+ UNOFLAGS(argc != 1); | |
+ | |
+ eopen_stream(&stream, NULL); | |
+ | |
+ if (stream.encoding == DOUBLE) | |
+ process = get_process_lf(argv[0]); | |
+ else | |
+ process = get_process_f(argv[0]); | |
+ | |
+ echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); | |
+ img = emalloc(stream.frame_size); | |
+ if (!eread_frame(&stream, img)) | |
+ eprintf("video has no frames\n"); | |
+ | |
+ process(&stream, img); | |
+ if (stream.ptr) | |
+ eprintf("%s: incomplete frame\n", stream.file); | |
+ | |
+ stream.frames = 1; | |
+ fprint_stream_head(stdout, &stream); | |
+ efflush(stdout, "<stdout>"); | |
+ ewriteall(STDOUT_FILENO, img, stream.frame_size, "<stdout>"); | |
+ free(img); | |
+ return 0; | |
+} | |
diff --git a/src/blind-temporal-mean.c b/src/blind-temporal-mean.c | |
@@ -1,8 +1,8 @@ | |
/* See LICENSE file for copyright and license details. */ | |
#include "common.h" | |
-USAGE("[-g | -h | -l power | -p power]") | |
-/* TODO add -w weight-stream */ | |
+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 disgustin… | |
typedef void (*process_func)(struct stream *stream, void *buffer, void *image,… | |
@@ -20,20 +20,23 @@ typedef void (*process_func)(struct stream *stream, void *b… | |
#define LIST_MEANS(TYPE)\ | |
/* [default] arithmetic mean */\ | |
X(ARITHMETIC, arithmetic, 1, COPY_FRAME,, *img1 += *buf,\ | |
- a = (TYPE)1.0 / (TYPE)frame, *img1 *= a)\ | |
+ a = (TYPE)1 / (TYPE)frame, *img1 *= a)\ | |
/* geometric mean */\ | |
X(GEOMETRIC, geometric, 1, COPY_FRAME,, *img1 *= *buf,\ | |
- a = (TYPE)1.0 / (TYPE)frame, *img1 = nnpow(*img1, a))\ | |
+ a = (TYPE)1 / (TYPE)frame, *img1 = nnpow(*img1, a))\ | |
/* harmonic mean */\ | |
X(HARMONIC, harmonic, 1, ZERO_AND_PROCESS_FRAME,, *img1 += (TYPE)1 / *… | |
a = (TYPE)frame, *img1 = a / *img1)\ | |
- /* lehmer mean */\ | |
+ /* Lehmer mean */\ | |
X(LEHMER, lehmer, 2, ZERO_AND_PROCESS_FRAME, (a = (TYPE)power, b = a -… | |
(*img1 += nnpow(*buf, a), *img2 += nnpow(*buf, b)),, *img1 /= *img2)\ | |
/* power mean (Hölder mean) (m = 2 for root square mean; m = 3 for cu… | |
X(POWER, power, 1, ZERO_AND_PROCESS_FRAME, a = (TYPE)power,\ | |
- *img1 += nnpow(*buf, a), (a = (TYPE)1 / (TYPE)frame, b = (TYPE)(1.0 … | |
- *img1 = a * nnpow(*img1, b)) | |
+ *img1 += nnpow(*buf, a), (a = (TYPE)1 / (TYPE)frame, b = (TYPE)(1. /… | |
+ *img1 = a * nnpow(*img1, b))\ | |
+ /* variance */\ | |
+ X(VARIANCE, variance, 2, ZERO_AND_PROCESS_FRAME,, (*img1 += *buf * *bu… | |
+ a = (TYPE)1 / (TYPE)frame, *img1 = (*img1 - *img2 * *img2 * a) * a) | |
enum first_frame_action { | |
COPY_FRAME, | |
@@ -54,34 +57,37 @@ static double power; | |
{\ | |
TYPE *buf = buffer, *img1 = image, a, b;\ | |
TYPE *img2 = (TYPE *)(((char *)image) + stream->frame_size);\ | |
- size_t x, y;\ | |
- if (!stream) {\ | |
+ size_t x, y, z;\ | |
+ if (!buf) {\ | |
PRE_FINALISE;\ | |
- for (y = 0; y < stream->height; y++)\ | |
- for (x = 0; x < stream->width; x++, img1++, im… | |
- FINALISE_SUBCELL;\ | |
+ for (z = 0; z < stream->n_chan; z++)\ | |
+ for (y = 0; y < stream->height; y++)\ | |
+ for (x = 0; x < stream->width; x++, im… | |
+ FINALISE_SUBCELL;\ | |
} else {\ | |
PRE_PROCESS;\ | |
- for (y = 0; y < stream->height; y++)\ | |
- for (x = 0; x < stream->width; x++, img1++, im… | |
- PROCESS_SUBCELL;\ | |
+ for (z = 0; z < stream->n_chan; z++)\ | |
+ for (y = 0; y < stream->height; y++)\ | |
+ for (x = 0; x < stream->width; x++, im… | |
+ PROCESS_SUBCELL;\ | |
+ }\ | |
}\ | |
(void) img2, (void) a, (void) b, (void) frame;\ | |
} | |
-#define X(...) MAKE_PROCESS(xyza, double, __VA_ARGS__) | |
+#define X(...) MAKE_PROCESS(lf, double, __VA_ARGS__) | |
LIST_MEANS(double) | |
#undef X | |
-#define X(...) MAKE_PROCESS(xyzaf, float, __VA_ARGS__) | |
+#define X(...) MAKE_PROCESS(f, float, __VA_ARGS__) | |
LIST_MEANS(float) | |
#undef X | |
#undef MAKE_PROCESS | |
-#define X(ID, NAME, ...) [ID] = process_xyza_##NAME, | |
-static const process_func process_functions_xyza[] = { LIST_MEANS() }; | |
+#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_xyzaf_##NAME, | |
-static const process_func process_functions_xyzaf[] = { LIST_MEANS() }; | |
+#define X(ID, NAME, ...) [ID] = process_f_##NAME, | |
+static const process_func process_functions_f[] = { LIST_MEANS() }; | |
#undef X | |
int | |
@@ -109,6 +115,9 @@ main(int argc, char *argv[]) | |
method = POWER; | |
power = etolf_flag('p', UARGF()); | |
break; | |
+ case 'v': | |
+ method = VARIANCE; | |
+ break; | |
default: | |
usage(); | |
} ARGEND; | |
@@ -130,12 +139,10 @@ main(int argc, char *argv[]) | |
eopen_stream(&stream, NULL); | |
- if (!strcmp(stream.pixfmt, "xyza")) | |
- process = process_functions_xyza[method]; | |
- else if (!strcmp(stream.pixfmt, "xyza f")) | |
- process = process_functions_xyzaf[method]; | |
+ if (stream.encoding == DOUBLE) | |
+ process = process_functions_lf[method]; | |
else | |
- eprintf("pixel format %s is not supported, try xyza\n", stream… | |
+ process = process_functions_f[method]; | |
stream.frames = 1; | |
echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); | |
@@ -149,14 +156,14 @@ main(int argc, char *argv[]) | |
frames = 0; | |
if (first_frame_action == COPY_FRAME) { | |
- if (!eread_frame(&stream, buf)) | |
+ if (!eread_frame(&stream, img)) | |
eprintf("video is no frames\n"); | |
frames++; | |
} | |
for (; eread_frame(&stream, buf); frames++) | |
process(&stream, buf, img, frames); | |
if (!frames) | |
- eprintf("video is no frames\n"); | |
+ eprintf("video has no frames\n"); | |
process(&stream, NULL, img, frames); | |
ewriteall(STDOUT_FILENO, img, stream.frame_size, "<stdout>"); | |
diff --git a/src/stream.c b/src/stream.c | |
@@ -487,7 +487,7 @@ nprocess_multiple_streams(int status, struct stream *stream… | |
while (n_streams) { | |
n = SIZE_MAX; | |
for (i = 0; i < n_streams; i++) { | |
- if (streams[i].ptr < sizeof(streams->buf) && !enread_s… | |
+ if (streams[i].ptr < streams->pixel_size && !enread_st… | |
close(streams[i].fd); | |
streams[i].fd = -1; | |
if (shortest) | |
diff --git a/src/util.c b/src/util.c | |
@@ -32,6 +32,11 @@ tollu(const char *s, unsigned long long int min, unsigned lo… | |
errno = ERANGE; | |
return -1; | |
} | |
+ if (!isdigit(s[*s == 'x' || *s == 'X' || *s == '#']) || | |
+ (*s == '0' && !isdigit(s[1 + (*s == 'x' || *s == 'o' || *s == 'b')… | |
+ errno = EINVAL; | |
+ return -1; | |
+ } | |
if (tolower(*s) == 'x' || *s == '#') | |
*out = strtoull(s + 1, &end, 16); | |
else if (*s == '0' && tolower(s[1]) == 'x') |