Code

refactoring:
[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 "display/nr-filter-utils.h"
14 #include <vector>
15 namespace NR {
17 FilterConvolveMatrix::FilterConvolveMatrix()
18 : orderX(3),
19   orderY(3),
20   targetX((int)(orderX/2)),
21   targetY((int)(orderY/2)),
22   bias(0),
23   edgeMode((NR::FilterConvolveMatrixEdgeMode) 0),
24   preserveAlpha(false)
25 {}
27 FilterPrimitive * FilterConvolveMatrix::create() {
28     return new FilterConvolveMatrix();
29 }
31 FilterConvolveMatrix::~FilterConvolveMatrix()
32 {}
34 static bool inside_area(int px, int py, int w, int h){
35         if (px<0) return false;
36         if (py<0) return false;
37         if (px>w) return false;
38         if (py>h) return false;
39         return true;
40 }
42 int FilterConvolveMatrix::render(FilterSlot &slot, Matrix const &trans) {
43     NRPixBlock *in = slot.get(_input);
44     NRPixBlock *out = new NRPixBlock;
46     nr_pixblock_setup_fast(out, in->mode,
47                            in->area.x0, in->area.y0, in->area.x1, in->area.y1,
48                            true);
50     unsigned char *in_data = NR_PIXBLOCK_PX(in);
51     unsigned char *out_data = NR_PIXBLOCK_PX(out);
53     double result_R, result_G, result_B, result_A;
54     int i, j, x, y;
55     int width = in->area.x1 - in->area.x0;
56     int height = in->area.y1 - in->area.y0;
58     double div=0;
60     if (divisor != 0){
61         div = divisor;
62     } else {
63         for (i=0;i<orderX*orderY;i++){
64             div += kernelMatrix[i];
65         }
66     }
68     for (x=targetX; x < width - (orderX - targetX); x++){
69         for (y=targetY; y < height - (orderY - targetY); y++){
70             result_R = 0;
71             result_G = 0;
72             result_B = 0;
73             result_A = 0;
74             for (i=0; i < orderY; i++){
75                 for (j=0; j < orderX; j++){
76                     if (inside_area(x - targetX + j, y - targetY + i, width, height)){
77                         result_R += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
78                         result_G += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )+1] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
79                         result_B += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )+2] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
80                         result_A += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )+3] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
81                     }
82                 }
83             }
85             out_data[4*( x + width*y )] = CLAMP_D_TO_U8(result_R / div + bias);
86             out_data[4*( x + width*y )+1] = CLAMP_D_TO_U8(result_G / div + bias);
87             out_data[4*( x + width*y )+2] = CLAMP_D_TO_U8(result_B / div + bias);
88             out_data[4*( x + width*y )+3] = CLAMP_D_TO_U8(result_A / div + bias);
89         }
90     }
92     out->empty = FALSE;
93     slot.set(_output, out);
94     return 0;
95 }
97 void FilterConvolveMatrix::set_targetX(int coord) {
98     targetX = coord;
99 }
101 void FilterConvolveMatrix::set_targetY(int coord) {
102     targetY = coord;
105 void FilterConvolveMatrix::set_orderX(int coord) {
106     orderX = coord;
109 void FilterConvolveMatrix::set_orderY(int coord) {
110     orderY = coord;
113 void FilterConvolveMatrix::set_divisor(double d) {
114     divisor = d;
117 void FilterConvolveMatrix::set_bias(double b) {
118     bias = b;
121 void FilterConvolveMatrix::set_kernelMatrix(std::vector<gdouble> &km) {
122     kernelMatrix = km;
125 void FilterConvolveMatrix::set_edgeMode(FilterConvolveMatrixEdgeMode mode){
126     edgeMode = mode;
127 }    
129 void FilterConvolveMatrix::set_preserveAlpha(bool pa){
130     preserveAlpha = pa;
133 void FilterConvolveMatrix::area_enlarge(NRRectL &area, Matrix const &trans)
135     //Seems to me that since this filter's operation is resolution dependent,
136     // some spurious pixels may still appear at the borders when low zooming or rotating. Needs a better fix.
137     area.x0 -= targetX;
138     area.y0 -= targetY;
139     area.x1 += orderX - targetX;
140     area.y1 += orderY - targetY;
143 } /* namespace NR */
145 /*
146   Local Variables:
147   mode:c++
148   c-file-style:"stroustrup"
149   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
150   indent-tabs-mode:nil
151   fill-column:99
152   End:
153 */
154 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :