Code

Patch from Felipe Sanches: support for feConvolveMatrix filter primitive
[inkscape.git] / src / display / nr-filter-convolve-matrix.cpp
1 /*
2  * feConvolveMatrix filter primitive renderer
3  *
4  * Authors:
5  *   Felipe CorrĂȘa da Silva Sanches <felipe.sanches@gmail.com>
6  *
7  * Copyright (C) 2007 authors
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #include "display/nr-filter-convolve-matrix.h"
13 #include <vector>
14 namespace NR {
16 FilterConvolveMatrix::FilterConvolveMatrix()
17 {}
19 FilterPrimitive * FilterConvolveMatrix::create() {
20     return new FilterConvolveMatrix();
21 }
23 FilterConvolveMatrix::~FilterConvolveMatrix()
24 {}
26 static bool inside_area(int px, int py, int w, int h){
27         if (px<0) return false;
28         if (py<0) return false;
29         if (px>w) return false;
30         if (py>h) return false;
31         return true;
32 }
34 int FilterConvolveMatrix::render(FilterSlot &slot, Matrix const &trans) {
35     NRPixBlock *in = slot.get(_input);
36     NRPixBlock *out = new NRPixBlock;
38     nr_pixblock_setup_fast(out, in->mode,
39                            in->area.x0, in->area.y0, in->area.x1, in->area.y1,
40                            true);
42     unsigned char *in_data = NR_PIXBLOCK_PX(in);
43     unsigned char *out_data = NR_PIXBLOCK_PX(out);
45     double result_R, result_G, result_B, result_A;
46     int i, j, x, y;
47     int width = in->area.x1 - in->area.x0;
48     int height = in->area.y1 - in->area.y0;
50     double div=0;
52     if (divisor != 0){
53         div = divisor;
54     } else {
55         for (i=0;i<orderX*orderY;i++){
56             div += kernelMatrix[i];
57         }
58     }
60     for (x=0; x < width; x++){
61         for (y=0; y < height; y++){
62             result_R = 0;
63             result_G = 0;
64             result_B = 0;
65             result_A = 0;
66             for (i=0; i < orderY; i++){
67                 for (j=0; j < orderX; j++){
68                     if (inside_area(x - targetX + j, y - targetY + i, width, height)){
69                         result_R += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
70                         result_G += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )+1] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
71                         result_B += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )+2] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
72                         result_A += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )+3] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
73                     }
74                 }
75             }
76             result_R = result_R / div + bias;
77             result_G = result_G / div + bias;
78             result_B = result_B / div + bias;
79             result_A = result_A / div + bias;
81             result_R = (result_R > 0 ? result_R : 0);
82             result_G = (result_G > 0 ? result_G : 0);
83             result_B = (result_B > 0 ? result_B : 0);
84             result_A = (result_A > 0 ? result_A : 0);
86             out_data[4*( x + width*y )] = (result_R < 255 ? (unsigned char)result_R : 255);
87             out_data[4*( x + width*y )+1] = (result_G < 255 ? (unsigned char)result_G : 255);
88             out_data[4*( x + width*y )+2] = (result_B < 255 ? (unsigned char)result_B : 255);
89             out_data[4*( x + width*y )+3] = (result_A < 255 ? (unsigned char)result_A : 255);
90         }
91     }
93     out->empty = FALSE;
94     slot.set(_output, out);
95     return 0;
96 }
98 void FilterConvolveMatrix::set_targetX(int coord) {
99     targetX = coord;
102 void FilterConvolveMatrix::set_targetY(int coord) {
103     targetY = coord;
106 void FilterConvolveMatrix::set_orderX(int coord) {
107     orderX = coord;
110 void FilterConvolveMatrix::set_orderY(int coord) {
111     orderY = coord;
114 void FilterConvolveMatrix::set_divisor(double d) {
115     divisor = d;
118 void FilterConvolveMatrix::set_bias(double b) {
119     bias = b;
122 void FilterConvolveMatrix::set_kernelMatrix(std::vector<gdouble> &km) {
123     kernelMatrix = km;
126 void FilterConvolveMatrix::area_enlarge(NRRectL &area, Matrix const &trans)
130 } /* namespace NR */
132 /*
133   Local Variables:
134   mode:c++
135   c-file-style:"stroustrup"
136   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
137   indent-tabs-mode:nil
138   fill-column:99
139   End:
140 */
141 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :