[gimp] Bug 725556 - Feather selection extremely slow



commit 30ae88ef073db163489de7cad07a07afe56ba692
Author: Michael Natterer <mitch gimp org>
Date:   Tue Mar 4 22:09:11 2014 +0100

    Bug 725556 - Feather selection extremely slow
    
    gimp_gegl_apply_feather(): add a "dest_rect" parameter to restrict
    the feather area. Pass the selection bounds plus the feather radius.
    
    For consistency, newly add gimp_gegl_apply_border,grow,shrink() and use
    them in gimpchannel.c

 app/core/gimpchannel-select.c        |   10 ++--
 app/core/gimpchannel.c               |   91 ++++++++++++---------------
 app/gegl/gimp-gegl-apply-operation.c |  114 +++++++++++++++++++++++++++++----
 app/gegl/gimp-gegl-apply-operation.h |   29 +++++++++
 4 files changed, 173 insertions(+), 71 deletions(-)
---
diff --git a/app/core/gimpchannel-select.c b/app/core/gimpchannel-select.c
index 765aa52..b804bc1 100644
--- a/app/core/gimpchannel-select.c
+++ b/app/core/gimpchannel-select.c
@@ -83,7 +83,7 @@ gimp_channel_select_rectangle (GimpChannel    *channel,
       gimp_gegl_mask_combine_rect (add_on, GIMP_CHANNEL_OP_ADD, x, y, w, h);
 
       if (feather)
-        gimp_gegl_apply_feather (add_on, NULL, NULL, add_on,
+        gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL,
                                  feather_radius_x,
                                  feather_radius_y);
 
@@ -136,7 +136,7 @@ gimp_channel_select_ellipse (GimpChannel    *channel,
                                       x, y, w, h, antialias);
 
       if (feather)
-        gimp_gegl_apply_feather (add_on, NULL, NULL, add_on,
+        gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL,
                                  feather_radius_x,
                                  feather_radius_y);
 
@@ -193,7 +193,7 @@ gimp_channel_select_round_rect (GimpChannel         *channel,
                                            antialias);
 
       if (feather)
-        gimp_gegl_apply_feather (add_on, NULL, NULL, add_on,
+        gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL,
                                  feather_radius_x,
                                  feather_radius_y);
 
@@ -249,7 +249,7 @@ gimp_channel_select_scan_convert (GimpChannel     *channel,
                             offset_x, offset_y, antialias);
 
   if (feather)
-    gimp_gegl_apply_feather (add_on, NULL, NULL, add_on,
+    gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL,
                              feather_radius_x,
                              feather_radius_y);
 
@@ -363,7 +363,7 @@ gimp_channel_select_buffer (GimpChannel    *channel,
                                      offset_x, offset_y);
 
       if (feather)
-        gimp_gegl_apply_feather (add_on2, NULL, NULL, add_on2,
+        gimp_gegl_apply_feather (add_on2, NULL, NULL, add_on2, NULL,
                                  feather_radius_x,
                                  feather_radius_y);
 
diff --git a/app/core/gimpchannel.c b/app/core/gimpchannel.c
index 6aeefd8..4f466e1 100644
--- a/app/core/gimpchannel.c
+++ b/app/core/gimpchannel.c
@@ -23,6 +23,7 @@
 #include <gegl.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
+#include "libgimpmath/gimpmath.h"
 #include "libgimpcolor/gimpcolor.h"
 
 #include "core-types.h"
@@ -1181,17 +1182,33 @@ gimp_channel_real_feather (GimpChannel *channel,
                            gdouble      radius_y,
                            gboolean     push_undo)
 {
-  GimpDrawable *drawable = GIMP_DRAWABLE (channel);
+  gint x1, y1, x2, y2;
+
+  if (radius_x <= 0.0 && radius_y <= 0.0)
+    return;
+
+  if (! gimp_channel_bounds (channel, &x1, &y1, &x2, &y2))
+    return;
+
+  if (gimp_channel_is_empty (channel))
+    return;
+
+  x1 = MAX (0, x1 - ceil (radius_x));
+  y1 = MAX (0, y1 - ceil (radius_y));
+
+  x2 = MIN (gimp_item_get_width  (GIMP_ITEM (channel)), x2 + ceil (radius_x));
+  y2 = MIN (gimp_item_get_height (GIMP_ITEM (channel)), y2 + ceil (radius_y));
 
   if (push_undo)
     gimp_channel_push_undo (channel,
                             GIMP_CHANNEL_GET_CLASS (channel)->feather_desc);
   else
-    gimp_drawable_invalidate_boundary (drawable);
+    gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 
-  gimp_gegl_apply_feather (gimp_drawable_get_buffer (drawable),
+  gimp_gegl_apply_feather (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
                            NULL, NULL,
-                           gimp_drawable_get_buffer (drawable),
+                           gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
+                           GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
                            radius_x,
                            radius_y);
 
@@ -1338,8 +1355,7 @@ gimp_channel_real_border (GimpChannel *channel,
                           gboolean     edge_lock,
                           gboolean     push_undo)
 {
-  GeglNode *border;
-  gint      x1, y1, x2, y2;
+  gint x1, y1, x2, y2;
 
   if (radius_x < 0 || radius_y < 0)
     return;
@@ -1376,21 +1392,11 @@ gimp_channel_real_border (GimpChannel *channel,
   else
     gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 
-  border = gegl_node_new_child (NULL,
-                                "operation", "gimp:border",
-                                "radius-x",  radius_x,
-                                "radius-y",  radius_y,
-                                "feather",   feather,
-                                "edge-lock", edge_lock,
-                                NULL);
-
-  gimp_gegl_apply_operation (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
-                             NULL, NULL,
-                             border,
-                             gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
-                             GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1));
-
-  g_object_unref (border);
+  gimp_gegl_apply_border (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
+                          NULL, NULL,
+                          gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
+                          GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
+                          radius_x, radius_y, feather, edge_lock);
 
   channel->bounds_known = FALSE;
 
@@ -1405,8 +1411,7 @@ gimp_channel_real_grow (GimpChannel *channel,
                         gint         radius_y,
                         gboolean     push_undo)
 {
-  GeglNode *grow;
-  gint      x1, y1, x2, y2;
+  gint x1, y1, x2, y2;
 
   if (radius_x == 0 && radius_y == 0)
     return;
@@ -1452,19 +1457,11 @@ gimp_channel_real_grow (GimpChannel *channel,
   else
     gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 
-  grow = gegl_node_new_child (NULL,
-                              "operation", "gimp:grow",
-                              "radius-x",  radius_x,
-                              "radius-y",  radius_y,
-                              NULL);
-
-  gimp_gegl_apply_operation (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
-                             NULL, NULL,
-                             grow,
-                             gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
-                             GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1));
-
-  g_object_unref (grow);
+  gimp_gegl_apply_grow (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
+                        NULL, NULL,
+                        gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
+                        GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
+                        radius_x, radius_y);
 
   channel->bounds_known = FALSE;
 
@@ -1480,8 +1477,7 @@ gimp_channel_real_shrink (GimpChannel *channel,
                           gboolean     edge_lock,
                           gboolean     push_undo)
 {
-  GeglNode *shrink;
-  gint      x1, y1, x2, y2;
+  gint x1, y1, x2, y2;
 
   if (radius_x == 0 && radius_y == 0)
     return;
@@ -1516,20 +1512,11 @@ gimp_channel_real_shrink (GimpChannel *channel,
   else
     gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
 
-  shrink = gegl_node_new_child (NULL,
-                                "operation", "gimp:shrink",
-                                "radius-x",  radius_x,
-                                "radius-y",  radius_y,
-                                "edge-lock", edge_lock,
-                                NULL);
-
-  gimp_gegl_apply_operation (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
-                             NULL, NULL,
-                             shrink,
-                             gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
-                             GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1));
-
-  g_object_unref (shrink);
+  gimp_gegl_apply_shrink (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
+                          NULL, NULL,
+                          gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
+                          GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
+                          radius_x, radius_y, edge_lock);
 
   channel->bounds_known = FALSE;
 
diff --git a/app/gegl/gimp-gegl-apply-operation.c b/app/gegl/gimp-gegl-apply-operation.c
index 180007c..059150d 100644
--- a/app/gegl/gimp-gegl-apply-operation.c
+++ b/app/gegl/gimp-gegl-apply-operation.c
@@ -185,12 +185,13 @@ gimp_gegl_apply_flatten (GeglBuffer    *src_buffer,
 }
 
 void
-gimp_gegl_apply_feather (GeglBuffer   *src_buffer,
-                         GimpProgress *progress,
-                         const gchar  *undo_desc,
-                         GeglBuffer   *dest_buffer,
-                         gdouble       radius_x,
-                         gdouble       radius_y)
+gimp_gegl_apply_feather (GeglBuffer          *src_buffer,
+                         GimpProgress        *progress,
+                         const gchar         *undo_desc,
+                         GeglBuffer          *dest_buffer,
+                         const GeglRectangle *dest_rect,
+                         gdouble              radius_x,
+                         gdouble              radius_y)
 {
   g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
   g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
@@ -201,18 +202,103 @@ gimp_gegl_apply_feather (GeglBuffer   *src_buffer,
    */
   gimp_gegl_apply_gaussian_blur (src_buffer,
                                  progress, undo_desc,
-                                 dest_buffer,
+                                 dest_buffer, dest_rect,
                                  radius_x / 3.5,
                                  radius_y / 3.5);
 }
 
 void
-gimp_gegl_apply_gaussian_blur (GeglBuffer   *src_buffer,
-                               GimpProgress *progress,
-                               const gchar  *undo_desc,
-                               GeglBuffer   *dest_buffer,
-                               gdouble       std_dev_x,
-                               gdouble       std_dev_y)
+gimp_gegl_apply_border (GeglBuffer          *src_buffer,
+                        GimpProgress        *progress,
+                        const gchar         *undo_desc,
+                        GeglBuffer          *dest_buffer,
+                        const GeglRectangle *dest_rect,
+                        gint                 radius_x,
+                        gint                 radius_y,
+                        gboolean             feather,
+                        gboolean             edge_lock)
+{
+  GeglNode *node;
+
+  g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
+  g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
+  g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
+
+  node = gegl_node_new_child (NULL,
+                              "operation", "gimp:border",
+                              "radius-x",  radius_x,
+                              "radius-y",  radius_y,
+                              "feather",   feather,
+                              "edge-lock", edge_lock,
+                              NULL);
+
+  gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
+                             node, dest_buffer, dest_rect);
+  g_object_unref (node);
+}
+
+void
+gimp_gegl_apply_grow (GeglBuffer          *src_buffer,
+                      GimpProgress        *progress,
+                      const gchar         *undo_desc,
+                      GeglBuffer          *dest_buffer,
+                      const GeglRectangle *dest_rect,
+                      gint                 radius_x,
+                      gint                 radius_y)
+{
+  GeglNode *node;
+
+  g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
+  g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
+  g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
+
+  node = gegl_node_new_child (NULL,
+                              "operation", "gimp:grow",
+                              "radius-x",  radius_x,
+                              "radius-y",  radius_y,
+                              NULL);
+
+  gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
+                             node, dest_buffer, dest_rect);
+  g_object_unref (node);
+}
+
+void
+gimp_gegl_apply_shrink (GeglBuffer          *src_buffer,
+                        GimpProgress        *progress,
+                        const gchar         *undo_desc,
+                        GeglBuffer          *dest_buffer,
+                        const GeglRectangle *dest_rect,
+                        gint                 radius_x,
+                        gint                 radius_y,
+                        gboolean             edge_lock)
+{
+  GeglNode *node;
+
+  g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
+  g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
+  g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
+
+  node = gegl_node_new_child (NULL,
+                              "operation", "gimp:shrink",
+                              "radius-x",  radius_x,
+                              "radius-y",  radius_y,
+                              "edge-lock", edge_lock,
+                              NULL);
+
+  gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
+                             node, dest_buffer, dest_rect);
+  g_object_unref (node);
+}
+
+void
+gimp_gegl_apply_gaussian_blur (GeglBuffer          *src_buffer,
+                               GimpProgress        *progress,
+                               const gchar         *undo_desc,
+                               GeglBuffer          *dest_buffer,
+                               const GeglRectangle *dest_rect,
+                               gdouble              std_dev_x,
+                               gdouble              std_dev_y)
 {
   GeglNode *node;
 
@@ -227,7 +313,7 @@ gimp_gegl_apply_gaussian_blur (GeglBuffer   *src_buffer,
                               NULL);
 
   gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
-                             node, dest_buffer, NULL);
+                             node, dest_buffer, dest_rect);
   g_object_unref (node);
 }
 
diff --git a/app/gegl/gimp-gegl-apply-operation.h b/app/gegl/gimp-gegl-apply-operation.h
index 14e3822..06edaa5 100644
--- a/app/gegl/gimp-gegl-apply-operation.h
+++ b/app/gegl/gimp-gegl-apply-operation.h
@@ -53,13 +53,42 @@ void   gimp_gegl_apply_feather         (GeglBuffer            *src_buffer,
                                         GimpProgress          *progress,
                                         const gchar           *undo_desc,
                                         GeglBuffer            *dest_buffer,
+                                        const GeglRectangle   *dest_rect,
                                         gdouble                radius_x,
                                         gdouble                radius_y);
 
+void   gimp_gegl_apply_border          (GeglBuffer            *src_buffer,
+                                        GimpProgress          *progress,
+                                        const gchar           *undo_desc,
+                                        GeglBuffer            *dest_buffer,
+                                        const GeglRectangle   *dest_rect,
+                                        gint                   radius_x,
+                                        gint                   radius_y,
+                                        gboolean               feather,
+                                        gboolean               edge_lock);
+
+void   gimp_gegl_apply_grow            (GeglBuffer            *src_buffer,
+                                        GimpProgress          *progress,
+                                        const gchar           *undo_desc,
+                                        GeglBuffer            *dest_buffer,
+                                        const GeglRectangle   *dest_rect,
+                                        gint                   radius_x,
+                                        gint                   radius_y);
+
+void   gimp_gegl_apply_shrink          (GeglBuffer            *src_buffer,
+                                        GimpProgress          *progress,
+                                        const gchar           *undo_desc,
+                                        GeglBuffer            *dest_buffer,
+                                        const GeglRectangle   *dest_rect,
+                                        gint                   radius_x,
+                                        gint                   radius_y,
+                                        gboolean               edge_lock);
+
 void   gimp_gegl_apply_gaussian_blur   (GeglBuffer            *src_buffer,
                                         GimpProgress          *progress,
                                         const gchar           *undo_desc,
                                         GeglBuffer            *dest_buffer,
+                                        const GeglRectangle   *dest_rect,
                                         gdouble                std_dev_x,
                                         gdouble                std_dev_y);
 


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