aboutsummaryrefslogtreecommitdiffstats
path: root/src/blind-affine-colour.c
blob: 88fd76a744af5c37f2ce87a36cab18e9936c5989 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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