diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-06-16 17:46:20 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-06-16 17:46:20 +0400 |
commit | 265262a5d5e56005d4636dc28f9fce25f4bbed57 (patch) | |
tree | fd055de04c8cbcba9fd5bb5a4f200d191547adcb /source/blender/compositor/operations | |
parent | 2f29f8d18656e9c8796b68671a60812d0cffcb70 (diff) |
feather option for dilate/erode node - needed for alpha masks so we can (blur in/out), currently only positive values supported.
Diffstat (limited to 'source/blender/compositor/operations')
10 files changed, 508 insertions, 8 deletions
diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index bb915fec590..0e7676dfcef 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -27,11 +27,11 @@ extern "C" { #include "RE_pipeline.h" } -BlurBaseOperation::BlurBaseOperation() : NodeOperation() +BlurBaseOperation::BlurBaseOperation(DataType data_type=COM_DT_COLOR) : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(data_type); this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); + this->addOutputSocket(data_type); this->setComplex(true); this->inputProgram = NULL; this->data = NULL; @@ -89,6 +89,24 @@ float *BlurBaseOperation::make_gausstab(int rad) return gausstab; } +/* normalized distance from the current (inverted so 1.0 is close and 0.0 is far) */ +float *BlurBaseOperation::make_dist_fac_inverse(int rad) +{ + float *dist_fac_invert, val; + int i, n; + + n = 2 * rad + 1; + + dist_fac_invert = new float[n]; + + for (i = -rad; i <= rad; i++) { + val = 1.0f - fabsf(((float)i / (float)rad)); + dist_fac_invert[i + rad] = val; + } + + return dist_fac_invert; +} + void BlurBaseOperation::deinitExecution() { this->inputProgram = NULL; diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.h b/source/blender/compositor/operations/COM_BlurBaseOperation.h index 84fc243a5af..33c07abbb36 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.h +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.h @@ -35,8 +35,9 @@ protected: SocketReader *inputProgram; SocketReader *inputSize; NodeBlurData *data; - BlurBaseOperation(); + BlurBaseOperation(DataType data_type); float *make_gausstab(int rad); + float *make_dist_fac_inverse(int rad); float size; bool deleteData; bool sizeavailable; diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp index 48cfbeb36f8..7491b0f30dd 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp @@ -26,7 +26,7 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" -FastGaussianBlurOperation::FastGaussianBlurOperation() : BlurBaseOperation() +FastGaussianBlurOperation::FastGaussianBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { this->iirgaus = NULL; } diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp new file mode 100644 index 00000000000..5b042ae9d40 --- /dev/null +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp @@ -0,0 +1,186 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Campbell Barton + */ + +#include "COM_GaussianAlphaXBlurOperation.h" +#include "BLI_math.h" + +extern "C" { + #include "RE_pipeline.h" +} + +GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(COM_DT_VALUE) +{ + this->gausstab = NULL; + this->rad = 0; +} + +void *GaussianAlphaXBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) +{ + if (!this->sizeavailable) { + updateGauss(memoryBuffers); + } + void *buffer = getInputOperation(0)->initializeTileData(NULL, memoryBuffers); + return buffer; +} + +void GaussianAlphaXBlurOperation::initExecution() +{ + BlurBaseOperation::initExecution(); + + if (this->sizeavailable) { + float rad = size * this->data->sizex; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->gausstab = BlurBaseOperation::make_gausstab(rad); + this->distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad); + } +} + +void GaussianAlphaXBlurOperation::updateGauss(MemoryBuffer **memoryBuffers) +{ + if (this->gausstab == NULL) { + updateSize(memoryBuffers); + float rad = size * this->data->sizex; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->gausstab = BlurBaseOperation::make_gausstab(rad); + } + + if (this->distbuf_inv == NULL) { + updateSize(memoryBuffers); + float rad = size * this->data->sizex; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad); + } +} + +void GaussianAlphaXBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) +{ + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + int bufferwidth = inputBuffer->getWidth(); + int bufferstartx = inputBuffer->getRect()->xmin; + int bufferstarty = inputBuffer->getRect()->ymin; + + int miny = y; + int maxy = y; + int minx = x - this->rad; + int maxx = x + this->rad; + miny = max(miny, inputBuffer->getRect()->ymin); + minx = max(minx, inputBuffer->getRect()->xmin); + maxy = min(maxy, inputBuffer->getRect()->ymax); + maxx = min(maxx, inputBuffer->getRect()->xmax); + + /* *** this is the main part which is different to 'GaussianXBlurOperation' *** */ + int step = getStep(); + int offsetadd = getOffsetAdd(); + int bufferindex = ((minx - bufferstartx) * 4) + ((miny - bufferstarty) * 4 * bufferwidth); + + /* gauss */ + float tempColor = 0.0f; + float overallmultiplyer = 0.0f; + + /* dilate */ + float value_max = buffer[(x * 4) + (y * 4 * bufferwidth)]; /* init with the current color to avoid unneeded lookups */ + float distfacinv_max = 1.0f; /* 0 to 1 */ + + for (int nx = minx; nx < maxx; nx += step) { + const int index = (nx - x) + this->rad; + float value = buffer[bufferindex]; + float multiplyer; + + /* gauss */ + { + multiplyer = gausstab[index]; + tempColor += value * multiplyer; + overallmultiplyer += multiplyer; + } + + /* dilate - find most extreme color */ + if (value > value_max) { +#if 0 + multiplyer = 1.0f - ((fabsf(x - nx)) / (float)this->rad); +#else + multiplyer = distbuf_inv[index]; +#endif + value *= multiplyer; + if ((value > value_max) == TRUE) { + value_max = value; + distfacinv_max = multiplyer; + } + } + + bufferindex += offsetadd; + } + + /* blend between the max value and gauss blue - gives nice feather */ + const float value_gauss = tempColor / overallmultiplyer; + const float value_final = (value_max * distfacinv_max) + (value_gauss * (1.0f - distfacinv_max)); + color[0] = value_final; +} + +void GaussianAlphaXBlurOperation::deinitExecution() +{ + BlurBaseOperation::deinitExecution(); + delete [] this->gausstab; + this->gausstab = NULL; + delete [] this->distbuf_inv; + this->distbuf_inv = NULL; +} + +bool GaussianAlphaXBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + rcti newInput; + rcti sizeInput; + sizeInput.xmin = 0; + sizeInput.ymin = 0; + sizeInput.xmax = 5; + sizeInput.ymax = 5; + + NodeOperation *operation = this->getInputOperation(1); + if (operation->determineDependingAreaOfInterest(&sizeInput, readOperation, output)) { + return true; + } + else { + if (this->sizeavailable && this->gausstab != NULL) { + newInput.xmax = input->xmax + rad; + newInput.xmin = input->xmin - rad; + newInput.ymax = input->ymax; + newInput.ymin = input->ymin; + } + else { + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + } + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } +} diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h new file mode 100644 index 00000000000..2b5e4d33673 --- /dev/null +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h @@ -0,0 +1,56 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Campbell Barton + */ + +#ifndef _COM_GaussianAlphaXBlurOperation_h +#define _COM_GaussianAlphaXBlurOperation_h +#include "COM_NodeOperation.h" +#include "COM_BlurBaseOperation.h" + +class GaussianAlphaXBlurOperation : public BlurBaseOperation { +private: + float *gausstab; + float *distbuf_inv; + int rad; + void updateGauss(MemoryBuffer **memoryBuffers); +public: + GaussianAlphaXBlurOperation(); + + /** + * @brief the inner loop of this program + */ + void executePixel(float *color, int x, int y, MemoryBuffer * inputBuffers[], void *data); + + /** + * @brief initialize the execution + */ + void initExecution(); + + /** + * @brief Deinitialize the execution + */ + void deinitExecution(); + + void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); +}; +#endif diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp new file mode 100644 index 00000000000..73dabda1e3f --- /dev/null +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp @@ -0,0 +1,183 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Campbell Barton + */ + +#include "COM_GaussianAlphaYBlurOperation.h" +#include "BLI_math.h" + +extern "C" { + #include "RE_pipeline.h" +} + +GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(COM_DT_VALUE) +{ + this->gausstab = NULL; + this->rad = 0; +} + +void *GaussianAlphaYBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) +{ + if (!this->sizeavailable) { + updateGauss(memoryBuffers); + } + void *buffer = getInputOperation(0)->initializeTileData(NULL, memoryBuffers); + return buffer; +} + +void GaussianAlphaYBlurOperation::initExecution() +{ + if (this->sizeavailable) { + float rad = size * this->data->sizey; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->gausstab = BlurBaseOperation::make_gausstab(rad); + this->distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad); + } +} + +void GaussianAlphaYBlurOperation::updateGauss(MemoryBuffer **memoryBuffers) +{ + if (this->gausstab == NULL) { + updateSize(memoryBuffers); + float rad = size * this->data->sizey; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->gausstab = BlurBaseOperation::make_gausstab(rad); + } + + if (this->distbuf_inv == NULL) { + updateSize(memoryBuffers); + float rad = size * this->data->sizex; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad); + } +} + +void GaussianAlphaYBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) +{ + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + int bufferwidth = inputBuffer->getWidth(); + int bufferstartx = inputBuffer->getRect()->xmin; + int bufferstarty = inputBuffer->getRect()->ymin; + + int miny = y - this->rad; + int maxy = y + this->rad; + int minx = x; + int maxx = x; + miny = max(miny, inputBuffer->getRect()->ymin); + minx = max(minx, inputBuffer->getRect()->xmin); + maxy = min(maxy, inputBuffer->getRect()->ymax); + maxx = min(maxx, inputBuffer->getRect()->xmax); + + /* *** this is the main part which is different to 'GaussianYBlurOperation' *** */ + int step = getStep(); + + /* gauss */ + float tempColor = 0.0f; + float overallmultiplyer = 0.0f; + + /* dilate */ + float value_max = buffer[(x * 4) + (y * 4 * bufferwidth)]; /* init with the current color to avoid unneeded lookups */ + float distfacinv_max = 1.0f; /* 0 to 1 */ + + for (int ny = miny; ny < maxy; ny += step) { + int bufferindex = ((minx - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth); + + const int index = (ny - y) + this->rad; + float value = buffer[bufferindex]; + float multiplyer; + + /* gauss */ + { + multiplyer = gausstab[index]; + tempColor += value * multiplyer; + overallmultiplyer += multiplyer; + } + + /* dilate - find most extreme color */ + if (value > value_max) { +#if 0 + multiplyer = 1.0f - ((fabsf(y - ny)) / (float)this->rad); +#else + multiplyer = distbuf_inv[index]; +#endif + value *= multiplyer; + if (value > value_max) { + value_max = value; + distfacinv_max = multiplyer; + } + } + + } + + /* blend between the max value and gauss blue - gives nice feather */ + const float value_gauss = tempColor / overallmultiplyer; + const float value_final = (value_max * distfacinv_max) + (value_gauss * (1.0f - distfacinv_max)); + color[0] = value_final; +} + +void GaussianAlphaYBlurOperation::deinitExecution() +{ + BlurBaseOperation::deinitExecution(); + delete [] this->gausstab; + this->gausstab = NULL; + delete [] this->distbuf_inv; + this->distbuf_inv = NULL; +} + +bool GaussianAlphaYBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + rcti newInput; + rcti sizeInput; + sizeInput.xmin = 0; + sizeInput.ymin = 0; + sizeInput.xmax = 5; + sizeInput.ymax = 5; + + NodeOperation *operation = this->getInputOperation(1); + if (operation->determineDependingAreaOfInterest(&sizeInput, readOperation, output)) { + return true; + } + else { + if (this->sizeavailable && this->gausstab != NULL) { + newInput.xmax = input->xmax; + newInput.xmin = input->xmin; + newInput.ymax = input->ymax + rad; + newInput.ymin = input->ymin - rad; + } + else { + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + } + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } +} diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h new file mode 100644 index 00000000000..830f9b35c30 --- /dev/null +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h @@ -0,0 +1,56 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Campbell Barton + */ + +#ifndef _COM_GaussianAlphaYBlurOperation_h +#define _COM_GaussianAlphaYBlurOperation_h +#include "COM_NodeOperation.h" +#include "COM_BlurBaseOperation.h" + +class GaussianAlphaYBlurOperation : public BlurBaseOperation { +private: + float *gausstab; + float *distbuf_inv; + int rad; + void updateGauss(MemoryBuffer **memoryBuffers); +public: + GaussianAlphaYBlurOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float *color, int x, int y, MemoryBuffer * inputBuffers[], void *data); + + /** + * @brief initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); +}; +#endif diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index b38ed28cd6a..208d482729d 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -27,7 +27,7 @@ extern "C" { #include "RE_pipeline.h" } -GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation() +GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { this->gausstab = NULL; } diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index 09a2a70ead3..8f6895784d1 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -27,7 +27,7 @@ extern "C" { #include "RE_pipeline.h" } -GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation() +GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { this->gausstab = NULL; this->rad = 0; diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp index ace817194f3..d2cf5d16d58 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp @@ -27,7 +27,7 @@ extern "C" { #include "RE_pipeline.h" } -GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation() +GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { this->gausstab = NULL; this->rad = 0; |