svn merge ^/trunk/blender -r50173:50179
[blender.git] / source / blender / compositor / operations / COM_BlurBaseOperation.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_BlurBaseOperation.h"
24 #include "BLI_math.h"
25 #include "MEM_guardedalloc.h"
26
27 extern "C" {
28         #include "RE_pipeline.h"
29 }
30
31 BlurBaseOperation::BlurBaseOperation(DataType data_type) : NodeOperation()
32 {
33         /* data_type is almost always COM_DT_COLOR except for alpha-blur */
34         this->addInputSocket(data_type);
35         this->addInputSocket(COM_DT_VALUE);
36         this->addOutputSocket(data_type);
37         this->setComplex(true);
38         this->m_inputProgram = NULL;
39         this->m_data = NULL;
40         this->m_size = 1.0f;
41         this->m_deleteData = false;
42         this->m_sizeavailable = false;
43 }
44 void BlurBaseOperation::initExecution()
45 {
46         this->m_inputProgram = this->getInputSocketReader(0);
47         this->m_inputSize = this->getInputSocketReader(1);
48         this->m_data->image_in_width = this->getWidth();
49         this->m_data->image_in_height = this->getHeight();
50         if (this->m_data->relative) {
51                 switch (this->m_data->aspect) {
52                         case CMP_NODE_BLUR_ASPECT_NONE:
53                                 this->m_data->sizex = (int)(this->m_data->percentx * 0.01f * this->m_data->image_in_width);
54                                 this->m_data->sizey = (int)(this->m_data->percenty * 0.01f * this->m_data->image_in_height);
55                                 break;
56                         case CMP_NODE_BLUR_ASPECT_Y:
57                                 this->m_data->sizex = (int)(this->m_data->percentx * 0.01f * this->m_data->image_in_width);
58                                 this->m_data->sizey = (int)(this->m_data->percenty * 0.01f * this->m_data->image_in_width);
59                                 break;
60                         case CMP_NODE_BLUR_ASPECT_X:
61                                 this->m_data->sizex = (int)(this->m_data->percentx * 0.01f * this->m_data->image_in_height);
62                                 this->m_data->sizey = (int)(this->m_data->percenty * 0.01f * this->m_data->image_in_height);
63                                 break;
64                 }
65         }
66
67         QualityStepHelper::initExecution(COM_QH_MULTIPLY);
68
69 }
70
71 float *BlurBaseOperation::make_gausstab(int rad)
72 {
73         float *gausstab, sum, val;
74         int i, n;
75
76         n = 2 * rad + 1;
77
78         gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__);
79
80         sum = 0.0f;
81         for (i = -rad; i <= rad; i++) {
82                 val = RE_filter_value(this->m_data->filtertype, (float)i / (float)rad);
83                 sum += val;
84                 gausstab[i + rad] = val;
85         }
86
87         sum = 1.0f / sum;
88         for (i = 0; i < n; i++)
89                 gausstab[i] *= sum;
90
91         return gausstab;
92 }
93
94 /* normalized distance from the current (inverted so 1.0 is close and 0.0 is far)
95  * 'ease' is applied after, looks nicer */
96 float *BlurBaseOperation::make_dist_fac_inverse(int rad, int falloff)
97 {
98         float *dist_fac_invert, val;
99         int i, n;
100
101         n = 2 * rad + 1;
102
103         dist_fac_invert = (float *)MEM_mallocN(sizeof(float) * n, __func__);
104
105         for (i = -rad; i <= rad; i++) {
106                 val = 1.0f - fabsf(((float)i / (float)rad));
107
108                 /* keep in sync with proportional_falloff_curve_only_items */
109                 switch (falloff) {
110                         case PROP_SMOOTH:
111                                 /* ease - gives less hard lines for dilate/erode feather */
112                                 val = (3.0f * val * val - 2.0f * val * val * val);
113                                 break;
114                         case PROP_SPHERE:
115                                 val = sqrtf(2.0f * val - val * val);
116                                 break;
117                         case PROP_ROOT:
118                                 val = sqrtf(val);
119                                 break;
120                         case PROP_SHARP:
121                                 val = val * val;
122                                 break;
123                         case PROP_LIN:
124 #ifndef NDEBUG
125                         /* uninitialized! */
126                         case -1:
127                                 BLI_assert(0);
128 #endif
129                         default:
130                                 /* nothing */
131                                 break;
132                 }
133                 dist_fac_invert[i + rad] = val;
134         }
135
136         return dist_fac_invert;
137 }
138
139 void BlurBaseOperation::deinitExecution()
140 {
141         this->m_inputProgram = NULL;
142         this->m_inputSize = NULL;
143         if (this->m_deleteData) {
144                 delete this->m_data;
145         }
146         this->m_data = NULL;
147 }
148
149 void BlurBaseOperation::updateSize()
150 {
151         if (!this->m_sizeavailable) {
152                 float result[4];
153                 this->getInputSocketReader(1)->read(result, 0, 0, COM_PS_NEAREST);
154                 this->m_size = result[0];
155                 this->m_sizeavailable = true;
156         }
157 }