Compositor filter node
[blender.git] / source / blender / compositor / operations / COM_ConvolutionFilterOperation.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor: 
19  *              Jeroen Bakker 
20  *              Monique Dewanchand
21  */
22
23 #include "COM_ConvolutionFilterOperation.h"
24
25 #include "BLI_utildefines.h"
26
27 ConvolutionFilterOperation::ConvolutionFilterOperation() : NodeOperation()
28 {
29         this->addInputSocket(COM_DT_COLOR);
30         this->addInputSocket(COM_DT_VALUE);
31         this->addOutputSocket(COM_DT_COLOR);
32         this->setResolutionInputSocketIndex(0);
33         this->inputOperation = NULL;
34         this->filter = NULL;
35         this->setComplex(true);
36 }
37 void ConvolutionFilterOperation::initExecution()
38 {
39         this->inputOperation = this->getInputSocketReader(0);
40         this->inputValueOperation = this->getInputSocketReader(1);
41 }
42
43 void ConvolutionFilterOperation::set3x3Filter(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9)
44 {
45         this->filter = new float[9];
46         this->filter[0] = f1;
47         this->filter[1] = f2;
48         this->filter[2] = f3;
49         this->filter[3] = f4;
50         this->filter[4] = f5;
51         this->filter[5] = f6;
52         this->filter[6] = f7;
53         this->filter[7] = f8;
54         this->filter[8] = f9;
55         this->filterHeight = 3;
56         this->filterWidth = 3;
57 }
58
59 void ConvolutionFilterOperation::deinitExecution()
60 {
61         this->inputOperation = NULL;
62         this->inputValueOperation = NULL;
63         if (this->filter) {
64                 delete this->filter;
65                 this->filter = NULL;
66         }
67 }
68
69
70 void ConvolutionFilterOperation::executePixel(float *color,int x, int y, MemoryBuffer *inputBuffers[], void *data)
71 {
72         color[0] = 0.0;
73         color[1] = 0.0;
74         color[2] = 0.0;
75         color[3] = 0.0;
76         float in1[4];
77         float in2[4];
78         int x1 = x - 1;
79         int x2 = x;
80         int x3 = x + 1;
81         int y1 = y - 1;
82         int y2 = y;
83         int y3 = y + 1;
84         CLAMP(x1, 0, getWidth()-1);
85         CLAMP(x2, 0, getWidth()-1);
86         CLAMP(x3, 0, getWidth()-1);
87         CLAMP(y1, 0, getHeight()-1);
88         CLAMP(y2, 0, getHeight()-1);
89         CLAMP(y3, 0, getHeight()-1);
90         float value[4];
91         this->inputValueOperation->read(value, x2, y2, inputBuffers, NULL);
92         float mval = 1.0f - value[0];
93         this->inputOperation->read(in1, x1, y1, inputBuffers, NULL);
94         color[0] += in1[0] * this->filter[0];
95         color[1] += in1[1] * this->filter[0];
96         color[2] += in1[2] * this->filter[0];
97         color[3] += in1[3] * this->filter[0];
98         this->inputOperation->read(in1, x2, y1, inputBuffers, NULL);
99         color[0] += in1[0] * this->filter[1];
100         color[1] += in1[1] * this->filter[1];
101         color[2] += in1[2] * this->filter[1];
102         color[3] += in1[3] * this->filter[1];
103         this->inputOperation->read(in1, x3, y1, inputBuffers, NULL);
104         color[0] += in1[0] * this->filter[2];
105         color[1] += in1[1] * this->filter[2];
106         color[2] += in1[2] * this->filter[2];
107         color[3] += in1[3] * this->filter[2];
108         this->inputOperation->read(in1, x1, y2, inputBuffers, NULL);
109         color[0] += in1[0] * this->filter[3];
110         color[1] += in1[1] * this->filter[3];
111         color[2] += in1[2] * this->filter[3];
112         color[3] += in1[3] * this->filter[3];
113         this->inputOperation->read(in2, x2, y2, inputBuffers, NULL);
114         color[0] += in2[0] * this->filter[4];
115         color[1] += in2[1] * this->filter[4];
116         color[2] += in2[2] * this->filter[4];
117         color[3] += in2[3] * this->filter[4];
118         this->inputOperation->read(in1, x3, y2, inputBuffers, NULL);
119         color[0] += in1[0] * this->filter[5];
120         color[1] += in1[1] * this->filter[5];
121         color[2] += in1[2] * this->filter[5];
122         color[3] += in1[3] * this->filter[5];
123         this->inputOperation->read(in1, x1, y3, inputBuffers, NULL);
124         color[0] += in1[0] * this->filter[6];
125         color[1] += in1[1] * this->filter[6];
126         color[2] += in1[2] * this->filter[6];
127         color[3] += in1[3] * this->filter[6];
128         this->inputOperation->read(in1, x2, y3, inputBuffers, NULL);
129         color[0] += in1[0] * this->filter[7];
130         color[1] += in1[1] * this->filter[7];
131         color[2] += in1[2] * this->filter[7];
132         color[3] += in1[3] * this->filter[7];
133         this->inputOperation->read(in1, x3, y3, inputBuffers, NULL);
134         color[0] += in1[0] * this->filter[8];
135         color[1] += in1[1] * this->filter[8];
136         color[2] += in1[2] * this->filter[8];
137         color[3] += in1[3] * this->filter[8];
138         
139         color[0] = color[0]*value[0] + in2[0] * mval;
140         color[1] = color[1]*value[0] + in2[1] * mval;
141         color[2] = color[2]*value[0] + in2[2] * mval;
142         color[3] = color[3]*value[0] + in2[3] * mval;
143 }
144
145 bool ConvolutionFilterOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
146 {
147         rcti newInput;
148         int addx = (this->filterWidth-1)/2+1;
149         int addy = (this->filterHeight-1)/2+1;
150         newInput.xmax = input->xmax + addx;
151         newInput.xmin = input->xmin - addx;
152         newInput.ymax = input->ymax + addy;
153         newInput.ymin = input->ymin - addy;
154         
155         return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
156 }