d213f5c713cb78c09a8fafe5824b29f5fdf09fde
[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 ConvolutionFilterOperation::ConvolutionFilterOperation() : NodeOperation()
26 {
27         this->addInputSocket(COM_DT_COLOR);
28         this->addInputSocket(COM_DT_VALUE);
29         this->addOutputSocket(COM_DT_COLOR);
30         this->setResolutionInputSocketIndex(0);
31         this->inputOperation = NULL;
32         this->filter = NULL;
33         this->setComplex(true);
34 }
35 void ConvolutionFilterOperation::initExecution()
36 {
37         this->inputOperation = this->getInputSocketReader(0);
38         this->inputValueOperation = this->getInputSocketReader(1);
39 }
40
41 void ConvolutionFilterOperation::set3x3Filter(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9)
42 {
43         this->filter = new float[9];
44         this->filter[0] = f1;
45         this->filter[1] = f2;
46         this->filter[2] = f3;
47         this->filter[3] = f4;
48         this->filter[4] = f5;
49         this->filter[5] = f6;
50         this->filter[6] = f7;
51         this->filter[7] = f8;
52         this->filter[8] = f9;
53         this->filterHeight = 3;
54         this->filterWidth = 3;
55 }
56
57 void ConvolutionFilterOperation::deinitExecution()
58 {
59         this->inputOperation = NULL;
60         this->inputValueOperation = NULL;
61         if (this->filter) {
62                 delete this->filter;
63                 this->filter = NULL;
64         }
65 }
66
67
68 void ConvolutionFilterOperation::executePixel(float *color,int x, int y, MemoryBuffer *inputBuffers[], void *data)
69 {
70         color[0] = 0.0;
71         color[1] = 0.0;
72         color[2] = 0.0;
73         color[3] = 0.0;
74         float in1[4];
75         float in2[4];
76         float value[4];
77         this->inputValueOperation->read(value, x, y, inputBuffers, NULL);
78         float mval = 1.0f - value[0];
79         
80         this->inputOperation->read(in1, x-1, y-1, inputBuffers, NULL);
81         color[0] += in1[0] * this->filter[0];
82         color[1] += in1[1] * this->filter[0];
83         color[2] += in1[2] * this->filter[0];
84         color[3] += in1[3] * this->filter[0];
85         this->inputOperation->read(in1, x, y-1, inputBuffers, NULL);
86         color[0] += in1[0] * this->filter[1];
87         color[1] += in1[1] * this->filter[1];
88         color[2] += in1[2] * this->filter[1];
89         color[3] += in1[3] * this->filter[1];
90         this->inputOperation->read(in1, x+1, y-1, inputBuffers, NULL);
91         color[0] += in1[0] * this->filter[2];
92         color[1] += in1[1] * this->filter[2];
93         color[2] += in1[2] * this->filter[2];
94         color[3] += in1[3] * this->filter[2];
95         this->inputOperation->read(in1, x-1, y, inputBuffers, NULL);
96         color[0] += in1[0] * this->filter[3];
97         color[1] += in1[1] * this->filter[3];
98         color[2] += in1[2] * this->filter[3];
99         color[3] += in1[3] * this->filter[3];
100         this->inputOperation->read(in2, x, y, inputBuffers, NULL);
101         color[0] += in2[0] * this->filter[4];
102         color[1] += in2[1] * this->filter[4];
103         color[2] += in2[2] * this->filter[4];
104         color[3] += in2[3] * this->filter[4];
105         this->inputOperation->read(in1, x+1, y, inputBuffers, NULL);
106         color[0] += in1[0] * this->filter[5];
107         color[1] += in1[1] * this->filter[5];
108         color[2] += in1[2] * this->filter[5];
109         color[3] += in1[3] * this->filter[5];
110         this->inputOperation->read(in1, x-1, y+1, inputBuffers, NULL);
111         color[0] += in1[0] * this->filter[6];
112         color[1] += in1[1] * this->filter[6];
113         color[2] += in1[2] * this->filter[6];
114         color[3] += in1[3] * this->filter[6];
115         this->inputOperation->read(in1, x, y+1, inputBuffers, NULL);
116         color[0] += in1[0] * this->filter[7];
117         color[1] += in1[1] * this->filter[7];
118         color[2] += in1[2] * this->filter[7];
119         color[3] += in1[3] * this->filter[7];
120         this->inputOperation->read(in1, x+1, y+1, inputBuffers, NULL);
121         color[0] += in1[0] * this->filter[8];
122         color[1] += in1[1] * this->filter[8];
123         color[2] += in1[2] * this->filter[8];
124         color[3] += in1[3] * this->filter[8];
125         
126         color[0] = color[0]*value[0] + in2[0] * mval;
127         color[1] = color[1]*value[0] + in2[1] * mval;
128         color[2] = color[2]*value[0] + in2[2] * mval;
129         color[3] = color[3]*value[0] + in2[3] * mval;
130 }
131
132 bool ConvolutionFilterOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
133 {
134         rcti newInput;
135         int addx = (this->filterWidth-1)/2+1;
136         int addy = (this->filterHeight-1)/2+1;
137         newInput.xmax = input->xmax + addx;
138         newInput.xmin = input->xmin - addx;
139         newInput.ymax = input->ymax + addy;
140         newInput.ymin = input->ymin - addy;
141         
142         return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
143 }