[gimp] app: various brush hardness improvements



commit 3bed373bff7800269cb1e4f975834fc9daceb51e
Author: Ell <ell_se yahoo com>
Date:   Sat Apr 8 04:36:47 2017 -0400

    app: various brush hardness improvements
    
    Fix brush shrinking used to compensate for the blur: avoid over-
    shrinking the brush and changing its aspect ratio.
    
    Change the way hardness maps to blur radius: hardness == 0 maps to
    the largest radius such that, when the kernel is applied to the
    middle pixel of the brush, the kernel is completely within the brush
    bounds, taking brush shrinking into account, *assuming the brush is
    a circle*.
    
    Use the dimensions of the unrotated brush when calculating the blur
    radius, so that rotation doesn't affect the blur amount (the blur
    itself is not isotropic, though, and is applied after rotation, so
    while the blur amount remains uniform, its effect does depend on the
    brush angle.)
    
    Get rid of the blur-radius upper limit -- it's fast enough to handle
    large radii now.

 app/core/gimpbrush-transform.c |  154 ++++++++++++++++++++++------------------
 1 files changed, 86 insertions(+), 68 deletions(-)
---
diff --git a/app/core/gimpbrush-transform.c b/app/core/gimpbrush-transform.c
index 191b888..8f0103f 100644
--- a/app/core/gimpbrush-transform.c
+++ b/app/core/gimpbrush-transform.c
@@ -35,28 +35,24 @@
 #include "gimptempbuf.h"
 
 
-#define MAX_BLUR_KERNEL 50
-
-
 /*  local function prototypes  */
 
-static void    gimp_brush_transform_bounding_box     (GimpBrush         *brush,
-                                                      const GimpMatrix3 *matrix,
-                                                      gint              *x,
-                                                      gint              *y,
-                                                      gint              *width,
-                                                      gint              *height);
-
-static void    gimp_brush_transform_blur             (GimpTempBuf       *buf,
-                                                      gint               r);
-static gint    gimp_brush_transform_blur_kernel_size (gint               height,
-                                                      gint               width,
-                                                      gdouble            hardness);
-static void    gimp_brush_transform_adjust_hardness_matrix
-                                                     (gdouble      width,
-                                                      gdouble      height,
-                                                      gdouble      kernel_size,
-                                                      GimpMatrix3 *matrix);
+static void    gimp_brush_transform_bounding_box           (GimpBrush         *brush,
+                                                            const GimpMatrix3 *matrix,
+                                                            gint              *x,
+                                                            gint              *y,
+                                                            gint              *width,
+                                                            gint              *height);
+
+static void    gimp_brush_transform_blur                   (GimpTempBuf       *buf,
+                                                            gint               r);
+static gint    gimp_brush_transform_blur_radius            (gint               height,
+                                                            gint               width,
+                                                            gdouble            hardness);
+static void    gimp_brush_transform_adjust_hardness_matrix (gdouble            width,
+                                                            gdouble            height,
+                                                            gdouble            blur_radius,
+                                                            GimpMatrix3       *matrix);
 
 
 /*  public functions  */
@@ -123,7 +119,7 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
   gint          src_height_minus_one;
   gint          dest_width;
   gint          dest_height;
-  gint          kernel_size;
+  gint          blur_radius;
   gint          x, y;
   gdouble       blx, brx, tlx, trx;
   gdouble       bly, bry, tly, try;
@@ -194,15 +190,31 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
 
   gimp_brush_transform_bounding_box (brush, &matrix,
                                      &x, &y, &dest_width, &dest_height);
+
+  blur_radius = 0;
+
   if (hardness < 1.0)
     {
-      kernel_size =
-        gimp_brush_transform_blur_kernel_size (dest_width,
-                                               dest_height,
-                                               hardness);
-
-      gimp_brush_transform_adjust_hardness_matrix (dest_width, dest_height, kernel_size,
-                                                   &matrix);
+      GimpMatrix3 unrotated_matrix;
+      gint        unrotated_x;
+      gint        unrotated_y;
+      gint        unrotated_dest_width;
+      gint        unrotated_dest_height;
+
+      gimp_brush_transform_matrix (src_width, src_height,
+                                   scale, aspect_ratio, 1.0, &unrotated_matrix);
+
+      gimp_brush_transform_bounding_box (brush, &unrotated_matrix,
+                                         &unrotated_x, &unrotated_y,
+                                         &unrotated_dest_width,
+                                         &unrotated_dest_height);
+
+      blur_radius = gimp_brush_transform_blur_radius (unrotated_dest_width,
+                                                      unrotated_dest_height,
+                                                      hardness);
+
+      gimp_brush_transform_adjust_hardness_matrix (dest_width, dest_height,
+                                                   blur_radius, &matrix);
     }
 
   gimp_matrix3_translate (&matrix, -x, -y);
