aboutsummaryrefslogtreecommitdiffstats
path: root/src/blind-affine-colour.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/blind-affine-colour.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/blind-affine-colour.c b/src/blind-affine-colour.c
new file mode 100644
index 0000000..88fd76a
--- /dev/null
+++ 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