2
* Copyright 2011, Blender Foundation.
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.
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.
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.
23
#include "COM_GaussianBokehBlurOperation.h"
25
#include "MEM_guardedalloc.h"
27
#include "RE_pipeline.h"
30
GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation(COM_DT_COLOR)
32
this->m_gausstab = NULL;
35
void *GaussianBokehBlurOperation::initializeTileData(rcti *rect)
38
if (!this->m_sizeavailable) {
41
void *buffer = getInputOperation(0)->initializeTileData(NULL);
46
void GaussianBokehBlurOperation::initExecution()
48
BlurBaseOperation::initExecution();
52
if (this->m_sizeavailable) {
57
void GaussianBokehBlurOperation::updateGauss()
59
if (this->m_gausstab == NULL) {
67
const float width = this->getWidth();
68
const float height = this->getHeight();
69
if (!this->m_sizeavailable) {
72
radxf = this->m_size * (float)this->m_data->sizex;
73
if (radxf > width / 2.0f)
75
else if (radxf < 1.0f)
79
radyf = this->m_size * (float)this->m_data->sizey;
80
if (radyf > height / 2.0f)
81
radyf = height / 2.0f;
82
else if (radyf < 1.0f)
85
this->m_radx = ceil(radxf);
86
this->m_rady = ceil(radyf);
88
n = (2 * this->m_radx + 1) * (2 * this->m_rady + 1);
90
/* create a full filter image */
91
ddgauss = (float *)MEM_mallocN(sizeof(float) * n, __func__);
94
for (j = -this->m_rady; j <= this->m_rady; j++) {
95
for (i = -this->m_radx; i <= this->m_radx; i++, dgauss++) {
96
float fj = (float)j / radyf;
97
float fi = (float)i / radxf;
98
float dist = sqrt(fj * fj + fi * fi);
99
*dgauss = RE_filter_value(this->m_data->filtertype, dist);
106
for (j = n - 1; j >= 0; j--) {
110
else ddgauss[4] = 1.0f;
112
this->m_gausstab = ddgauss;
116
void GaussianBokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
123
float multiplier_accum = 0;
124
MemoryBuffer *inputBuffer = (MemoryBuffer *)data;
125
float *buffer = inputBuffer->getBuffer();
126
int bufferwidth = inputBuffer->getWidth();
127
int bufferstartx = inputBuffer->getRect()->xmin;
128
int bufferstarty = inputBuffer->getRect()->ymin;
130
int miny = y - this->m_rady;
131
int maxy = y + this->m_rady;
132
int minx = x - this->m_radx;
133
int maxx = x + this->m_radx;
134
miny = max(miny, inputBuffer->getRect()->ymin);
135
minx = max(minx, inputBuffer->getRect()->xmin);
136
maxy = min(maxy, inputBuffer->getRect()->ymax);
137
maxx = min(maxx, inputBuffer->getRect()->xmax);
140
int step = QualityStepHelper::getStep();
141
int offsetadd = QualityStepHelper::getOffsetAdd();
142
const int addConst = (minx - x + this->m_radx);
143
const int mulConst = (this->m_radx * 2 + 1);
144
for (int ny = miny; ny < maxy; ny += step) {
145
index = ((ny - y) + this->m_rady) * mulConst + addConst;
146
int bufferindex = ((minx - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth);
147
for (int nx = minx; nx < maxx; nx += step) {
148
const float multiplier = this->m_gausstab[index];
149
madd_v4_v4fl(tempColor, &buffer[bufferindex], multiplier);
150
multiplier_accum += multiplier;
152
bufferindex += offsetadd;
156
mul_v4_v4fl(output, tempColor, 1.0f / multiplier_accum);
159
void GaussianBokehBlurOperation::deinitExecution()
161
BlurBaseOperation::deinitExecution();
162
MEM_freeN(this->m_gausstab);
163
this->m_gausstab = NULL;
168
bool GaussianBokehBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
176
NodeOperation *operation = this->getInputOperation(1);
178
if (operation->determineDependingAreaOfInterest(&sizeInput, readOperation, output)) {
182
if (this->m_sizeavailable && this->m_gausstab != NULL) {
185
newInput.xmax = this->getWidth();
186
newInput.ymax = this->getHeight();
189
int addx = this->m_radx;
190
int addy = this->m_rady;
191
newInput.xmax = input->xmax + addx;
192
newInput.xmin = input->xmin - addx;
193
newInput.ymax = input->ymax + addy;
194
newInput.ymin = input->ymin - addy;
197
return BlurBaseOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
202
GaussianBlurReferenceOperation::GaussianBlurReferenceOperation() : BlurBaseOperation(COM_DT_COLOR)
204
this->m_maintabs = NULL;
207
void *GaussianBlurReferenceOperation::initializeTileData(rcti *rect)
209
void *buffer = getInputOperation(0)->initializeTileData(NULL);
213
void GaussianBlurReferenceOperation::initExecution()
215
BlurBaseOperation::initExecution();
217
this->m_data->image_in_width = this->getWidth();
218
this->m_data->image_in_height = this->getHeight();
219
if (this->m_data->relative) {
220
switch (this->m_data->aspect) {
221
case CMP_NODE_BLUR_ASPECT_NONE:
222
this->m_data->sizex = (int)(this->m_data->percentx * 0.01f * this->m_data->image_in_width);
223
this->m_data->sizey = (int)(this->m_data->percenty * 0.01f * this->m_data->image_in_height);
225
case CMP_NODE_BLUR_ASPECT_Y:
226
this->m_data->sizex = (int)(this->m_data->percentx * 0.01f * this->m_data->image_in_width);
227
this->m_data->sizey = (int)(this->m_data->percenty * 0.01f * this->m_data->image_in_width);
229
case CMP_NODE_BLUR_ASPECT_X:
230
this->m_data->sizex = (int)(this->m_data->percentx * 0.01f * this->m_data->image_in_height);
231
this->m_data->sizey = (int)(this->m_data->percenty * 0.01f * this->m_data->image_in_height);
238
m_radx = (float)this->m_data->sizex;
239
int imgx = getWidth() / 2;
244
m_radxf = (float)m_radx;
247
m_rady = (float)this->m_data->sizey;
248
int imgy = getHeight() / 2;
253
m_radyf = (float)m_rady;
257
void GaussianBlurReferenceOperation::updateGauss()
260
int x = max(m_radx, m_rady);
261
this->m_maintabs = (float **)MEM_mallocN(x * sizeof(float *), "gauss array");
262
for (i = 0; i < x; i++) {
263
m_maintabs[i] = make_gausstab(i + 1);
267
void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y, void *data)
269
MemoryBuffer *memorybuffer = (MemoryBuffer *)data;
270
float *buffer = memorybuffer->getBuffer();
271
float *gausstabx, *gausstabcenty;
272
float *gausstaby, *gausstabcentx;
275
register float sum, val;
276
float rval, gval, bval, aval;
277
int imgx = getWidth();
278
int imgy = getHeight();
280
this->m_inputSize->read(tempSize, x, y, data);
281
float refSize = tempSize[0];
282
int refradx = (int)(refSize * m_radxf);
283
int refrady = (int)(refSize * m_radyf);
284
if (refradx > m_radx) refradx = m_radx;
285
else if (refradx < 1) refradx = 1;
286
if (refrady > m_rady) refrady = m_rady;
287
else if (refrady < 1) refrady = 1;
289
if (refradx == 1 && refrady == 1) {
290
memorybuffer->readNoCheck(output, x, y);
293
int minxr = x - refradx < 0 ? -x : -refradx;
294
int maxxr = x + refradx > imgx ? imgx - x : refradx;
295
int minyr = y - refrady < 0 ? -y : -refrady;
296
int maxyr = y + refrady > imgy ? imgy - y : refrady;
298
float *srcd = buffer + COM_NUMBER_OF_CHANNELS * ( (y + minyr) * imgx + x + minxr);
300
gausstabx = m_maintabs[refradx - 1];
301
gausstabcentx = gausstabx + refradx;
302
gausstaby = m_maintabs[refrady - 1];
303
gausstabcenty = gausstaby + refrady;
305
sum = gval = rval = bval = aval = 0.0f;
306
for (i = minyr; i < maxyr; i++, srcd += COM_NUMBER_OF_CHANNELS * imgx) {
308
for (j = minxr; j < maxxr; j++, src += COM_NUMBER_OF_CHANNELS) {
310
val = gausstabcenty[i] * gausstabcentx[j];
312
rval += val * src[0];
313
gval += val * src[1];
314
bval += val * src[2];
315
aval += val * src[3];
319
output[0] = rval * sum;
320
output[1] = gval * sum;
321
output[2] = bval * sum;
322
output[3] = aval * sum;
327
void GaussianBlurReferenceOperation::deinitExecution()
330
x = max(this->m_radx, this->m_rady);
331
for (i = 0; i < x; i++) {
332
MEM_freeN(this->m_maintabs[i]);
334
MEM_freeN(this->m_maintabs);
335
BlurBaseOperation::deinitExecution();
338
bool GaussianBlurReferenceOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
341
NodeOperation *operation = this->getInputOperation(1);
343
if (operation->determineDependingAreaOfInterest(input, readOperation, output)) {
347
int addx = this->m_data->sizex + 2;
348
int addy = this->m_data->sizey + 2;
349
newInput.xmax = input->xmax + addx;
350
newInput.xmin = input->xmin - addx;
351
newInput.ymax = input->ymax + addy;
352
newInput.ymin = input->ymin - addy;
353
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);