[Bf-blender-cvs] [06c8ebdc7cf] compositor-full-frame: Compositor: Full frame Dilate/Erode node

Manuel Castilla noreply at git.blender.org
Thu Aug 12 01:06:40 CEST 2021


Commit: 06c8ebdc7cff1fd9e15f5075187c563615138d3d
Author: Manuel Castilla
Date:   Thu Aug 12 01:04:53 2021 +0200
Branches: compositor-full-frame
https://developer.blender.org/rB06c8ebdc7cff1fd9e15f5075187c563615138d3d

Compositor: Full frame Dilate/Erode node

===================================================================

M	source/blender/compositor/operations/COM_DilateErodeOperation.cc
M	source/blender/compositor/operations/COM_DilateErodeOperation.h

===================================================================

diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cc b/source/blender/compositor/operations/COM_DilateErodeOperation.cc
index c67a35b686c..83de8ea45e9 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.cc
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cc
@@ -35,9 +35,9 @@ DilateErodeThresholdOperation::DilateErodeThresholdOperation()
   this->m__switch = 0.5f;
   this->m_distance = 0.0f;
 }
-void DilateErodeThresholdOperation::initExecution()
+
+void DilateErodeThresholdOperation::init_data()
 {
-  this->m_inputProgram = this->getInputSocketReader(0);
   if (this->m_distance < 0.0f) {
     this->m_scope = -this->m_distance + this->m_inset;
   }
@@ -54,6 +54,11 @@ void DilateErodeThresholdOperation::initExecution()
   }
 }
 
+void DilateErodeThresholdOperation::initExecution()
+{
+  this->m_inputProgram = this->getInputSocketReader(0);
+}
+
 void *DilateErodeThresholdOperation::initializeTileData(rcti * /*rect*/)
 {
   void *buffer = this->m_inputProgram->initializeTileData(nullptr);
@@ -160,6 +165,94 @@ bool DilateErodeThresholdOperation::determineDependingAreaOfInterest(
   return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
 }
 
+void DilateErodeThresholdOperation::get_area_of_interest(const int input_idx,
+                                                         const rcti &output_area,
+                                                         rcti &r_input_area)
+{
+  BLI_assert(input_idx == 0);
+  UNUSED_VARS_NDEBUG(input_idx);
+  r_input_area.xmin = output_area.xmin - m_scope;
+  r_input_area.xmax = output_area.xmax + m_scope;
+  r_input_area.ymin = output_area.ymin - m_scope;
+  r_input_area.ymax = output_area.ymax + m_scope;
+}
+
+template<template<typename> typename TCompare>
+static float get_min_distance(DilateErodeThresholdOperation::PixelData &p)
+{
+  const TCompare compare;
+  float min_dist = p.distance;
+  const float *row = p.elem + ((intptr_t)p.ymin - p.y) * p.row_stride +
+                     ((intptr_t)p.xmin - p.x) * p.elem_stride;
+  for (int yi = p.ymin; yi < p.ymax; yi++) {
+    const float dy = yi - p.y;
+    const float dist_y = dy * dy;
+    const float *elem = row;
+    for (int xi = p.xmin; xi < p.xmax; xi++) {
+      if (compare(*elem, p.sw)) {
+        const float dx = xi - p.x;
+        const float dist = dx * dx + dist_y;
+        min_dist = MIN2(min_dist, dist);
+      }
+      elem += p.elem_stride;
+    }
+    row += p.row_stride;
+  }
+  return min_dist;
+}
+
+void DilateErodeThresholdOperation::update_memory_buffer_partial(MemoryBuffer *output,
+                                                                 const rcti &area,
+                                                                 Span<MemoryBuffer *> inputs)
+{
+  const MemoryBuffer *input = inputs[0];
+  const rcti &input_rect = input->get_rect();
+  const float rd = m_scope * m_scope;
+  const float inset = m_inset;
+
+  PixelData p;
+  p.sw = m__switch;
+  p.distance = rd * 2;
+  p.elem_stride = input->elem_stride;
+  p.row_stride = input->row_stride;
+  for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+    p.x = it.x;
+    p.y = it.y;
+    p.xmin = MAX2(p.x - m_scope, input_rect.xmin);
+    p.ymin = MAX2(p.y - m_scope, input_rect.ymin);
+    p.xmax = MIN2(p.x + m_scope, input_rect.xmax);
+    p.ymax = MIN2(p.y + m_scope, input_rect.ymax);
+    p.elem = it.in(0);
+
+    float pixel_value;
+    if (*p.elem > p.sw) {
+      pixel_value = -sqrtf(get_min_distance<std::less>(p));
+    }
+    else {
+      pixel_value = sqrtf(get_min_distance<std::greater>(p));
+    }
+
+    if (m_distance > 0.0f) {
+      const float delta = m_distance - pixel_value;
+      if (delta >= 0.0f) {
+        *it.out = delta >= inset ? 1.0f : delta / inset;
+      }
+      else {
+        *it.out = 0.0f;
+      }
+    }
+    else {
+      const float delta = -m_distance + pixel_value;
+      if (delta < 0.0f) {
+        *it.out = delta < -inset ? 1.0f : (-delta) / inset;
+      }
+      else {
+        *it.out = 0.0f;
+      }
+    }
+  }
+}
+
 // Dilate Distance
 DilateDistanceOperation::DilateDistanceOperation()
 {
@@ -170,15 +263,31 @@ DilateDistanceOperation::DilateDistanceOperation()
   flags.complex = true;
   flags.open_cl = true;
 }
