commit fa20f84e2d12bf9998591ce4e464180586d957ff
parent 0a034f2bd5a44c3cc0c033eacc940bb3bf73662c
Author: Mattias Andrée <maandree@kth.se>
Date: Thu, 20 Jul 2017 20:03:52 +0200
Add blind-affine-colour and blind-split-chans
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
12 files changed, 335 insertions(+), 17 deletions(-)
diff --git a/Makefile b/Makefile
@@ -3,6 +3,7 @@ include $(CONFIGFILE)
BIN =\
+ blind-affine-colour\
blind-apply-palette\
blind-arithm\
blind-cat-cols\
@@ -76,6 +77,7 @@ BIN =\
blind-spectrum\
blind-spiral-gradient\
blind-split\
+ blind-split-chans\
blind-split-cols\
blind-split-rows\
blind-square-gradient\
diff --git a/README b/README
@@ -12,6 +12,9 @@ DESCRIPTION
storing the video without first convert it with blind-to-video(1).
UTILITIES
+ blind-affine-colour(1)
+ Apply an affine transformation to the colours in a video
+
blind-arithm(1)
Perform simple arithmetic on a video
@@ -234,6 +237,9 @@ UTILITIES
blind-split(1)
Split a video, by frame, into multiple videos
+ blind-split-chans(1)
+ Split colour channels into separate videos
+
blind-split-cols(1)
Split a video vertically into multiple videos
diff --git a/TODO b/TODO
@@ -1,22 +1,17 @@
Fix blind-from-named without command
-blind-transform affine transformation by matrix multiplication, -t for tiling, -s for
- improve quality on downscaling (pixels' neighbours must not change).
-blind-primary-key replace a primary with transparency, -g for greyscaled images.
-blind-primaries given three selectable primaries split the video into three side-by-side which
- only one primary active.
-blind-apply-map remap pixels (distortion) using the X and Y values, -t for tiling, -s for
- improve quality on downscaling (pixels' neighbours must not change).
+blind-transform affine transformation by matrix multiplication, -[xy] for tiling, -s for
+ improve quality on downscaling (pixels' neighbours must not change)
+blind-primary-key replace a primary with transparency, -g for greyscaled images
+blind-colour-matrix create colour space conversion matrix
+blind-apply-map remap pixels (distortion) using the X and Y values, -[xy] for tiling, -s for
+ improve quality on downscaling (pixels' neighbours must not change)
blind-apply-kernel apply a convolution matrix.
blind-find-frame a graphical tool for locating frames, should highlight key frames, and
- play audio. Should support both regular videos files and uivf.
+ play audio. Should support both regular videos files and uivf
finding key frames: ffprobe -show_frames (lists all frames)
-blind-affine-colour apply an affine transformation to the colour of each pixel,
- -a for ignoring the alpha channel,
- -l for linear transformation,
- -p for transforming each pixel with their own transformation.
blind-invert-chroma invert the chroma
-blind-from-sent convert a sent presentation to a one-frame-per-slide blind video.
+blind-from-sent convert a sent presentation to a one-frame-per-slide blind video
blind-kirsch https://en.wikipedia.org/wiki/Kirsch_operator
blind-gaussian-noise https://en.wikipedia.org/wiki/Gaussian_noise
@@ -43,6 +38,10 @@ blind-mean mean of multiple streams
https://en.wikipedia.org/wiki/Stolarsky_mean
blind-temporal-arithm blind-arithm but over all frames in a video instead of over all streams
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
+ (convexo-concave gradient is not necessary is blind-convex-gradient
+ or blind-concave-gradient can be combined with blind-arithm for this)
blind-from-video: add options to:
* just run ffmpeg just print the output
diff --git a/man/blind-affine-colour.1 b/man/blind-affine-colour.1
@@ -0,0 +1,71 @@
+.TH BLIND-AFFINE-COLOUR 1 blind
+.SH NAME
+blind-affine-colour - Apply an affine transformation to the colours in a video
+.SH SYNOPSIS
+.B blind-affine-colour
+[-alp]
+.I matrix-stream
+.SH DESCRIPTION
+.B blind-affine-colour
+reads a video from stdin and a matrix video from
+.I matrix-stream
+and multiplies colours from stdin with matrices from
+.I matrix-stream
+and prints the resulting video to stdout.
+.P
+Each frame in
+.I matrix-stream
+is a matrix and shall have the width and height 5.
+Each pixel in a frame is a cell in the matrix,
+the pixels luma is multiples by its alpha value
+to determine the value of the matrix cell.
+.SH OPTIONS
+.TP
+.B -a
+The width and height of the matrix shall be 4
+instead of 5 (reduced by 1) and the alpha values
+of the pixels shall not be modified.
+.TP
+.B -l
+The width and height of the matrix shall be 4
+instead of 5 (reduced by 1) making the transformation
+linear instead of affine.
+.TP
+.B -p
+Each frame in
+.I matrix-stream
+shall contain one matrix per pixel in a frame in
+stdin. The video in
+.I matrix-stream
+shall be 5, 4, or 3, depending on whether
+.B -a
+and
+.B -l
+are specified, times are wide and tall as the
+video in stdin.
+.SH NOTES
+If both
+.B -a
+and
+.B -l
+are specified, the matrices shall have the
+width and height 3 instead of 5.
+.SH REQUIREMENTS
+.B blind-affine-colour
+requires enough free memory to load 5, 4, or 3,
+depending on whether
+.B -a
+and
+.B -l
+are specified, full rows from
+.I matrix-stream
+into memory. A frame requires 32 bytes per pixel
+it contains.
+.SH SEE ALSO
+.BR blind (7),
+.BR blind-arithm (1),
+.BR blind-invert-matrix (1),
+.BR blind-multiply-matrice (1)
+.SH AUTHORS
+Mattias Andrée
+.RI < maandree@kth.se >
diff --git a/man/blind-arithm.1 b/man/blind-arithm.1
@@ -90,7 +90,8 @@ Do not modify the Z channel (the third channel).
.BR blind-set-alpha (1),
.BR blind-set-luma (1),
.BR blind-invert-luma (1),
-.BR blind-set-saturation (1)
+.BR blind-set-saturation (1),
+.BR blind-affine-colour (1)
.SH AUTHORS
Mattias Andrée
.RI < maandree@kth.se >
diff --git a/man/blind-invert-matrix.1 b/man/blind-invert-matrix.1
@@ -29,7 +29,8 @@ are identical.
.BR blind-flop (1),
.BR blind-rotate-90 (1),
.BR blind-rotate-180 (1),
-.BR blind-rotate-270 (1)
+.BR blind-rotate-270 (1),
+.BR blind-rewrite-head (1)
.SH AUTHORS
Mattias Andrée
.RI < maandree@kth.se >
diff --git a/man/blind-multiply-matrices.1 b/man/blind-multiply-matrices.1
@@ -44,7 +44,8 @@ in reverse order.
.BR blind-flop (1),
.BR blind-rotate-90 (1),
.BR blind-rotate-180 (1),
-.BR blind-rotate-270 (1)
+.BR blind-rotate-270 (1),
+.BR blind-rewrite-head (1)
.SH AUTHORS
Mattias Andrée
.RI < maandree@kth.se >
diff --git a/man/blind-rewrite-head.1 b/man/blind-rewrite-head.1
@@ -72,7 +72,8 @@ two copies of on disc.
.BR blind-from-video (1),
.BR blind-split (1),
.BR blind-read-head (1),
-.BR blind-write-head (1)
+.BR blind-write-head (1),
+.BR blind-transpose (1)
.SH AUTHORS
Mattias Andrée
.RI < maandree@kth.se >
diff --git a/man/blind-split-chans.1 b/man/blind-split-chans.1
@@ -0,0 +1,47 @@
+.TH BLIND-SPLIT-CHANS 1 blind
+.SH NAME
+blind-split-chans - Split colour channels into separate videos
+.SH SYNOPSIS
+.B blind-split-chans
+.I X-file
+.I Y-file
+.I Z-file
+.RI [ alpha-file ]
+.SH DESCRIPTION
+.B blind-split-chans
+reads a video from stdin and prints
+it to
+.I X-file
+with the values of the first channel
+(the X channel) in written to all
+channels, to
+.I Y-file
+with the values of the second channel
+(the Y channel) in written to all
+channels, to
+.I Z-file
+with the values of the third channel
+(the Z channel) in written to all
+channels, and to
+.I alpha-file
+with the values of the fourth channel
+(the alpha channel) in written to all
+channels.
+.P
+If
+.I alpha-file
+is omitted, values of the alpha channel
+are instead written to the alpha channels
+in
+.IR X-file ,
+.IR Y-file ,
+and
+.IR Z-file .
+.SH SEE ALSO
+.BR blind (7),
+.BR blind-arithm (1),
+.BR blind-cat-cols (1),
+.BR blind-cat-rows (1)
+.SH AUTHORS
+Mattias Andrée
+.RI < maandree@kth.se >
diff --git a/man/blind.7 b/man/blind.7
@@ -19,6 +19,9 @@ first convert it with
.BR blind-to-video (1).
.SH UTILITIES
.TP
+.BR blind-affine-colour (1)
+Apply an affine transformation to the colours in a video
+.TP
.BR blind-arithm (1)
Perform simple arithmetic on a video
.TP
@@ -247,6 +250,9 @@ Generate a video with a spiral gradient
.BR blind-split (1)
Split a video, by frame, into multiple videos
.TP
+.BR blind-split-chans (1)
+Split colour channels into separate videos
+.TP
.BR blind-split-cols (1)
Split a video vertically into multiple videos
.TP
diff --git a/src/blind-affine-colour.c b/src/blind-affine-colour.c
@@ -0,0 +1,118 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef TYPE
+#include "common.h"
+
+USAGE("[-alp] matrix-stream")
+
+static int skip_alpha = 0;
+static int linear = 0;
+static int per_pixel = 0;
+static size_t dim;
+
+#define FILE "blind-affine-colour.c"
+#include "define-functions.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct stream colour, matrix;
+ void (*process)(struct stream *colour, struct stream *matrix);
+ size_t h;
+
+ ARGBEGIN {
+ case 'a':
+ skip_alpha = 1;
+ break;
+ case 'l':
+ linear = 1;
+ break;
+ case 'p':
+ per_pixel = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc != 1)
+ usage();
+
+ eopen_stream(&colour, NULL);
+ eopen_stream(&matrix, argv[0]);
+
+ SELECT_PROCESS_FUNCTION(&colour);
+
+ if (strcmp(colour.pixfmt, matrix.pixfmt))
+ eprintf("videos use incompatible pixel formats\n");
+
+ dim = colour.n_chan - (size_t)skip_alpha + (size_t)!linear;
+ h = matrix.height, matrix.height = dim;
+ echeck_dimensions(&matrix, WIDTH | HEIGHT, "matrix");
+ matrix.height = h;
+
+ if (per_pixel) {
+ if (matrix.height != dim * colour.height || matrix.width != dim * colour.width)
+ eprintf("the matrice should have the size %zux%zu, but are %zux%zu",
+ dim * colour.height, dim * colour.width, matrix.height, matrix.width);
+ } else {
+ if (matrix.height != dim || matrix.width != dim)
+ eprintf("the matrice should have the size %zux%zu, but are %zux%zu",
+ dim, dim, matrix.height, matrix.width);
+ }
+
+ fprint_stream_head(stdout, &colour);
+ efflush(stdout, "<stdout>");
+ process(&colour, &matrix);
+ return 0;
+}
+
+#else
+
+static void
+PROCESS(struct stream *colour, struct stream *matrix)
+{
+ char *mbuf;
+ TYPE *mat, *pixel, V[5], M[ELEMENTSOF(V)][ELEMENTSOF(V)];
+ size_t ptr, i, j, w, x = 0, y = 0, cn;
+
+ mbuf = emalloc2(dim, matrix->row_size);
+ mat = (TYPE *)mbuf;
+ w = matrix->width * matrix->n_chan;
+ cn = colour->n_chan - (size_t)skip_alpha;
+
+ memset(M, 0, sizeof(M));
+ for (i = 0; i < ELEMENTSOF(V); i++)
+ M[i][i] = V[i] = 1;
+
+ do {
+ for (ptr = 0; ptr + colour->pixel_size <= colour->ptr; x = (x + 1) % colour->width, ptr += colour->pixel_size) {
+ if (!x) {
+ if (!y && !eread_segment(matrix, mbuf, dim * matrix->row_size))
+ break;
+ if (!per_pixel)
+ y = (y + 1) % colour->height;
+ }
+ if (per_pixel) {
+ mat = (TYPE *)(mbuf + x * dim * matrix->pixel_size);
+ for (i = 0; i < dim; i++, mat += w)
+ for (j = 0; j < dim; j++)
+ M[i][j] = mat[j * matrix->n_chan + 1] * mat[(j + 1) * matrix->n_chan - 1];
+ }
+ pixel = (TYPE *)(colour->buf + ptr);
+ for (i = 0; i < dim; i++) {
+ V[i] = 0;
+ for (j = 0; j < cn; j++)
+ V[i] += M[i][j] * pixel[j];
+ for (; j < dim; j++)
+ V[i] += M[i][j];
+ }
+ for (i = 0; i < cn; i++)
+ pixel[i] = V[i] / V[cn];
+ }
+ ewriteall(STDOUT_FILENO, colour->buf, ptr, "<stdout>");
+ memmove(colour->buf, colour->buf + ptr, colour->ptr -= ptr);
+ } while (eread_stream(colour, SIZE_MAX));
+ if (colour->ptr)
+ eprintf("%s: incomplete frame\n", colour->file);
+}
+
+#endif
diff --git a/src/blind-split-chans.c b/src/blind-split-chans.c
@@ -0,0 +1,65 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("X-file Y-file Z-file [alpha-file]")
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ char xbuf[BUFSIZ], ybuf[BUFSIZ], zbuf[BUFSIZ], abuf[BUFSIZ];
+ int xfd, yfd, zfd, afd = -1;
+ size_t i, n, ptr;
+
+ UNOFLAGS(argc != 3 && argc != 4);
+
+ eopen_stream(&stream, NULL);
+
+ xfd = eopen(argv[0], O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ yfd = eopen(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ zfd = eopen(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (argc == 4)
+ afd = eopen(argv[3], O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+ if (DPRINTF_HEAD(xfd, stream.frames, stream.width, stream.height, stream.pixfmt) < 0)
+ eprintf("dprintf %s:", argv[0]);
+ if (DPRINTF_HEAD(yfd, stream.frames, stream.width, stream.height, stream.pixfmt) < 0)
+ eprintf("dprintf %s:", argv[1]);
+ if (DPRINTF_HEAD(zfd, stream.frames, stream.width, stream.height, stream.pixfmt) < 0)
+ eprintf("dprintf %s:", argv[2]);
+ if (afd >= 0 && DPRINTF_HEAD(afd, stream.frames, stream.width, stream.height, stream.pixfmt) < 0)
+ eprintf("dprintf %s:", argv[3]);
+
+ n = (stream.n_chan - (afd < 0)) * stream.chan_size;
+ do {
+ for (ptr = 0; ptr + stream.pixel_size <= stream.ptr; ptr += stream.pixel_size) {
+ for (i = 0; i < n; i += stream.chan_size) {
+ memcpy(xbuf + ptr + i, stream.buf + ptr + 0 * stream.chan_size, stream.chan_size);
+ memcpy(ybuf + ptr + i, stream.buf + ptr + 1 * stream.chan_size, stream.chan_size);
+ memcpy(zbuf + ptr + i, stream.buf + ptr + 2 * stream.chan_size, stream.chan_size);
+ if (afd >= 0)
+ memcpy(abuf + ptr + i, stream.buf + ptr + 3 * stream.chan_size, stream.chan_size);
+ }
+ if (afd < 0) {
+ memcpy(xbuf + ptr + n, stream.buf + ptr + 3 * stream.chan_size, stream.chan_size);
+ memcpy(ybuf + ptr + n, stream.buf + ptr + 3 * stream.chan_size, stream.chan_size);
+ memcpy(zbuf + ptr + n, stream.buf + ptr + 3 * stream.chan_size, stream.chan_size);
+ }
+ }
+ ewriteall(xfd, xbuf, ptr, argv[0]);
+ ewriteall(yfd, ybuf, ptr, argv[1]);
+ ewriteall(zfd, zbuf, ptr, argv[2]);
+ if (afd >= 0)
+ ewriteall(afd, abuf, ptr, argv[3]);
+ memmove(stream.buf, stream.buf + ptr, stream.ptr -= ptr);
+ } while (eread_stream(&stream, SIZE_MAX));
+ if (stream.ptr)
+ eprintf("%s: incomplete frame\n", stream.file);
+
+ close(xfd);
+ close(yfd);
+ close(zfd);
+ if (afd >= 0)
+ close(afd);
+ return 0;
+}