Introduction
Introduction Statistics Contact Development Disclaimer Help
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')
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.