@@ -345,10 +357,7 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
 
     } /* end for y */
 
-  if (hardness < 1.0)
-    {
-      gimp_brush_transform_blur (result, kernel_size / 2);
-    }
+  gimp_brush_transform_blur (result, blur_radius);
 
   return result;
 }
@@ -401,7 +410,7 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
   gint          src_height_minus_one;
   gint          dest_width;
   gint          dest_height;
-  gint          kernel_size;
+  gint          blur_radius;
   gint          x, y;
   gdouble       blx, brx, tlx, trx;
   gdouble       bly, bry, tly, try;
@@ -474,12 +483,30 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
   gimp_brush_transform_bounding_box (brush, &matrix,
                                      &x, &y, &dest_width, &dest_height);
 
-    if (hardness < 1.0)
+  blur_radius = 0;
+
+  if (hardness < 1.0)
     {
-      kernel_size =
-        gimp_brush_transform_blur_kernel_size (dest_width,
-                                               dest_height,
-                                               hardness);
+      GimpMatrix3 unrotated_matrix;
+      gint        unrotated_x;
+      gint        unrotated_y;
+      gint        unrotated_dest_width;
+      gint        unrotated_dest_height;
+
+      gimp_brush_transform_matrix (src_width, src_height,
+                                   scale, aspect_ratio, 1.0, &unrotated_matrix);
+
+      gimp_brush_transform_bounding_box (brush, &unrotated_matrix,
+                                         &unrotated_x, &unrotated_y,
+                                         &unrotated_dest_width,
+                                         &unrotated_dest_height);
+
+      blur_radius = gimp_brush_transform_blur_radius (unrotated_dest_width,
+                                                      unrotated_dest_height,
+                                                      hardness);
+
+      gimp_brush_transform_adjust_hardness_matrix (dest_width, dest_height,
+                                                   blur_radius, &matrix);
     }
 
   gimp_matrix3_translate (&matrix, -x, -y);
@@ -627,10 +654,7 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
         src_space_cur_pos_y = src_space_cur_pos_y_i >> fraction_bits;
     } /* end for y */
 
-  if (hardness < 1.0)
-    {
-      gimp_brush_transform_blur (result, kernel_size / 2);
-    }
+  gimp_brush_transform_blur (result, blur_radius);
 
   return result;
 }
@@ -666,21 +690,6 @@ gimp_brush_transform_matrix (gdouble      width,
   gimp_matrix3_translate (matrix, center_x * scale_x, center_y * scale_y);
 }
 
-void
-gimp_brush_transform_adjust_hardness_matrix (gdouble      width,
-                                             gdouble      height,
-                                             gdouble      kernel_size,
-                                             GimpMatrix3 *matrix)
-{
-
-  gdouble       scale_x  = (width - 2 * kernel_size)/width;
-  gdouble       scale_y  = (height - 2 * kernel_size)/height;
-
-
-  gimp_matrix3_scale (matrix, scale_x, scale_y);
-  gimp_matrix3_translate (matrix, kernel_size, kernel_size);
-}
-
 /*  private functions  */
 
 static void
@@ -910,18 +919,27 @@ gimp_brush_transform_blur (GimpTempBuf *buf,
 }
 
 static gint
-gimp_brush_transform_blur_kernel_size (gint    height,
-                                       gint    width,
-                                       gdouble hardness)
+gimp_brush_transform_blur_radius (gint    height,
+                                  gint    width,
+                                  gdouble hardness)
 {
-  gint kernel_size = (MIN (MAX_BLUR_KERNEL,
-                           MIN (width, height)) *
-                      ((MIN (width, height) * (1.0 - hardness)) /
-                       MIN (width, height)));
+  return floor ((1.0 - hardness) * (sqrt (0.5) - 0.5) * MIN (width, height));
+}
+
+static void
+gimp_brush_transform_adjust_hardness_matrix (gdouble      width,
+                                             gdouble      height,
+                                             gdouble      blur_radius,
+                                             GimpMatrix3 *matrix)
+{
+
+  gdouble scale;
+
+  if (blur_radius == 0.0)
+    return;
 
-  /* Kernel size must be odd */
-  if (kernel_size % 2 == 0)
-    kernel_size++;
+  scale = (MIN (width, height) - 2.0 * blur_radius) / MIN (width, height);
 
-  return kernel_size;
+  gimp_matrix3_scale (matrix, scale, scale);
+  gimp_matrix3_translate (matrix, blur_radius, blur_radius);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]