blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

commit 4dfdb29707bf7af8df1fae28907d5e492338e8b8
parent f9adfc4c7c21dc0526c0d13285e41f4292176378
Author: Mattias Andrée <maandree@kth.se>
Date:   Sun,  2 Jul 2017 16:59:44 +0200

Add blind-{,un}premultiply, blind-{dot,cross,quaternion}-product, and blind-vector-projection

Signed-off-by: Mattias Andrée <maandree@kth.se>

Diffstat:
MMakefile | 6++++++
MREADME | 18++++++++++++++++++
MTODO | 7+++++++
Mman/blind-arithm.1 | 4++++
Aman/blind-cross-product.1 | 32++++++++++++++++++++++++++++++++
Aman/blind-dot-product.1 | 31+++++++++++++++++++++++++++++++
Aman/blind-premultiply.1 | 27+++++++++++++++++++++++++++
Aman/blind-quaternion-product.1 | 36++++++++++++++++++++++++++++++++++++
Aman/blind-unpremultiply.1 | 29+++++++++++++++++++++++++++++
Aman/blind-vector-projection.1 | 41+++++++++++++++++++++++++++++++++++++++++
Mman/blind.7 | 18++++++++++++++++++
Asrc/blind-cross-product.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/blind-dot-product.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/blind-premultiply.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/blind-quaternion-product.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/blind-unpremultiply.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/blind-vector-projection.c | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17 files changed, 673 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -11,10 +11,12 @@ BIN =\ blind-concat\ blind-convert\ blind-crop\ + blind-cross-product\ blind-cut\ blind-decompress\ blind-disperse\ blind-dissolve\ + blind-dot-product\ blind-extend\ blind-find-rectangle\ blind-flip\ @@ -29,6 +31,8 @@ BIN =\ blind-invert-luma\ blind-make-kernel\ blind-next-frame\ + blind-quaternion-product\ + blind-premultiply\ blind-read-head\ blind-repeat\ blind-reverse\ @@ -51,6 +55,8 @@ BIN =\ blind-to-video\ blind-translate\ blind-transpose\ + blind-unpremultiply\ + blind-vector-projection\ blind-write-head\ blind-kernel\ blind-temporal-mean diff --git a/README b/README @@ -33,12 +33,18 @@ UTILITIES blind-convert(1) Change pixel format of a video + blind-cross-product(1) + Calculate the cross product of colours in a video + blind-crop(1) Extract subframes for all frames blind-cut(1) Retain consecutive frames + blind-dot-product(1) + Calculate the dot product of colours in a video + blind-dissolve(1) Fade a video by chaning it's alpha channel @@ -87,6 +93,12 @@ UTILITIES blind-next-frame(1) Extracts the next frame from a video + blind-premultiply(1) + Premultiply the alpha channel of a video + + blind-quaternion-product(1) + Calculate the quaternion product of colours in a video + blind-read-head(1) Reads the head from a video @@ -162,6 +174,12 @@ UTILITIES blind-transpose(1) Transpose a video + blind-unpremultiply(1) + Unpremultiply the alpha channel of a video + + blind-vector-projection(1) + Calculate the projection or rejection of colours in a video + blind-write-head(1) Writes the head of a video diff --git a/TODO b/TODO @@ -64,6 +64,13 @@ long double (xyza q) could be added as another format. unsigned char (xyza 8) could be added as another format, it's probably good for previewing +UNTESTED: + blind-dot-product + blind-cross-product + blind-quaternion-product + blind-vector-projection + + HELP REQUIRED: blind-z-map create a Z-map video from two or more videos blind-track track the movement of a point diff --git a/man/blind-arithm.1 b/man/blind-arithm.1 @@ -77,6 +77,10 @@ Do not modify the Y channel (the second channel). Do not modify the Z channel (the third channel). .SH SEE ALSO .BR blind (7), +.BR blind-dot-product (1), +.BR blind-cross-product (1), +.BR blind-quaternion-product (1), +.BR blind-vector-projection (1), .BR blind-single-colour (1), .BR blind-set-alpha (1), .BR blind-set-luma (1), diff --git a/man/blind-cross-product.1 b/man/blind-cross-product.1 @@ -0,0 +1,32 @@ +.TH BLIND-CROSS-PRODUCT 1 blind +.SH NAME +blind-cross-product - Calculate the cross product of colours in a video +.SH SYNOPSIS +.B blind-cross-product +.I right-hand-stream +.SH DESCRIPTION +.B blind-cross-product +reads left-hand operands from stdin, and right-hand +operands from +.IR right-hand-stream , +and calculates the cross product of the colours. +The values of the alpha channels multiple with each +others with regular scalar-scalar multiplication. +.P +If stdin is longer than +.IR right-hand-stream , +the remainder of stdin is printed without any changes. +If stdin is shorter than +.IR right-hand-stream , +the remainder of +.I right-hand-stream +is ignored but may be partially read. +.SH SEE ALSO +.BR blind (7), +.BR blind-arithm (1), +.BR blind-dot-product (1), +.BR blind-quaternion-product (1), +.BR blind-vector-projection (1) +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/man/blind-dot-product.1 b/man/blind-dot-product.1 @@ -0,0 +1,31 @@ +.TH BLIND-DOT-PRODUCT 1 blind +.SH NAME +blind-dot-product - Calculate the dot product of colours in a video +.SH SYNOPSIS +.B blind-dot-product +.I right-hand-stream +.SH DESCRIPTION +.B blind-dot-product +reads left-hand operands from stdin, and right-hand +operands from +.IR right-hand-stream , +and calculates the dot product of the colours. The +product is store in all four channels. +.P +If stdin is longer than +.IR right-hand-stream , +the remainder of stdin is printed without any changes. +If stdin is shorter than +.IR right-hand-stream , +the remainder of +.I right-hand-stream +is ignored but may be partially read. +.SH SEE ALSO +.BR blind (7), +.BR blind-arithm (1), +.BR blind-cross-product (1), +.BR blind-quaternion-product (1), +.BR blind-vector-projection (1) +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/man/blind-premultiply.1 b/man/blind-premultiply.1 @@ -0,0 +1,27 @@ +.TH BLIND-PREMULTIPLY 1 blind +.SH NAME +blind-premultiply - Premultiply the alpha channel of a video +.SH SYNOPSIS +.B blind-premultiply +[-xyz] +.SH DESCRIPTION +.B blind-premultiply +reads a video from stdin and multiplies the +colour values with the alpha value for each pixel, +and prints the resulting video to stdout. +.SH OPTIONS +.TP +.B -x +Do not modify the X channel (the first channel). +.TP +.B -y +Do not modify the Y channel (the second channel). +.TP +.B -z +Do not modify the Z channel (the third channel). +.SH SEE ALSO +.BR blind (7), +.BR blind-unpremultiply (1) +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/man/blind-quaternion-product.1 b/man/blind-quaternion-product.1 @@ -0,0 +1,36 @@ +.TH BLIND-QUATERNION-PRODUCT 1 blind +.SH NAME +blind-quaternion-product - Calculate the quaternion product of colours in a video +.SH SYNOPSIS +.B blind-quaternion-product +.I right-hand-stream +.SH DESCRIPTION +.B blind-quaternion-product +reads left-hand operands from stdin, and right-hand +operands from +.IR right-hand-stream , +and calculates the quaternion product of the colours. +The values in the the first channel (the X channel) are +treated as real, the values in the the second channel +(the Y channel) are treated as i-imaginary, the values +in the the third channel (the Z channel) are treated +as j-imaginary, and the values in the the fourth channel +(the alpha channel) are treated as k-imaginary. +.P +If stdin is longer than +.IR right-hand-stream , +the remainder of stdin is printed without any changes. +If stdin is shorter than +.IR right-hand-stream , +the remainder of +.I right-hand-stream +is ignored but may be partially read. +.SH SEE ALSO +.BR blind (7), +.BR blind-arithm (1), +.BR blind-cross-product (1), +.BR blind-quaternion-product (1), +.BR blind-vector-projection (1) +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/man/blind-unpremultiply.1 b/man/blind-unpremultiply.1 @@ -0,0 +1,29 @@ +.TH BLIND-UNPREMULTIPLY 1 blind +.SH NAME +blind-unpremultiply - Unpremultiply the alpha channel of a video +.SH SYNOPSIS +.B blind-unpremultiply +[-xyz] +.SH DESCRIPTION +.B blind-unpremultiply +reads a video from stdin and divides the colour +with the alpha value for each pixel, and prints +the resulting video to stdout, effectively +undoing affects of +.BR blind-unpremultiply (1). +.SH OPTIONS +.TP +.B -x +Do not modify the X channel (the first channel). +.TP +.B -y +Do not modify the Y channel (the second channel). +.TP +.B -z +Do not modify the Z channel (the third channel). +.SH SEE ALSO +.BR blind (7), +.BR blind-premultiply (1) +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/man/blind-vector-projection.1 b/man/blind-vector-projection.1 @@ -0,0 +1,41 @@ +.TH BLIND-VECTOR-PROJECTION 1 blind +.SH NAME +blind-vector-projection - Calculate the projection or rejection of colours in a video +.SH SYNOPSIS +.B blind-vector-projection +[-r | -s] +.I plane-stream +.SH DESCRIPTION +.B blind-vector-projection +reads a video from stdin and a video from +.IR plane-stream , +and calculates the projection of the colours from +stdin onto the colours from +.I plane-stream +and prints the resulting video to stdout. +.P +If stdin is longer than +.IR plane-stream , +the remainder of stdin is printed without any changes. +If stdin is shorter than +.IR plane-stream , +the remainder of +.I plane-stream +is ignored but may be partially read. +.SH OPTIONS +.TP +.B -r +Calculate the vector rejection instead of the vector projection. +.TP +.B -s +Calculate the scalar projection instead of the vector projection. +The scalar projection is stored in all four channels. +.SH SEE ALSO +.BR blind (7), +.BR blind-arithm (1), +.BR blind-dot-product (1), +.BR blind-cross-product (1), +.BR blind-quaternion-product (1) +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/man/blind.7 b/man/blind.7 @@ -43,6 +43,9 @@ Concatenate videos .BR blind-convert (1) Change pixel format of a video .TP +.BR blind-cross-product (1) +Calculate the cross product of colours in a video +.TP .BR blind-crop (1) Extract subframes for all frames .TP @@ -58,6 +61,9 @@ Fade a video by chaning it's alpha channel .BR blind-disperse (1) Framewise split a video into multiple videos .TP +.BR blind-dot-product (1) +Calculate the dot product of colours in a video +.TP .BR blind-extend (1) Add margins to a video .TP @@ -100,6 +106,12 @@ Create a custom convolution matrix .BR blind-next-frame (1) Extracts the next frame from a video .TP +.BR blind-premultiply (1) +Premultiply the alpha channel of a video +.TP +.BR blind-quaternion-product (1) +Calculate the quaternion product of colours in a video +.TP .BR blind-read-head (1) Reads the head from a video .TP @@ -177,6 +189,12 @@ Perform framewise translation of a video .BR blind-transpose (1) Transpose a video .TP +.BR blind-unpremultiply (1) +Unpremultiply the alpha channel of a video +.TP +.BR blind-vector-projection (1) +Calculate the projection or rejection of colours in a video +.TP .BR blind-write-head (1) Writes the head of a video .SH SEE ALSO diff --git a/src/blind-cross-product.c b/src/blind-cross-product.c @@ -0,0 +1,62 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("right-hand-stream") + +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" +#endif + +#define PROCESS(TYPE, SUFFIX)\ + static void\ + process_##SUFFIX(struct stream *left, struct stream *right, size_t n)\ + {\ + size_t i;\ + TYPE *lx, *ly, *lz, *la, *rx, *ry, *rz, *ra, x, y, z, a;\ + for (i = 0; i < n; i += 4 * sizeof(TYPE)) {\ + lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i)) + 0;\ + ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i)) + 1;\ + lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i)) + 2;\ + la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i)) + 3;\ + x = *ly * *rz - *lz * *ry;\ + y = *lz * *rx - *lx * *rz;\ + z = *lx * *ry - *ly * *rx;\ + a = *la * *ra;\ + *lx = x;\ + *ly = y;\ + *lz = z;\ + *la = a;\ + }\ + } + +PROCESS(double, lf) +PROCESS(float, f) + +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic pop +#endif + +int +main(int argc, char *argv[]) +{ + struct stream left, right; + void (*process)(struct stream *left, struct stream *right, size_t n); + + UNOFLAGS(argc != 2); + + eopen_stream(&left, NULL); + eopen_stream(&right, argv[1]); + + if (!strcmp(left.pixfmt, "xyza")) + process = process_lf; + else if (!strcmp(left.pixfmt, "xyza f")) + process = process_f; + else + eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt); + + fprint_stream_head(stdout, &left); + efflush(stdout, "<stdout>"); + process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process); + return 0; +} diff --git a/src/blind-dot-product.c b/src/blind-dot-product.c @@ -0,0 +1,55 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("right-hand-stream") + +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" +#endif + +#define PROCESS(TYPE, SUFFIX)\ + static void\ + process_##SUFFIX(struct stream *left, struct stream *right, size_t n)\ + {\ + size_t i;\ + TYPE *lx, *ly, *lz, *la, *rx, *ry, *rz, *ra;\ + for (i = 0; i < n; i += 4 * sizeof(TYPE)) {\ + lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i)) + 0;\ + ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i)) + 1;\ + lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i)) + 2;\ + la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i)) + 3;\ + *lx = *ly = *lz = *la = *lx * *rx + *ly * *ry + *lz * *rz + *la * *ra;\ + }\ + } + +PROCESS(double, lf) +PROCESS(float, f) + +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic pop +#endif + +int +main(int argc, char *argv[]) +{ + struct stream left, right; + void (*process)(struct stream *left, struct stream *right, size_t n); + + UNOFLAGS(argc != 2); + + eopen_stream(&left, NULL); + eopen_stream(&right, argv[1]); + + if (!strcmp(left.pixfmt, "xyza")) + process = process_lf; + else if (!strcmp(left.pixfmt, "xyza f")) + process = process_f; + else + eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt); + + fprint_stream_head(stdout, &left); + efflush(stdout, "<stdout>"); + process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process); + return 0; +} diff --git a/src/blind-premultiply.c b/src/blind-premultiply.c @@ -0,0 +1,76 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-xyz]") + +static int skip_x = 0; +static int skip_y = 0; +static int skip_z = 0; + + +#define PROCESS(TYPE, SUFFIX)\ + static void\ + process_##SUFFIX(struct stream *stream)\ + {\ + size_t i, n;\ + TYPE a;\ + do {\ + n = stream->ptr / stream->pixel_size;\ + for (i = 0; i < n; i++) {\ + a = ((TYPE *)(stream->buf))[4 * i + 3];\ + if (!skip_x)\ + ((TYPE *)(stream->buf))[4 * i + 0] *= a;\ + if (!skip_y)\ + ((TYPE *)(stream->buf))[4 * i + 1] *= a;\ + if (!skip_z)\ + ((TYPE *)(stream->buf))[4 * i + 2] *= a;\ + }\ + n *= stream->pixel_size;\ + ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\ + memmove(stream->buf, stream->buf + n, stream->ptr -= n);\ + } while (eread_stream(stream, SIZE_MAX));\ + if (stream->ptr)\ + eprintf("%s: incomplete frame\n", stream->file);\ + } + +PROCESS(double, lf) +PROCESS(float, f) + + +int +main(int argc, char *argv[]) +{ + struct stream stream; + void (*process)(struct stream *stream); + + ARGBEGIN { + case 'x': + skip_x = 1; + break; + case 'y': + skip_y = 1; + break; + case 'z': + skip_z = 1; + break; + default: + usage(); + } ARGEND; + + if (argc) + usage(); + + eopen_stream(&stream, NULL); + + if (!strcmp(stream.pixfmt, "xyza")) + process = process_lf; + else if (!strcmp(stream.pixfmt, "xyza f")) + process = process_f; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); + + fprint_stream_head(stdout, &stream); + efflush(stdout, "<stdout>"); + process(&stream); + return 0; +} diff --git a/src/blind-quaternion-product.c b/src/blind-quaternion-product.c @@ -0,0 +1,62 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("right-hand-stream") + +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" +#endif + +#define PROCESS(TYPE, SUFFIX)\ + static void\ + process_##SUFFIX(struct stream *left, struct stream *right, size_t n)\ + {\ + size_t i;\ + TYPE *lx, *ly, *lz, *la, *rx, *ry, *rz, *ra, x, y, z, a;\ + for (i = 0; i < n; i += 4 * sizeof(TYPE)) {\ + lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i)) + 0;\ + ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i)) + 1;\ + lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i)) + 2;\ + la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i)) + 3;\ + x = *lx * *rx - *ly * *ry - *lz * *rz - *la * *ra;\ + y = *lz * *ra - *la * *rz + *lx * *ry + *ly * *rx;\ + z = *la * *ry - *ly * *rz + *lx * *rz + *lz * *rx;\ + a = *ly * *rz - *lz * *rz + *lx * *ra + *la * *rx;\ + *lx = x;\ + *ly = y;\ + *lz = z;\ + *la = a;\ + }\ + } + +PROCESS(double, lf) +PROCESS(float, f) + +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic pop +#endif + +int +main(int argc, char *argv[]) +{ + struct stream left, right; + void (*process)(struct stream *left, struct stream *right, size_t n); + + UNOFLAGS(argc != 2); + + eopen_stream(&left, NULL); + eopen_stream(&right, argv[1]); + + if (!strcmp(left.pixfmt, "xyza")) + process = process_lf; + else if (!strcmp(left.pixfmt, "xyza f")) + process = process_f; + else + eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt); + + fprint_stream_head(stdout, &left); + efflush(stdout, "<stdout>"); + process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process); + return 0; +} diff --git a/src/blind-unpremultiply.c b/src/blind-unpremultiply.c @@ -0,0 +1,78 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-xyz]") + +static int skip_x = 0; +static int skip_y = 0; +static int skip_z = 0; + + +#define PROCESS(TYPE, SUFFIX)\ + static void\ + process_##SUFFIX(struct stream *stream)\ + {\ + size_t i, n;\ + TYPE a;\ + do {\ + n = stream->ptr / stream->pixel_size;\ + for (i = 0; i < n; i++) {\ + a = ((TYPE *)(stream->buf))[4 * i + 3];\ + if (!a)\ + continue;\ + if (!skip_x)\ + ((TYPE *)(stream->buf))[4 * i + 0] /= a;\ + if (!skip_y)\ + ((TYPE *)(stream->buf))[4 * i + 1] /= a;\ + if (!skip_z)\ + ((TYPE *)(stream->buf))[4 * i + 2] /= a;\ + }\ + n *= stream->pixel_size;\ + ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\ + memmove(stream->buf, stream->buf + n, stream->ptr -= n);\ + } while (eread_stream(stream, SIZE_MAX));\ + if (stream->ptr)\ + eprintf("%s: incomplete frame\n", stream->file);\ + } + +PROCESS(double, lf) +PROCESS(float, f) + + +int +main(int argc, char *argv[]) +{ + struct stream stream; + void (*process)(struct stream *stream); + + ARGBEGIN { + case 'x': + skip_x = 1; + break; + case 'y': + skip_y = 1; + break; + case 'z': + skip_z = 1; + break; + default: + usage(); + } ARGEND; + + if (argc) + usage(); + + eopen_stream(&stream, NULL); + + if (!strcmp(stream.pixfmt, "xyza")) + process = process_lf; + else if (!strcmp(stream.pixfmt, "xyza f")) + process = process_f; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); + + fprint_stream_head(stdout, &stream); + efflush(stdout, "<stdout>"); + process(&stream); + return 0; +} diff --git a/src/blind-vector-projection.c b/src/blind-vector-projection.c @@ -0,0 +1,91 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-r | -s] plane-stream") + +static int level = 1; + +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" +#endif + +#define PROCESS(TYPE, SUFFIX)\ + static void\ + process_##SUFFIX(struct stream *left, struct stream *right, size_t n)\ + {\ + size_t i;\ + TYPE *lx, *ly, *lz, *la, rx, ry, rz, ra, x, y, z, a, norm;\ + for (i = 0; i < n; i += 4 * sizeof(TYPE)) {\ + lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i))[0];\ + ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i))[1];\ + lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i))[2];\ + la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i))[3];\ + norm = rx * rx + ry * ry + rz * rz + ra * ra;\ + norm = sqrt(norm);\ + x = y = z = a = *lx * rx + *ly * ry + *lz * rz + *la * ra;\ + if (level) {\ + x *= rx;\ + y *= ry;\ + z *= rz;\ + a *= rz;\ + if (level > 1) {\ + x = *lx - x;\ + y = *ly - y;\ + z = *lz - z;\ + a = *la - a;\ + }\ + }\ + *lx = x;\ + *ly = y;\ + *lz = z;\ + *la = a;\ + }\ + } + +PROCESS(double, lf) +PROCESS(float, f) + +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic pop +#endif + +int +main(int argc, char *argv[]) +{ + struct stream left, right; + void (*process)(struct stream *left, struct stream *right, size_t n); + + ARGBEGIN { + case 'r': + if (level == 0) + usage(); + level = 2; + break; + case 's': + if (level == 2) + usage(); + level = 0; + break; + default: + usage(); + } ARGEND; + + if (argc != 2) + usage(); + + eopen_stream(&left, NULL); + eopen_stream(&right, argv[1]); + + if (!strcmp(left.pixfmt, "xyza")) + process = process_lf; + else if (!strcmp(left.pixfmt, "xyza f")) + process = process_f; + else + eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt); + + fprint_stream_head(stdout, &left); + efflush(stdout, "<stdout>"); + process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process); + return 0; +}