-void DilateDistanceOperation::initExecution()
+
+DilateDistanceOperation::PixelData::PixelData(MemoryBuffer *input,
+                                              const int distance,
+                                              const int scope)
+    : min_distance(distance * distance),
+      scope(scope),
+      elem_stride(input->elem_stride),
+      row_stride(input->row_stride),
+      input_rect(input->get_rect())
+{
+}
+
+void DilateDistanceOperation::init_data()
 {
-  this->m_inputProgram = this->getInputSocketReader(0);
   this->m_scope = this->m_distance;
   if (this->m_scope < 3) {
     this->m_scope = 3;
   }
 }
 
+void DilateDistanceOperation::initExecution()
+{
+  this->m_inputProgram = this->getInputSocketReader(0);
+}
+
 void *DilateDistanceOperation::initializeTileData(rcti * /*rect*/)
 {
   void *buffer = this->m_inputProgram->initializeTileData(nullptr);
@@ -258,6 +367,55 @@ void DilateDistanceOperation::executeOpenCL(OpenCLDevice *device,
   device->COM_clEnqueueRange(dilateKernel, outputMemoryBuffer, 7, this);
 }
 
+void DilateDistanceOperation::get_area_of_interest(const int input_idx,
+                                                   const rcti &output_area,
+                                                   rcti &r_input_area)
+{
+  BLI_assert(input_idx == 0);
+  UNUSED_VARS_NDEBUG(input_idx);
+  r_input_area.xmin = output_area.xmin - m_scope;
+  r_input_area.xmax = output_area.xmax + m_scope;
+  r_input_area.ymin = output_area.ymin - m_scope;
+  r_input_area.ymax = output_area.ymax + m_scope;
+}
+
+template<template<typename> typename TCompare>
+static float get_distance_value(DilateDistanceOperation::PixelData &p, const float start_value)
+{
+  const TCompare compare;
+  const float min_dist = p.min_distance;
+  float value = start_value;
+  const float *row = p.elem + ((intptr_t)p.ymin - p.y) * p.row_stride +
+                     ((intptr_t)p.xmin - p.x) * p.elem_stride;
+  for (int yi = p.ymin; yi < p.ymax; yi++) {
+    const float dy = yi - p.y;
+    const float dist_y = dy * dy;
+    const float *elem = row;
+    for (int xi = p.xmin; xi < p.xmax; xi++) {
+      const float dx = xi - p.x;
+      const float dist = dx * dx + dy * dy;
+      if (dist <= min_dist) {
+        value = compare(*elem, value) ? *elem : value;
+      }
+      elem += p.elem_stride;
+    }
+    row += p.row_stride;
+  }
+
+  return value;
+}
+
+void DilateDistanceOperation::update_memory_buffer_partial(MemoryBuffer *output,
+                                                           const rcti &area,
+                                                           Span<MemoryBuffer *> inputs)
+{
+  PixelData p(inputs[0], m_distance, m_scope);
+  for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+    p.update(it);
+    *it.out = get_distance_value<std::greater>(p, 0.0f);
+  }
+}
+
 /* Erode Distance */
 ErodeDistanceOperation::ErodeDistanceOperation() : DilateDistanceOperation()
 {
@@ -318,6 +476,17 @@ void ErodeDistanceOperation::executeOpenCL(OpenCLDevice *device,
   device->COM_clEnqueueRange(erodeKernel, outputMemoryBuffer, 7, this);
 }
 
+void ErodeDistanceOperation::update_memory_buffer_partial(MemoryBuffer *output,
+                                                          const rcti &area,
+                                                          Span<MemoryBuffer *> inputs)
+{
+  PixelData p(inputs[0], m_distance, m_scope);
+  for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+    p.update(it);
+    *it.out = get_distance_value<std::less>(p, 1.0f);
+  }
+}
+
 /* Dilate step */
 DilateStepOperation::DilateStepOperation()
 {
@@ -475,6 +644,125 @@ bool DilateStepOperation::determineDependingAreaOfInterest(rcti *input,
   return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
 }
 
+void DilateStepOperation::get_area_of_interest(const int input_idx,
+                                               const rcti &output_area,
+                                               rcti &r_input_area)
+{
+  BLI_assert(input_idx == 0);
+  UNUSED_VARS_NDEBUG(input_idx);
+  r_input_area.xmin = output_area.xmin - m_iterations;
+  r_input_area.xmax = output_area.xmax + m_iterations;
+  r_input_area.ymin = output_area.ymin - m_iterations;
+  r_input_area.ymax = output_area.ymax + m_iterations;
+}
+
+template<typename TCompareSelector>
+static void step_update_memory_buffer(MemoryBuffer *output,
+                                      const MemoryBuffer *input,
+                                      const rcti &area,
+                                      const int num_iterations,
+                                      const float compare_min_value)
+{
+  TCompareSelector selector;
+
+  const int width = output->getWidth();
+  const int height = output->getHeight();
+
+  const int half_window = num_iterations;
+  const int window = half_window * 2 + 1;
+
+  const int xmin = MAX2(0, area.xmin - half_window);
+  const int ymin = MAX2(0, area.ymin - half_window);
+  const int xmax = MIN2(width, area.xmax + half_window);
+  const int ymax = MIN2(height, area.ymax + half_window);
+
+  const int bwidth = area.xmax - area.xmin;
+  const int bheight = area.ymax - area.ymin;
+
+  /* NOTE: #result has area width, but new height.
+   * We have to calculate the additional rows in the first pass,
+   * to have valid data available for the second pass. */
+  rcti result_area;
+  BLI_rcti_init(&result_area, area.xmin, area.xmax, ymin, ymax);
+  MemoryBuffer result(DataType::Value, result_area);
+
+  /* #temp holds maxima for every step in the algorithm, #buf holds a
+   * single row or column of input values, padded with #limit values to
+   * simplify the logic. */
+  float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp");
+  float *buf = (float *)MEM_mallocN(siz

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list