aboutsummaryrefslogtreecommitdiffstats
path: root/libglitter_compose_double.c
blob: 53da733b3e796f44c287bc9eceb4a7d76e5dd523 (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
119
120
121
122
123
124
125
126
127
128
/* See LICENSE file for copyright and license details. */
#include "common.h"
#ifndef TEST


static void
vstrips(double **outputs_, const double *restrict input, size_t output_rowsize, size_t output_cellsize,
        size_t input_rowsize, size_t width, size_t height, const uint8_t *restrict cellmap)
{
	double *outputs[3];
	size_t y, x, output_y, output_i, input_blanking;

	outputs[0] = outputs_[cellmap[0]];
	outputs[1] = outputs_[cellmap[1]];
	outputs[2] = outputs_[cellmap[2]];

	output_rowsize *= output_cellsize;
	input_blanking = input_rowsize - width * 3;

	for (y = 0, output_y = 0; y < height; y++, output_y += output_rowsize) {
		for (x = 0, output_i = output_y; x < width; x++, output_i += output_cellsize) {

			outputs[0][output_i] = input[0];
			outputs[1][output_i] = input[1];
			outputs[2][output_i] = input[2];
			input = &input[3];
		}
		input = &input[input_blanking];
	}
}


static void
hstrips(double **outputs_, const double *restrict input, size_t output_rowsize, size_t output_cellsize,
        size_t input_rowsize, size_t width, size_t height, const uint8_t *restrict cellmap)
{
	double *outputs[3];
	size_t y, x, output_y, output_i, input_blanking;

	outputs[0] = outputs_[cellmap[0]];
	outputs[1] = outputs_[cellmap[1]];
	outputs[2] = outputs_[cellmap[2]];

	output_rowsize *= output_cellsize;
	input_blanking = input_rowsize * 3 - width;

	for (y = 0, output_y = 0; y < height; y++, output_y += output_rowsize) {
		for (x = 0, output_i = output_y; x < width; x++, output_i += output_cellsize) {

			outputs[0][output_i] = input[0 * input_rowsize];
			outputs[1][output_i] = input[1 * input_rowsize];
			outputs[2][output_i] = input[2 * input_rowsize];
			input = &input[1];
		}
		input = &input[input_blanking];
	}
}


# ifndef ONLY_INT_COMPATIBLE


static void
generic(double **outputs, size_t noutputs, const double *restrict input,
        size_t output_rowsize, size_t output_cellsize, size_t input_rowsize,
        size_t width, size_t height, size_t widthmul, size_t heightmul,
        const uint8_t *restrict cellmap, const double *restrict cellweights)
{
	size_t y, x, iy, ix, i, output_y, output_i, input_blanking;
	uint8_t channel;
	double value;

	output_rowsize *= output_cellsize;
	input_blanking = input_rowsize * heightmul - width * widthmul;

	for (y = 0, output_y = 0; y < height; y++, output_y += output_rowsize) {
		for (x = 0, output_i = output_y; x < width; x++, output_i += output_cellsize) {

			for (i = 0; i < noutputs; i++)
				outputs[i][output_i] = 0;
			for (iy = 0; iy < heightmul; iy++) {
				for (ix = 0; ix < widthmul; ix++) {
					channel = cellmap[iy * widthmul + ix];

					value = input[iy * input_rowsize + ix];
					value *= cellweights[channel];

					outputs[channel][output_i] += value;
				}
			}
			input = &input[widthmul];
		}
		input = &input[input_blanking];
	}
}


void
libglitter_compose_double(double **outputs, const double *restrict input, size_t output_rowsize, size_t output_cellsize,
                          size_t width, size_t height, const LIBGLITTER_RENDER_CONTEXT *render_ctx)
{
	if (render_ctx->render_method == RENDER_METHOD_VSTRIPS) {
		vstrips(outputs, input, output_rowsize, output_cellsize, render_ctx->rowsize, width, height, render_ctx->cellmap);
	} else if (render_ctx->render_method == RENDER_METHOD_HSTRIPS) {
		hstrips(outputs, input, output_rowsize, output_cellsize, render_ctx->rowsize, width, height, render_ctx->cellmap);
	} else {
		generic(outputs, render_ctx->noutputs, input, output_rowsize, output_cellsize, render_ctx->rowsize, width, height,
		        render_ctx->widthmul, render_ctx->heightmul, render_ctx->cellmap, render_ctx->cellweights_double);
	}
}


# endif


#else
# ifndef ONLY_INT_COMPATIBLE


int
main(void)
{
	return 0; /* TODO add test */
}


# endif
#endif