1
#ifndef __NR_FILTER_PIXOPS_H__
2
#define __NR_FILTER_PIXOPS_H__
5
* Per-pixel image manipulation functions.
6
* These can be used by all filter primitives, which combine two images on
7
* per-pixel basis. These are at least feBlend, feComposite and feMerge.
10
* Niko Kiirala <niko@kiirala.com>
12
* Copyright (C) 2007 authors
14
* Released under GNU GPL, read the file 'COPYING' for more information
20
* Mixes the two input images using the function given as template.
21
* The result is placed in out.
22
* The mixing function should have the following type:
23
* void mix(unsigned char *result, unsigned char const *in1,
24
* unsigned char const *in2);
25
* Each of the parameters for mix-function is a pointer to four bytes of data,
26
* giving the RGBA values for that pixel. The mix function must only access
27
* the four bytes beginning at a pointer given as parameter.
30
* The implementation is in a header file because of the template. It has to
31
* be in the same compilation unit as the code using it. Otherwise, linking
32
* the program will not succeed.
34
template <void(*blend)(unsigned char *cr, unsigned char const *ca, unsigned char const *cb)>
35
void pixops_mix(NRPixBlock &out, NRPixBlock &in1, NRPixBlock &in2) {
36
unsigned char *in1_data = NR_PIXBLOCK_PX(&in1);
37
unsigned char *in2_data = NR_PIXBLOCK_PX(&in2);
38
unsigned char *out_data = NR_PIXBLOCK_PX(&out);
39
unsigned char zero_rgba[4] = {0, 0, 0, 0};
41
if (in1.area.y0 < in2.area.y0) {
42
// in1 begins before in2 on y-axis
43
for (int y = in1.area.y0 ; y < in2.area.y0 ; y++) {
44
int out_line = (y - out.area.y0) * out.rs;
45
int in_line = (y - in1.area.y0) * in1.rs;
46
for (int x = in1.area.x0 ; x < in1.area.x1 ; x++) {
47
blend(out_data + out_line + 4 * (x - out.area.x0),
48
in1_data + in_line + 4 * (x - in1.area.x0),
52
} else if (in1.area.y0 > in2.area.y0) {
53
// in2 begins before in1 on y-axis
54
for (int y = in2.area.y0 ; y < in1.area.y0 ; y++) {
55
int out_line = (y - out.area.y0) * out.rs;
56
int in_line = (y - in2.area.y0) * in2.rs;
57
for (int x = in2.area.x0 ; x < in2.area.x1 ; x++) {
58
blend(out_data + out_line + 4 * (x - out.area.x0),
60
in2_data + in_line + 4 * (x - in2.area.x0));
65
for (int y = std::max(in1.area.y0, in2.area.y0) ;
66
y < std::min(in1.area.y1, in2.area.y1) ; ++y) {
67
int out_line = (y - out.area.y0) * out.rs;
68
int in1_line = (y - in1.area.y0) * in1.rs;
69
int in2_line = (y - in2.area.y0) * in2.rs;
71
if (in1.area.x0 < in2.area.x0) {
72
// in1 begins before in2 on x-axis
73
for (int x = in1.area.x0 ; x < in2.area.x0 ; ++x) {
74
blend(out_data + out_line + 4 * (x - out.area.x0),
75
in1_data + in1_line + 4 * (x - in1.area.x0),
78
} else if (in1.area.x0 > in2.area.x0) {
79
// in2 begins before in1 on x-axis
80
for (int x = in2.area.x0 ; x < in1.area.x0 ; ++x) {
81
blend(out_data + out_line + 4 * (x - out.area.x0),
83
in2_data + in2_line + 4 * (x - in2.area.x0));
87
for (int x = std::max(in1.area.x0, in2.area.x0) ;
88
x < std::min(in1.area.x1, in2.area.x1) ; ++x) {
89
blend(out_data + out_line + 4 * (x - out.area.x0),
90
in1_data + in1_line + 4 * (x - in1.area.x0),
91
in2_data + in2_line + 4 * (x - in2.area.x0));
94
if (in1.area.x1 > in2.area.x1) {
95
// in1 ends after in2 on x-axis
96
for (int x = in2.area.x1 ; x < in1.area.x1 ; ++x) {
97
blend(out_data + out_line + 4 * (x - out.area.x0),
98
in1_data + in1_line + 4 * (x - in1.area.x0),
101
} else if (in1.area.x1 < in2.area.x1) {
102
// in2 ends after in1 on x-axis
103
for (int x = in1.area.x1 ; x < in2.area.x1 ; ++x) {
104
blend(out_data + out_line + 4 * (x - out.area.x0),
106
in2_data + in2_line + 4 * (x - in2.area.x0));
111
if (in1.area.y1 > in2.area.y1) {
112
// in1 ends after in2 on y-axis
113
for (int y = in2.area.y1 ; y < in1.area.y1 ; y++) {
114
int out_line = (y - out.area.y0) * out.rs;
115
int in_line = (y - in1.area.y0) * in1.rs;
116
for (int x = in1.area.x0 ; x < in1.area.x1 ; x++) {
117
blend(out_data + out_line + 4 * (x - out.area.x0),
118
in1_data + in_line + 4 * (x - in1.area.x0),
122
} else if (in1.area.y1 < in2.area.y1) {
123
// in2 ends after in1 on y-axis
124
for (int y = in1.area.y1 ; y < in2.area.y1 ; y++) {
125
int out_line = (y - out.area.y0) * out.rs;
126
int in_line = (y - in2.area.y0) * in2.rs;
127
for (int x = in2.area.x0 ; x < in2.area.x1 ; x++) {
128
blend(out_data + out_line + 4 * (x - out.area.x0),
130
in2_data + in_line + 4 * (x - in2.area.x0));
138
#endif // __NR_FILTER_PIXOPS_H_
142
c-file-style:"stroustrup"
143
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
148
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :