Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2012-06-16 17:46:20 +0400
committerCampbell Barton <ideasman42@gmail.com>2012-06-16 17:46:20 +0400
commit265262a5d5e56005d4636dc28f9fce25f4bbed57 (patch)
treefd055de04c8cbcba9fd5bb5a4f200d191547adcb /source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp
parent2f29f8d18656e9c8796b68671a60812d0cffcb70 (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/COM_GaussianAlphaYBlurOperation.cpp')
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp183
1 files changed, 183 insertions, 0 deletions
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);
+ }
+}