diff options
Diffstat (limited to 'source/blender/compositor')
6 files changed, 475 insertions, 0 deletions
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 870e379b343..4dc111cebd2 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -286,6 +286,8 @@ set(SRC nodes/COM_FilterNode.h nodes/COM_DilateErodeNode.cpp nodes/COM_DilateErodeNode.h + nodes/COM_InpaintNode.cpp + nodes/COM_InpaintNode.h nodes/COM_BlurNode.cpp nodes/COM_BlurNode.h nodes/COM_BokehBlurNode.cpp @@ -590,6 +592,8 @@ set(SRC operations/COM_ConvolutionEdgeFilterOperation.cpp operations/COM_DilateErodeOperation.cpp operations/COM_DilateErodeOperation.h + operations/COM_InpaintOperation.cpp + operations/COM_InpaintOperation.h operations/COM_GlareThresholdOperation.cpp operations/COM_GlareThresholdOperation.h operations/COM_GlareBaseOperation.cpp diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 37d38261ea5..24c3c36b79e 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -74,6 +74,7 @@ #include "COM_HueSaturationValueNode.h" #include "COM_IDMaskNode.h" #include "COM_ImageNode.h" +#include "COM_InpaintNode.h" #include "COM_InvertNode.h" #include "COM_KeyingNode.h" #include "COM_KeyingScreenNode.h" @@ -303,6 +304,9 @@ Node *Converter::convert(bNode *b_node, bool fast) case CMP_NODE_DILATEERODE: node = new DilateErodeNode(b_node); break; + case CMP_NODE_INPAINT: + node = new InpaintNode(b_node); + break; case CMP_NODE_LENSDIST: node = new LensDistortionNode(b_node); break; diff --git a/source/blender/compositor/nodes/COM_InpaintNode.cpp b/source/blender/compositor/nodes/COM_InpaintNode.cpp new file mode 100644 index 00000000000..e90a3921edc --- /dev/null +++ b/source/blender/compositor/nodes/COM_InpaintNode.cpp @@ -0,0 +1,48 @@ +/* + * 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: Peter Schlaile + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_InpaintNode.h" +#include "DNA_scene_types.h" +#include "COM_ExecutionSystem.h" +#include "COM_InpaintOperation.h" +#include "BLI_math.h" + +InpaintNode::InpaintNode(bNode *editorNode) : Node(editorNode) +{ + /* pass */ +} + +void InpaintNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) +{ + + bNode *editorNode = this->getbNode(); + + /* if (editorNode->custom1 == CMP_NODE_INPAINT_SIMPLE) { */ + if (true) { + InpaintSimpleOperation *operation = new InpaintSimpleOperation(); + operation->setbNode(editorNode); + operation->setIterations(editorNode->custom2); + this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); + this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); + graph->addOperation(operation); + } +} diff --git a/source/blender/compositor/nodes/COM_InpaintNode.h b/source/blender/compositor/nodes/COM_InpaintNode.h new file mode 100644 index 00000000000..5837b979958 --- /dev/null +++ b/source/blender/compositor/nodes/COM_InpaintNode.h @@ -0,0 +1,38 @@ +/* + * 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: Peter Schlaile + * Jeroen Bakker + * Monique Dewanchand + */ + +#ifndef _COM_InpaintNode_h_ +#define _COM_InpaintNode_h_ + +#include "COM_Node.h" + +/** + * @brief InpaintNode + * @ingroup Node + */ +class InpaintNode : public Node { +public: + InpaintNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp new file mode 100644 index 00000000000..5b21273e4ab --- /dev/null +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -0,0 +1,305 @@ +/* + * 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: Peter Schlaile + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "MEM_guardedalloc.h" + +#include "COM_InpaintOperation.h" +#include "COM_OpenCLDevice.h" + +#include "BLI_math.h" + +#define ASSERT_XY_RANGE(x, y) \ + BLI_assert(x >= 0 && x < this->getWidth() && \ + y >= 0 && y < this->getHeight()) + + +// Inpaint (simple convolve using average of known pixels) +InpaintSimpleOperation::InpaintSimpleOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); + this->m_inputImageProgram = NULL; + this->m_pixelorder = NULL; + this->m_manhatten_distance = NULL; + this->m_cached_buffer = NULL; + this->m_cached_buffer_ready = false; +} +void InpaintSimpleOperation::initExecution() +{ + this->m_inputImageProgram = this->getInputSocketReader(0); + + this->m_cached_buffer = NULL; + this->m_pixelorder = NULL; + this->m_manhatten_distance = NULL; + this->m_cached_buffer = NULL; + this->m_cached_buffer_ready = false; + + this->initMutex(); +} + +void InpaintSimpleOperation::clamp_xy(int & x, int & y) +{ + int width = this->getWidth(); + int height = this->getHeight(); + + if (x < 0) { + x = 0; + } + else if (x >= width) { + x = width - 1; + } + + if (y < 0) { + y = 0; + } + else if (y >= height) { + y = height - 1; + } +} + +float InpaintSimpleOperation::get(int x, int y, int component) +{ + int width = this->getWidth(); + + ASSERT_XY_RANGE(x, y); + + return this->m_cached_buffer[ + y * width * COM_NUMBER_OF_CHANNELS + + x * COM_NUMBER_OF_CHANNELS + component]; +} + +void InpaintSimpleOperation::set(int x, int y, int component, float v) +{ + int width = this->getWidth(); + + ASSERT_XY_RANGE(x, y); + + this->m_cached_buffer[ + y * width * COM_NUMBER_OF_CHANNELS + + x * COM_NUMBER_OF_CHANNELS + component] = v; +} + +int InpaintSimpleOperation::mdist(int x, int y) +{ + int width = this->getWidth(); + + ASSERT_XY_RANGE(x, y); + + return this->m_manhatten_distance[y * width + x]; +} + +bool InpaintSimpleOperation::next_pixel(int & x, int & y, int & curr, int iters) +{ + int width = this->getWidth(); + + if (curr >= this->m_area_size) { + return false; + } + + int r = this->m_pixelorder[curr++]; + + x = r % width; + y = r / width; + + if (mdist(x, y) > iters) { + return false; + } + + return true; +} + +void InpaintSimpleOperation::calc_manhatten_distance() +{ + int width = this->getWidth(); + int height = this->getHeight(); + short *m = this->m_manhatten_distance = new short[width * height]; + int *offsets; + + offsets = (int *)MEM_callocN(sizeof(int) * (width + height + 1), "InpaintSimpleOperation offsets"); + + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + int r = 0; + /* no need to clamp here */ + if (get(i, j, 3) < 1.0f) { + r = width + height; + if (i > 0) + r = mini(r, m[j * width + i - 1] + 1); + if (j > 0) + r = mini(r, m[(j - 1) * width + i] + 1); + } + m[j * width + i] = r; + } + } + + for (int j = height - 1; j >= 0; j--) { + for (int i = width; i >= 0; i--) { + int r = m[j * width + i]; + + if (i + 1 < width) + r = mini(r, m[j * width + i + 1] + 1); + if (j + 1 < height) + r = mini(r, m[(j + 1) * width + i] + 1); + + m[j * width + i] = r; + + offsets[r]++; + } + } + + offsets[0] = 0; + + for (int i = 1; i < width + height + 1; i++) { + offsets[i] += offsets[i - 1]; + } + + this->m_area_size = offsets[width + height]; + this->m_pixelorder = new int[this->m_area_size]; + + for (int i = 0; i < width * height; i++) { + if (m[i] > 0) { + this->m_pixelorder[offsets[m[i] - 1]++] = i; + } + } + + MEM_freeN(offsets); +} + +void InpaintSimpleOperation::pix_step(int x, int y) +{ + int d = this->mdist(x, y); + + float n = 0; + + float pix[3] = {0.0f, 0.0f, 0.0f}; + + for (int dx = -1; dx <= 1; dx++) { + for (int dy = -1; dy <= 1; dy++) { + if (dx != 0 && dy != 0) { + + int x_ofs = x + dx; + int y_ofs = y + dy; + clamp_xy(x_ofs, y_ofs); + + if (this->mdist(x_ofs, y_ofs) < d) { + + float weight; + + if (dx == 0 || dy == 0) { + weight = 1.0f; + } + else { + weight = M_SQRT1_2; /* 1.0f / sqrt(2) */ + } + + for (int c = 0; c < 3; c++) { + float fk = this->get(x_ofs, y_ofs, c); + + pix[c] += fk * weight; + } + n += weight; + } + } + } + } + + for (int c = 0; c < 3; c++) { + this->set(x, y, c, pix[c] / n); + } +} + +void *InpaintSimpleOperation::initializeTileData(rcti *rect) +{ + if (this->m_cached_buffer_ready) { + return this->m_cached_buffer; + } + lockMutex(); + if (!this->m_cached_buffer_ready) { + MemoryBuffer *buf = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect); + + this->m_cached_buffer = new float[this->getWidth() * this->getHeight() * COM_NUMBER_OF_CHANNELS]; + memcpy(this->m_cached_buffer, buf->getBuffer(), this->getWidth() * this->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float)); + + calc_manhatten_distance(); + + int curr = 0; + int x, y; + + + while (next_pixel(x, y, curr, this->m_iterations)) { + pix_step(x, y); + } + this->m_cached_buffer_ready = true; + } + + unlockMutex(); + return this->m_cached_buffer; +} + +void InpaintSimpleOperation::executePixel(float *color, int x, int y, void *data) +{ + clamp_xy(x, y); + for (int c = 0; c < 3; c++) { + color[c] = get(x, y, c); + } + color[3] = 1.0f; +} + +void InpaintSimpleOperation::deinitExecution() +{ + this->m_inputImageProgram = NULL; + this->deinitMutex(); + if (this->m_cached_buffer) { + delete [] this->m_cached_buffer; + this->m_cached_buffer = NULL; + } + + if (this->m_pixelorder) { + delete [] this->m_pixelorder; + this->m_pixelorder = NULL; + } + + if (this->m_manhatten_distance) { + delete [] this->m_manhatten_distance; + this->m_manhatten_distance = NULL; + } + this->m_cached_buffer_ready = false; +} + +bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + if (this->m_cached_buffer_ready) { + return false; + } + else { + rcti newInput; + + newInput.xmax = getWidth(); + newInput.xmin = 0; + newInput.ymax = getHeight(); + newInput.ymin = 0; + + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } +} + diff --git a/source/blender/compositor/operations/COM_InpaintOperation.h b/source/blender/compositor/operations/COM_InpaintOperation.h new file mode 100644 index 00000000000..0ff65174161 --- /dev/null +++ b/source/blender/compositor/operations/COM_InpaintOperation.h @@ -0,0 +1,76 @@ +/* + * 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: Peter Schlaile + * Jeroen Bakker + * Monique Dewanchand + */ + +#ifndef _COM_InpaintOperation_h +#define _COM_InpaintOperation_h +#include "COM_NodeOperation.h" + +class InpaintSimpleOperation : public NodeOperation { +protected: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputImageProgram; + + int m_iterations; + + float *m_cached_buffer; + bool m_cached_buffer_ready; + + int *m_pixelorder; + int m_area_size; + short *m_manhatten_distance; +public: + InpaintSimpleOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float *color, int x, int y, void *data); + + /** + * Initialize the execution + */ + void initExecution(); + + void *initializeTileData(rcti *rect); + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setIterations(int iterations) { this->m_iterations = iterations; } + + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + +private: + void calc_manhatten_distance(); + void clamp_xy(int & x, int & y); + float get(int x, int y, int component); + void set(int x, int y, int component, float v); + int mdist(int x, int y); + bool next_pixel(int & x, int & y, int & curr, int iters); + void pix_step(int x, int y); +}; + + +#endif |