Add blind-multiply-matrices - blind - suckless command-line video editing utili… | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 1d6f31b2f6092e05056dc6a3d97b03a251f110e1 | |
parent edc0a1ca9c1c85a77ac04eb78c8fa208e0c5b24f | |
Author: Mattias Andrée <[email protected]> | |
Date: Fri, 14 Jul 2017 17:38:11 +0200 | |
Add blind-multiply-matrices | |
Signed-off-by: Mattias Andrée <[email protected]> | |
Diffstat: | |
M Makefile | 1 + | |
M README | 3 +++ | |
M man/blind-matrix-orthoproject.1 | 3 ++- | |
M man/blind-matrix-reflect.1 | 3 ++- | |
M man/blind-matrix-rotate.1 | 3 ++- | |
M man/blind-matrix-scale.1 | 3 ++- | |
M man/blind-matrix-shear.1 | 3 ++- | |
M man/blind-matrix-translate.1 | 3 ++- | |
M man/blind-matrix-transpose.1 | 3 ++- | |
A man/blind-multiply-matrices.1 | 43 ++++++++++++++++++++++++++++++ | |
M man/blind-stack.1 | 2 +- | |
M man/blind.7 | 3 +++ | |
A src/blind-multiply-matrices.c | 138 ++++++++++++++++++++++++++++++ | |
13 files changed, 203 insertions(+), 8 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
@@ -50,6 +50,7 @@ BIN =\ | |
blind-matrix-transpose\ | |
blind-mosaic\ | |
blind-mosaic-edges\ | |
+ blind-multiply-matrices\ | |
blind-next-frame\ | |
blind-norm\ | |
blind-quaternion-product\ | |
diff --git a/README b/README | |
@@ -144,6 +144,9 @@ UTILITIES | |
blind-mosaic-edges(1) | |
Find edges in a mosaic video | |
+ blind-multiply-matrices(1) | |
+ Multiply matrix-vidoes | |
+ | |
blind-next-frame(1) | |
Extracts the next frame from a video | |
diff --git a/man/blind-matrix-orthoproject.1 b/man/blind-matrix-orthoproject.1 | |
@@ -37,7 +37,8 @@ channels in stdout. | |
.BR blind-matrix-scale (1), | |
.BR blind-matrix-shear (1), | |
.BR blind-matrix-translate (1), | |
-.BR blind-matrix-transpose (1) | |
+.BR blind-matrix-transpose (1), | |
+.BR blind-multiply-matrices (1) | |
.SH AUTHORS | |
Mattias Andrée | |
.RI < [email protected] > | |
diff --git a/man/blind-matrix-reflect.1 b/man/blind-matrix-reflect.1 | |
@@ -37,7 +37,8 @@ channels in stdout. | |
.BR blind-matrix-scale (1), | |
.BR blind-matrix-shear (1), | |
.BR blind-matrix-translate (1), | |
-.BR blind-matrix-transpose (1) | |
+.BR blind-matrix-transpose (1), | |
+.BR blind-multiply-matrices (1) | |
.SH AUTHORS | |
Mattias Andrée | |
.RI < [email protected] > | |
diff --git a/man/blind-matrix-rotate.1 b/man/blind-matrix-rotate.1 | |
@@ -39,7 +39,8 @@ grows upwards rather than downwards. | |
.BR blind-matrix-scale (1), | |
.BR blind-matrix-shear (1), | |
.BR blind-matrix-translate (1), | |
-.BR blind-matrix-transpose (1) | |
+.BR blind-matrix-transpose (1), | |
+.BR blind-multiply-matrices (1) | |
.SH AUTHORS | |
Mattias Andrée | |
.RI < [email protected] > | |
diff --git a/man/blind-matrix-scale.1 b/man/blind-matrix-scale.1 | |
@@ -37,7 +37,8 @@ channels in stdout. | |
.BR blind-matrix-rotate (1), | |
.BR blind-matrix-shear (1), | |
.BR blind-matrix-translate (1), | |
-.BR blind-matrix-transpose (1) | |
+.BR blind-matrix-transpose (1), | |
+.BR blind-multiply-matrices (1) | |
.SH AUTHORS | |
Mattias Andrée | |
.RI < [email protected] > | |
diff --git a/man/blind-matrix-shear.1 b/man/blind-matrix-shear.1 | |
@@ -52,7 +52,8 @@ other. | |
.BR blind-matrix-rotate (1), | |
.BR blind-matrix-scale (1), | |
.BR blind-matrix-translate (1), | |
-.BR blind-matrix-transpose (1) | |
+.BR blind-matrix-transpose (1), | |
+.BR blind-multiply-matrices (1) | |
.SH AUTHORS | |
Mattias Andrée | |
.RI < [email protected] > | |
diff --git a/man/blind-matrix-translate.1 b/man/blind-matrix-translate.1 | |
@@ -41,7 +41,8 @@ Y-axis grows upwards rather than downwards. | |
.BR blind-matrix-rotate (1), | |
.BR blind-matrix-scale (1), | |
.BR blind-matrix-shear (1), | |
-.BR blind-matrix-transpose (1) | |
+.BR blind-matrix-transpose (1), | |
+.BR blind-multiply-matrices (1) | |
.SH AUTHORS | |
Mattias Andrée | |
.RI < [email protected] > | |
diff --git a/man/blind-matrix-transpose.1 b/man/blind-matrix-transpose.1 | |
@@ -37,7 +37,8 @@ channels in stdout. | |
.BR blind-matrix-rotate (1), | |
.BR blind-matrix-scale (1), | |
.BR blind-matrix-shear (1), | |
-.BR blind-matrix-translate (1) | |
+.BR blind-matrix-translate (1), | |
+.BR blind-multiply-matrices (1) | |
.SH AUTHORS | |
Mattias Andrée | |
.RI < [email protected] > | |
diff --git a/man/blind-multiply-matrices.1 b/man/blind-multiply-matrices.1 | |
@@ -0,0 +1,43 @@ | |
+.TH BLIND-MULTIPLY-MATRICES 1 blind | |
+.SH NAME | |
+blind-multiply-matrices - Multiply matrix-vidoes | |
+.SH SYNOPSIS | |
+.B blind-multiply-matrices | |
+[-en] | |
+.I leftmost-stream | |
+.RI "... " rightmost-stream | |
+.SH DESCRIPTION | |
+.B blind-multiply-matrices | |
+reads videos representing matrices from the files | |
+specified via the arguments | |
+.I leftmost-stream | |
+to | |
+.IR rightmost-stream , | |
+and multiples them, frame by frame, from right to | |
+left, and prints the resulting video to stdout. | |
+Each frame in a video contains one matrix per | |
+channel, made up from the values on a channel | |
+of each pixel. | |
+.SH OPTIONS | |
+.TP | |
+.B -e | |
+Apply optimisation that assumes all channels | |
+are identical. | |
+.TP | |
+.B -n | |
+Reverse the order of each specified files, | |
+so that the transformations are applied in | |
+the order they are specified rather than | |
+in reverse order. | |
+.SH SEE ALSO | |
+.BR blind (7), | |
+.BR blind-matrix-orthoproject (1), | |
+.BR blind-matrix-reflect (1), | |
+.BR blind-matrix-rotate (1), | |
+.BR blind-matrix-scale (1), | |
+.BR blind-matrix-shear (1), | |
+.BR blind-matrix-translate (1), | |
+.BR blind-matrix-transpose (1) | |
+.SH AUTHORS | |
+Mattias Andrée | |
+.RI < [email protected] > | |
diff --git a/man/blind-stack.1 b/man/blind-stack.1 | |
@@ -4,7 +4,7 @@ blind-stack - Overlay videos | |
.SH SYNOPSIS | |
.B blind-stack | |
[-bs] | |
-.IR bottom-stream | |
+.I bottom-stream | |
.RI "... " top-stream | |
.SH DESCRIPTION | |
.B blind-stack | |
diff --git a/man/blind.7 b/man/blind.7 | |
@@ -160,6 +160,9 @@ Redraw each frame in video as a mosaic | |
.BR blind-mosaic-edges (1) | |
Find edges in a mosaic video | |
.TP | |
+.BR blind-multiply-matrices (1) | |
+Multiply matrix-vidoes | |
+.TP | |
.BR blind-next-frame (1) | |
Extracts the next frame from a video | |
.TP | |
diff --git a/src/blind-multiply-matrices.c b/src/blind-multiply-matrices.c | |
@@ -0,0 +1,138 @@ | |
+/* See LICENSE file for copyright and license details. */ | |
+#include "common.h" | |
+ | |
+USAGE("[-en] leftmost-stream ... rightmost-stream") | |
+ | |
+static int equal = 0; | |
+static size_t max_frame_size; | |
+ | |
+#define PROCESS(TYPE)\ | |
+ do {\ | |
+ typedef TYPE pixel_t[4];\ | |
+ pixel_t *res, *left, *right, *tmp;\ | |
+ size_t i, j, w, h, h2, x, y, k, r;\ | |
+ res = emalloc(max_frame_size);\ | |
+ left = emalloc(max_frame_size);\ | |
+ right = emalloc(max_frame_size);\ | |
+ \ | |
+ while (eread_frame(streams + (n_streams - 1), res)) {\ | |
+ w = streams[n_streams - 1].width;\ | |
+ h = streams[n_streams - 1].height;\ | |
+ for (i = n_streams - 1; i--;) {\ | |
+ tmp = res, res = right, right = tmp;\ | |
+ if (!eread_frame(streams + i, left))\ | |
+ goto done;\ | |
+ h2 = streams[i].height;\ | |
+ memset(res, 0, w * h2 * streams->pixel_size);\ | |
+ \ | |
+ /* XXX Is there any significant performance to… | |
+ if (equal) {\ | |
+ for (y = r = 0; y < h2; y++) {\ | |
+ for (x = 0; x < w; x++, r++) {\ | |
+ for (k = 0; k < h; k++… | |
+ res[r][1] += l… | |
+ res[r][3] = res[r][2] … | |
+ }\ | |
+ }\ | |
+ } else {\ | |
+ for (y = r = 0; y < h2; y++)\ | |
+ for (x = 0; x < w; x++, r++) \ | |
+ for (k = 0; k < h; k++… | |
+ for (j = 0; j … | |
+ res[r]… | |
+ }\ | |
+ \ | |
+ h = h2;\ | |
+ }\ | |
+ ewriteall(STDOUT_FILENO, res, streams->frame_size, "<s… | |
+ }\ | |
+ \ | |
+ done:\ | |
+ free(res);\ | |
+ free(left);\ | |
+ free(right);\ | |
+ } while (0) | |
+ | |
+static void process_lf(struct stream *streams, size_t n_streams) { PROCESS(dou… | |
+static void process_f (struct stream *streams, size_t n_streams) { PROCESS(flo… | |
+ | |
+int | |
+main(int argc, char *argv[]) | |
+{ | |
+ struct stream *streams; | |
+ size_t n_streams, i, frames = 0; | |
+ int natural = 0, j; | |
+ char **rev_argv; | |
+ size_t max_width = 0, max_height = 0; | |
+ size_t width = 0, height = 0, w, h; | |
+ void (*process)(struct stream *streams, size_t n_streams); | |
+ | |
+ ARGBEGIN { | |
+ case 'e': | |
+ equal = 1; | |
+ break; | |
+ case 'n': | |
+ natural = 1; | |
+ break; | |
+ default: | |
+ usage(); | |
+ } ARGEND; | |
+ | |
+ if (argc < 2) | |
+ usage(); | |
+ | |
+ if (natural) { | |
+ rev_argv = alloca(argc * sizeof(*rev_argv)); | |
+ for (j = 0; j < argc; j++) | |
+ rev_argv[j] = argv[argc - 1 - j]; | |
+ argv = rev_argv; | |
+ } | |
+ | |
+ n_streams = (size_t)argc; | |
+ streams = ecalloc(n_streams, sizeof(*streams)); | |
+ | |
+ for (i = 0; i < n_streams; i++) { | |
+ eopen_stream(streams + i, argv[i]); | |
+ if (streams[i].frames && streams[i].frames < frames) | |
+ frames = streams[i].frames; | |
+ if (streams->width > max_width) | |
+ max_width = streams->width; | |
+ if (streams->height > max_height) | |
+ max_height = streams->height; | |
+ } | |
+ for (i = 1; i < n_streams; i++) | |
+ if (strcmp(streams->pixfmt, streams[i].pixfmt)) | |
+ eprintf("videos use incompatible pixel formats\n"); | |
+ | |
+ width = streams[n_streams - 1].width; | |
+ height = streams[n_streams - 1].height; | |
+ for (i = n_streams - 1; i--;) { | |
+ if (streams[i].width != height) | |
+ eprintf("videos do not have the compatible geometry\n"… | |
+ height = streams[i].height; | |
+ } | |
+ | |
+ if (!strcmp(streams->pixfmt, "xyza")) | |
+ process = process_lf; | |
+ else if (!strcmp(streams->pixfmt, "xyza f")) | |
+ process = process_f; | |
+ else | |
+ eprintf("pixel format %s is not supported, try xyza\n", stream… | |
+ | |
+ w = streams->width, streams->width = max_width; | |
+ h = streams->height, streams->height = max_height; | |
+ echeck_dimensions(streams, WIDTH | HEIGHT, NULL); | |
+ streams->width = width; | |
+ streams->height = height; | |
+ streams->frames = frames; | |
+ fprint_stream_head(stdout, streams); | |
+ streams->width = w; | |
+ streams->height = h; | |
+ efflush(stdout, "<stdout>"); | |
+ max_frame_size = max_width * max_height * streams->pixel_size; | |
+ | |
+ process(streams, n_streams); | |
+ | |
+ free(streams); | |
+ return 0; | |
+} |