[Bf-blender-cvs] [5fd792c1f6d] blender-v3.1-release: GPencil: Fill Dilate using negative values contract the fill area

Antonio Vazquez noreply at git.blender.org
Fri Feb 25 11:20:46 CET 2022


Commit: 5fd792c1f6d348411469d5b9744c55106d317375
Author: Antonio Vazquez
Date:   Mon Feb 14 16:30:09 2022 +0100
Branches: blender-v3.1-release
https://developer.blender.org/rB5fd792c1f6d348411469d5b9744c55106d317375

GPencil: Fill Dilate using negative values contract the fill area

This is requested by artist for some animation styles where is necessary to fill the area, but create a gap between fill and stroke.

Also some code cleanup and fix a bug in dilate for top area.

Reviewed By: pepeland, mendio

Differential Revision: https://developer.blender.org/D14082

Note: This was committed only in master (3.2) by error.

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

M	source/blender/editors/gpencil/gpencil_fill.c
M	source/blender/makesrna/intern/rna_brush.c

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

diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 541b6673cb6..9b4f4470356 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -1020,7 +1020,6 @@ static void gpencil_invert_image(tGPDfill *tgpf)
   ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
 
   const int maxpixel = (ibuf->x * ibuf->y) - 1;
-  const int center = ibuf->x / 2;
 
   for (int v = maxpixel; v != 0; v--) {
     float color[4];
@@ -1032,15 +1031,6 @@ static void gpencil_invert_image(tGPDfill *tgpf)
     /* Red->Green */
     else if (color[0] == 1.0f) {
       set_pixel(ibuf, v, fill_col[1]);
-      /* Add thickness of 2 pixels to avoid too thin lines, but avoid extremes of the pixel line.
-       */
-      int row = v / ibuf->x;
-      int lowpix = row * ibuf->x;
-      int highpix = lowpix + ibuf->x - 1;
-      if ((v > lowpix) && (v < highpix)) {
-        int offset = (v % ibuf->x < center) ? 1 : -1;
-        set_pixel(ibuf, v + offset, fill_col[1]);
-      }
     }
     else {
       /* Set to Transparent. */
@@ -1136,11 +1126,14 @@ static void gpencil_erase_processed_area(tGPDfill *tgpf)
  */
 static bool dilate_shape(ImBuf *ibuf)
 {
+#define IS_RED (color[0] == 1.0f)
+#define IS_GREEN (color[1] == 1.0f)
+
   bool done = false;
 
   BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
   const float green[4] = {0.0f, 1.0f, 0.0f, 1.0f};
-  // const int maxpixel = (ibuf->x * ibuf->y) - 1;
+  const int max_size = (ibuf->x * ibuf->y) - 1;
   /* detect pixels and expand into red areas */
   for (int row = 0; row < ibuf->y; row++) {
     if (!is_row_filled(ibuf, row)) {
@@ -1153,7 +1146,7 @@ static bool dilate_shape(ImBuf *ibuf)
       float color[4];
       int index;
       get_pixel(ibuf, v, color);
-      if (color[1] == 1.0f) {
+      if (IS_GREEN) {
         int tp = 0;
         int bm = 0;
         int lt = 0;
@@ -1163,7 +1156,7 @@ static bool dilate_shape(ImBuf *ibuf)
         if (v - 1 >= 0) {
           index = v - 1;
           get_pixel(ibuf, index, color);
-          if (color[0] == 1.0f) {
+          if (IS_RED) {
             BLI_stack_push(stack, &index);
             lt = index;
           }
@@ -1172,25 +1165,25 @@ static bool dilate_shape(ImBuf *ibuf)
         if (v + 1 <= maxpixel) {
           index = v + 1;
           get_pixel(ibuf, index, color);
-          if (color[0] == 1.0f) {
+          if (IS_RED) {
             BLI_stack_push(stack, &index);
             rt = index;
           }
         }
         /* pixel top */
-        if (v + (ibuf->x * 1) <= maxpixel) {
-          index = v + (ibuf->x * 1);
+        if (v + ibuf->x <= max_size) {
+          index = v + ibuf->x;
           get_pixel(ibuf, index, color);
-          if (color[0] == 1.0f) {
+          if (IS_RED) {
             BLI_stack_push(stack, &index);
             tp = index;
           }
         }
         /* pixel bottom */
-        if (v - (ibuf->x * 1) >= 0) {
-          index = v - (ibuf->x * 1);
+        if (v - ibuf->x >= 0) {
+          index = v - ibuf->x;
           get_pixel(ibuf, index, color);
-          if (color[0] == 1.0f) {
+          if (IS_RED) {
             BLI_stack_push(stack, &index);
             bm = index;
           }
@@ -1199,7 +1192,7 @@ static bool dilate_shape(ImBuf *ibuf)
         if (tp && lt) {
           index = tp - 1;
           get_pixel(ibuf, index, color);
-          if (color[0] == 1.0f) {
+          if (IS_RED) {
             BLI_stack_push(stack, &index);
           }
         }
@@ -1207,7 +1200,7 @@ static bool dilate_shape(ImBuf *ibuf)
         if (tp && rt) {
           index = tp + 1;
           get_pixel(ibuf, index, color);
-          if (color[0] == 1.0f) {
+          if (IS_RED) {
             BLI_stack_push(stack, &index);
           }
         }
@@ -1215,7 +1208,7 @@ static bool dilate_shape(ImBuf *ibuf)
         if (bm && lt) {
           index = bm - 1;
           get_pixel(ibuf, index, color);
-          if (color[0] == 1.0f) {
+          if (IS_RED) {
             BLI_stack_push(stack, &index);
           }
         }
@@ -1223,7 +1216,7 @@ static bool dilate_shape(ImBuf *ibuf)
         if (bm && rt) {
           index = bm + 1;
           get_pixel(ibuf, index, color);
-          if (color[0] == 1.0f) {
+          if (IS_RED) {
             BLI_stack_push(stack, &index);
           }
         }
@@ -1240,6 +1233,88 @@ static bool dilate_shape(ImBuf *ibuf)
   BLI_stack_free(stack);
 
   return done;
+
+#undef IS_RED
+#undef IS_GREEN
+}
+
+/**
+ * Contract
+ *
+ * Contract green areas to scale down the size.
+ * Using stack prevents creep when replacing colors directly.
+ */
+static bool contract_shape(ImBuf *ibuf)
+{
+#define IS_GREEN (color[1] == 1.0f)
+#define IS_NOT_GREEN (color[1] != 1.0f)
+
+  bool done = false;
+
+  BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
+  const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+  const int max_size = (ibuf->x * ibuf->y) - 1;
+
+  /* detect pixels and expand into red areas */
+  for (int row = 0; row < ibuf->y; row++) {
+    if (!is_row_filled(ibuf, row)) {
+      continue;
+    }
+    int maxpixel = (ibuf->x * (row + 1)) - 1;
+    int minpixel = ibuf->x * row;
+
+    for (int v = maxpixel; v != minpixel; v--) {
+      float color[4];
+      get_pixel(ibuf, v, color);
+      if (IS_GREEN) {
+        /* pixel left */
+        if (v - 1 >= 0) {
+          get_pixel(ibuf, v - 1, color);
+          if (IS_NOT_GREEN) {
+            BLI_stack_push(stack, &v);
+            continue;
+          }
+        }
+        /* pixel right */
+        if (v + 1 <= maxpixel) {
+          get_pixel(ibuf, v + 1, color);
+          if (IS_NOT_GREEN) {
+            BLI_stack_push(stack, &v);
+            continue;
+          }
+        }
+        /* pixel top */
+        if (v + ibuf->x <= max_size) {
+          get_pixel(ibuf, v + ibuf->x, color);
+          if (IS_NOT_GREEN) {
+            BLI_stack_push(stack, &v);
+            continue;
+          }
+        }
+        /* pixel bottom */
+        if (v - ibuf->x >= 0) {
+          get_pixel(ibuf, v - ibuf->x, color);
+          if (IS_NOT_GREEN) {
+            BLI_stack_push(stack, &v);
+            continue;
+          }
+        }
+      }
+    }
+  }
+  /* Clear pixels. */
+  while (!BLI_stack_is_empty(stack)) {
+    int v;
+    BLI_stack_pop(stack, &v);
+    set_pixel(ibuf, v, clear);
+    done = true;
+  }
+  BLI_stack_free(stack);
+
+  return done;
+
+#undef IS_GREEN
+#undef IS_NOT_GREEN
 }
 
 /* Get the outline points of a shape using Moore Neighborhood algorithm
@@ -1281,10 +1356,15 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate)
   ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
   int imagesize = ibuf->x * ibuf->y;
 
-  /* Dilate. */
+  /* Dilate or contract. */
   if (dilate) {
-    for (int i = 0; i < brush->gpencil_settings->dilate_pixels; i++) {
-      dilate_shape(ibuf);
+    for (int i = 0; i < abs(brush->gpencil_settings->dilate_pixels); i++) {
+      if (brush->gpencil_settings->dilate_pixels > 0) {
+        dilate_shape(ibuf);
+      }
+      else {
+        contract_shape(ibuf);
+      }
     }
   }
 
@@ -1991,6 +2071,24 @@ static void gpencil_zoom_level_set(tGPDfill *tgpf)
   }
 }
 
+static bool gpencil_find_and_mark_empty_areas(tGPDfill *tgpf)
+{
+  ImBuf *ibuf;
+  void *lock;
+  const float blue_col[4] = {0.0f, 0.0f, 1.0f, 1.0f};
+  ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
+  const int maxpixel = (ibuf->x * ibuf->y) - 1;
+  float rgba[4];
+  for (int i = 0; i < maxpixel; i++) {
+    get_pixel(ibuf, i, rgba);
+    if (rgba[3] == 0.0f) {
+      set_pixel(ibuf, i, blue_col);
+      return true;
+    }
+  }
+  return false;
+}
+
 static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted)
 {
   wmWindow *win = CTX_wm_window(tgpf->C);
@@ -2011,6 +2109,9 @@ static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted)
       /* Invert direction if press Ctrl. */
       if (is_inverted) {
         gpencil_invert_image(tgpf);
+        while (gpencil_find_and_mark_empty_areas(tgpf)) {
+          gpencil_boundaryfill_area(tgpf);
+        }
       }
 
       /* Clean borders to avoid infinite loops. */
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index b4cf15ebfc6..7a5877ec4ce 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1629,12 +1629,13 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
       prop, "Stroke Extension", "Strokes end extension for closing gaps, use zero to disable");
   RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
 
-  /* Number of pixels to dilate fill area. */
+  /* Number of pixels to dilate fill area. Negative values contract the filled area. */
   prop = RNA_def_property(srna, "dilate", PROP_INT, PROP_PIXEL);
   RNA_def_property_int_sdna(prop, NULL, "dilate_pixels");
-  RNA_def_property_range(prop, 0, 20);
+  RNA_def_property_range(prop, -40, 40);
   RNA_def_property_int_default(prop, 1);
-  RNA_def_property_ui_text(prop, "Dilate", "Number of pixels to dilate fill area");
+  RNA_def_property_ui_text(
+      prop, "Dilate/Contract", "Number of pixels to expand or contract fill area");
   RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
   RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);



More information about the Bf-blender-cvs mailing list