[gimp] Paint Select tool: enable viewport-based local selection



commit 041104b5ec9db3faf637f59e36de4544c4d05a9d
Author: Thomas Manni <thomas manni free fr>
Date:   Mon Jan 18 18:43:39 2021 +0100

    Paint Select tool: enable viewport-based local selection
    
    The tool now takes care of the portion of the layer effectively displayed
    on the screen. This allows faster expansion/shrink of the selection since
    an area smaller than the whole layer is used.
    
    It will also limit the impact of the incoming multilevels processing, which
    tends to decrease the segmentation accuracy on thin structures, since users
    often zoom-in to work on such thin details.

 app/tools/gimppaintselecttool.c | 90 +++++++++++++++++++++++++++++++++++++++--
 app/tools/gimppaintselecttool.h |  2 +
 2 files changed, 89 insertions(+), 3 deletions(-)
---
diff --git a/app/tools/gimppaintselecttool.c b/app/tools/gimppaintselecttool.c
index 9732f612dd..10bad87431 100644
--- a/app/tools/gimppaintselecttool.c
+++ b/app/tools/gimppaintselecttool.c
@@ -55,6 +55,7 @@
 
 #include "display/gimpdisplay.h"
 #include "display/gimpdisplayshell.h"
+#include "display/gimpdisplayshell-scroll.h"
 #include "display/gimptoolgui.h"
 
 #include "core/gimptooloptions.h"
@@ -132,6 +133,14 @@ static gboolean  gimp_paint_select_tool_paint_scribble     (GimpPaintSelectTool
 
 static void      gimp_paint_select_tool_toggle_scribbles_visibility (GimpPaintSelectTool  *ps_tool);
 
+static GeglRectangle gimp_paint_select_tool_get_local_region (GimpDisplay        *display,
+                                                              gint                brush_x,
+                                                              gint                brush_y,
+                                                              gint                drawable_off_x,
+                                                              gint                drawable_off_y,
+                                                              gint                drawable_width,
+                                                              gint                drawable_height);
+
 static gfloat euclidean_distance                           (gint                  x1,
                                                             gint                  y1,
                                                             gint                  x2,
@@ -454,8 +463,16 @@ gimp_paint_select_tool_motion (GimpTool         *tool,
           if (gimp_paint_select_tool_paint_scribble (ps_tool))
             {
               GimpPaintSelectOptions *options = GIMP_PAINT_SELECT_TOOL_GET_OPTIONS (ps_tool);
+              GeglRectangle  local_region;
               GeglBuffer  *result;
-              GTimer *timer = g_timer_new ();
+              GTimer      *timer;
+
+              local_region = gimp_paint_select_tool_get_local_region (display,
+                                                       coords->x, coords->y,
+                                                       ps_tool->drawable_off_x,
+                                                       ps_tool->drawable_off_y,
+                                                       ps_tool->drawable_width,
+                                                       ps_tool->drawable_height);
 
               if (options->mode == GIMP_PAINT_SELECT_MODE_ADD)
                 {
@@ -468,12 +485,29 @@ gimp_paint_select_tool_motion (GimpTool         *tool,
                   gegl_node_set (ps_tool->threshold_node, "value", 0.01, NULL);
                 }
 
+              if (local_region.width < ps_tool->drawable_width ||
+                  local_region.height < ps_tool->drawable_height)
+                {
+                  gegl_node_set (ps_tool->ps_node,
+                                 "use_local_region", TRUE,
+                                 "region_x", local_region.x,
+                                 "region_y", local_region.y,
+                                 "region_width", local_region.width,
+                                 "region_height", local_region.height,
+                                 NULL);
+                }
+              else
+                {
+                  gegl_node_set (ps_tool->ps_node,
+                                 "use_local_region", FALSE, NULL);
+                }
+
               gegl_node_set (ps_tool->render_node, "buffer", &result, NULL);
 
-              g_timer_start (timer);
+              timer = g_timer_new ();;
               gegl_node_process (ps_tool->render_node);
               g_timer_stop (timer);
-              g_printerr ("processing graph takes %.3f s\n", g_timer_elapsed (timer, NULL));
+              g_printerr ("processing graph takes %.3f s\n\n", g_timer_elapsed (timer, NULL));
               g_timer_destroy (timer);
 
               gimp_paint_select_tool_update_image_mask (ps_tool,
@@ -630,6 +664,8 @@ gimp_paint_select_tool_init_buffers (GimpPaintSelectTool  *ps_tool,
   gimp_item_get_offset (GIMP_ITEM (drawable),
                         &ps_tool->drawable_off_x,
                         &ps_tool->drawable_off_y);
+  ps_tool->drawable_width  = gimp_item_get_width (GIMP_ITEM (drawable));
+  ps_tool->drawable_height = gimp_item_get_height (GIMP_ITEM (drawable));
 
   ps_tool->drawable = gimp_drawable_get_buffer (drawable);
 
@@ -845,6 +881,54 @@ gimp_paint_select_tool_toggle_scribbles_visibility (GimpPaintSelectTool  *ps_too
     }
 }
 
+static GeglRectangle
+gimp_paint_select_tool_get_local_region (GimpDisplay  *display,
+                                         gint          brush_x,
+                                         gint          brush_y,
+                                         gint          drawable_off_x,
+                                         gint          drawable_off_y,
+                                         gint          drawable_width,
+                                         gint          drawable_height)
+{
+  GimpDisplayShell  *shell;
+  GeglRectangle      brush_window;
+  GeglRectangle      drawable_region;
+  GeglRectangle      viewport;
+  GeglRectangle      local_region;
+  gdouble            x, y, w, h;
+
+  shell = gimp_display_get_shell (display);
+  gimp_display_shell_scroll_get_viewport (shell, &x, &y, &w, &h);
+
+  viewport.x      = (gint) x;
+  viewport.y      = (gint) y;
+  viewport.width  = (gint) w;
+  viewport.height = (gint) h;
+
+  brush_window.x      = brush_x - viewport.width / 2;
+  brush_window.y      = brush_y - viewport.height / 2;
+  brush_window.width  = viewport.width;
+  brush_window.height = viewport.height;
+
+  gegl_rectangle_bounding_box (&local_region, &brush_window, &viewport);
+
+  drawable_region.x      = drawable_off_x;
+  drawable_region.y      = drawable_off_y;
+  drawable_region.width  = drawable_width;
+  drawable_region.height = drawable_height;
+
+  gegl_rectangle_intersect (&local_region, &local_region, &drawable_region);
+
+  local_region.x -= drawable_off_x;
+  local_region.y -= drawable_off_y;
+
+  g_printerr ("local region: (%d,%d) %d x %d\n",
+              local_region.x, local_region.y,
+              local_region.width, local_region.height);
+
+  return local_region;
+}
+
 static gfloat
 euclidean_distance (gint  x1,
                     gint  y1,
diff --git a/app/tools/gimppaintselecttool.h b/app/tools/gimppaintselecttool.h
index f5008aa90d..6281e30231 100644
--- a/app/tools/gimppaintselecttool.h
+++ b/app/tools/gimppaintselecttool.h
@@ -46,6 +46,8 @@ struct _GimpPaintSelectTool
 
   gint                   drawable_off_x;
   gint                   drawable_off_y;
+  gint                   drawable_width;
+  gint                   drawable_height;
 
   GeglNode              *graph;
   GeglNode              *ps_node;


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