* Added new dilate/erode function
authorJeroen Bakker <j.bakker@atmind.nl>
Thu, 31 May 2012 10:38:11 +0000 (10:38 +0000)
committerJeroen Bakker <j.bakker@atmind.nl>
Thu, 31 May 2012 10:38:11 +0000 (10:38 +0000)
source/blender/compositor/nodes/COM_DilateErodeNode.cpp
source/blender/compositor/operations/COM_DilateErodeOperation.cpp
source/blender/compositor/operations/COM_DilateErodeOperation.h
source/blender/editors/space_node/drawnode.c
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c

index cc96f672ebd52231638d4e0bd239b23b8e38f6f9..b722e40a87570471a574cfd028542a1ae4be29bc 100644 (file)
@@ -35,7 +35,7 @@ void DilateErodeNode::convertToOperations(ExecutionSystem *graph, CompositorCont
 {
        
        bNode *editorNode = this->getbNode();
-       if (editorNode->custom1 == CMP_NODE_DILATEERODE_DISTANCE) {
+       if (editorNode->custom1 == CMP_NODE_DILATEERODE_DISTANCE_THRESH) {
                DilateErodeDistanceOperation *operation = new DilateErodeDistanceOperation();
                operation->setDistance(editorNode->custom2);
                operation->setInset(editorNode->custom3);
@@ -52,8 +52,22 @@ void DilateErodeNode::convertToOperations(ExecutionSystem *graph, CompositorCont
                        this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
                }
                graph->addOperation(operation);
-       }
-       else {
+       } else if (editorNode->custom1 == CMP_NODE_DILATEERODE_DISTANCE) {
+               if (editorNode->custom2 > 0) {
+                       DilateDistanceOperation * operation = new DilateDistanceOperation();
+                       operation->setDistance(editorNode->custom2);
+                       this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
+                       this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
+                       graph->addOperation(operation);
+               }
+               else {
+                       ErodeDistanceOperation * operation = new ErodeDistanceOperation();
+                       operation->setDistance(-editorNode->custom2);
+                       this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
+                       this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
+                       graph->addOperation(operation);
+               }
+       } else {
                if (editorNode->custom2 > 0) {
                        DilateStepOperation * operation = new DilateStepOperation();
                        operation->setIterations(editorNode->custom2);
index a73f76030ab7aac599897a8f8365a6ae015417de..7bc49fa695c3876c7c3c6b12bb459326e2620304 100644 (file)
@@ -23,6 +23,7 @@
 #include "COM_DilateErodeOperation.h"
 #include "BLI_math.h"
 
+// DilateErode Distance Threshold
 DilateErodeDistanceOperation::DilateErodeDistanceOperation(): NodeOperation()
 {
        this->addInputSocket(COM_DT_VALUE);
@@ -158,6 +159,115 @@ bool DilateErodeDistanceOperation::determineDependingAreaOfInterest(rcti *input,
        return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
 }
 
+// Dilate Distance
+DilateDistanceOperation::DilateDistanceOperation(): NodeOperation()
+{
+       this->addInputSocket(COM_DT_VALUE);
+       this->addOutputSocket(COM_DT_VALUE);
+       this->setComplex(true);
+       this->inputProgram = NULL;
+       this->distance = 0.0f;
+}
+void DilateDistanceOperation::initExecution()
+{
+       this->inputProgram = this->getInputSocketReader(0);
+       this->scope = distance;
+       if (scope < 3) {
+               scope = 3;
+       }
+}
+
+void *DilateDistanceOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers)
+{
+       void *buffer = inputProgram->initializeTileData(NULL, memoryBuffers);
+       return buffer;
+}
+
+void DilateDistanceOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data)
+{
+       const float distance = this->distance;
+       float mindist = distance * distance;
+
+       MemoryBuffer *inputBuffer = (MemoryBuffer*)data;
+       float *buffer = inputBuffer->getBuffer();
+       rcti *rect = inputBuffer->getRect();
+       const int minx = max(x - scope, rect->xmin);
+       const int miny = max(y - scope, rect->ymin);
+       const int maxx = min(x + scope, rect->xmax);
+       const int maxy = min(y + scope, rect->ymax);
+       const int bufferWidth = rect->xmax-rect->xmin;
+       int offset;
+       
+       float value = 0.0f;
+
+       for (int yi = miny ; yi<maxy;yi++) {
+               offset = ((yi-rect->ymin)*bufferWidth+(minx-rect->xmin))*4;
+               for (int xi = minx ; xi<maxx;xi++) {
+                       const float dx = xi-x;
+                       const float dy = yi-y;
+                       const float dis = dx*dx+dy*dy;
+                       if (dis <= mindist) {
+                               value = max(buffer[offset], value);
+                       }
+                       offset +=4;
+               }
+       }
+       color[0] = value;
+}
+
+void DilateDistanceOperation::deinitExecution()
+{
+       this->inputProgram = NULL;
+}
+
+bool DilateDistanceOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+       rcti newInput;
+
+       newInput.xmax = input->xmax + scope;
+       newInput.xmin = input->xmin - scope;
+       newInput.ymax = input->ymax + scope;
+       newInput.ymin = input->ymin - scope;
+
+       return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
+// Erode Distance
+ErodeDistanceOperation::ErodeDistanceOperation() : DilateDistanceOperation() 
+{
+}
+
+void ErodeDistanceOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data)
+{
+       const float distance = this->distance;
+       float mindist = distance * distance;
+
+       MemoryBuffer *inputBuffer = (MemoryBuffer*)data;
+       float *buffer = inputBuffer->getBuffer();
+       rcti *rect = inputBuffer->getRect();
+       const int minx = max(x - scope, rect->xmin);
+       const int miny = max(y - scope, rect->ymin);
+       const int maxx = min(x + scope, rect->xmax);
+       const int maxy = min(y + scope, rect->ymax);
+       const int bufferWidth = rect->xmax-rect->xmin;
+       int offset;
+       
+       float value = 1.0f;
+
+       for (int yi = miny ; yi<maxy;yi++) {
+               offset = ((yi-rect->ymin)*bufferWidth+(minx-rect->xmin))*4;
+               for (int xi = minx ; xi<maxx;xi++) {
+                       const float dx = xi-x;
+                       const float dy = yi-y;
+                       const float dis = dx*dx+dy*dy;
+                       if (dis <= mindist) {
+                               value = min(buffer[offset], value);
+                       }
+                       offset +=4;
+               }
+       }
+       color[0] = value;
+}
+
 // Dilate step
 DilateStepOperation::DilateStepOperation(): NodeOperation()
 {
index 7f01ea944948beed46c5492617c080cbfc62ca62..71bbab74a4bda013723409d7e6e2de14de19222c 100644 (file)
@@ -68,6 +68,47 @@ public:
 
 };
 
+class DilateDistanceOperation : public NodeOperation {
+private:
+       /**
+         * Cached reference to the inputProgram
+         */
+       SocketReader * inputProgram;
+protected:
+       float distance;
+       int scope;
+public:
+       DilateDistanceOperation();
+       
+       /**
+         * the inner loop of this program
+         */
+       void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data);
+       
+       /**
+         * Initialize the execution
+         */
+       void initExecution();
+       
+       void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers);
+       /**
+         * Deinitialize the execution
+         */
+       void deinitExecution();
+       
+       void setDistance(float distance) {this->distance = distance;}
+       bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
+};
+class ErodeDistanceOperation : public DilateDistanceOperation {
+public:
+       ErodeDistanceOperation();
+       
+       /**
+         * the inner loop of this program
+         */
+       void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data);
+};
+
 class DilateStepOperation : public NodeOperation {
 protected:
        /**
index 97e7cff6f09f3bfec78e07c4508d2e716b496606..676b1276569869917ce20864cc61fd609835bd68 100644 (file)
@@ -1641,7 +1641,7 @@ static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C)
 {
        uiItemR(layout, ptr, "type", 0, NULL, ICON_NONE);
        uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
-       if (RNA_enum_get(ptr, "type") == CMP_NODE_DILATEERODE_DISTANCE) {
+       if (RNA_enum_get(ptr, "type") == CMP_NODE_DILATEERODE_DISTANCE_THRESH) {
                uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE);
        }
 }
index b2781675cbef94717776d1afc1ced904c2db96b4..5b87ecc44aefe9ed2fee4e8292c391d7757cdb25 100644 (file)
@@ -350,8 +350,9 @@ typedef struct bNodeSocketValueRGBA {
 #define CMP_NODE_LENSFLARE_CIRCLE  4
 #define CMP_NODE_LENSFLARE_STREAKS 8
 
-#define CMP_NODE_DILATEERODE_STEP     0
-#define CMP_NODE_DILATEERODE_DISTANCE 1
+#define CMP_NODE_DILATEERODE_STEP            0
+#define CMP_NODE_DILATEERODE_DISTANCE_THRESH 1
+#define CMP_NODE_DILATEERODE_DISTANCE        2
 
 typedef struct NodeFrame {
        short flag;
index 8294a96b83640ac9f75aca32d0dcb08cfcc1fbf9..466a9b80c505ece63e74d1db360e00694e3a608f 100644 (file)
@@ -1994,8 +1994,9 @@ static void def_cmp_dilate_erode(StructRNA *srna)
        PropertyRNA *prop;
 
        static EnumPropertyItem type_items[] = {
-               {CMP_NODE_DILATEERODE_STEP,     "STEP",       0, "Step",     ""},
-               {CMP_NODE_DILATEERODE_DISTANCE, "DISTANCE",   0, "Distance", ""},
+               {CMP_NODE_DILATEERODE_STEP,            "STEP",      0, "Step",      ""},
+           {CMP_NODE_DILATEERODE_DISTANCE_THRESH, "THRESHOLD", 0, "Threshold", ""},
+           {CMP_NODE_DILATEERODE_DISTANCE,        "DISTANCE",  0, "Distance",  ""},
                {0, NULL, 0, NULL, NULL}
        };