[gimp] app: merge layers in chunks, and show progress



commit e83d8ac4f2dc0260e97a91938ae3e34608efdbf9
Author: Ell <ell_se yahoo com>
Date:   Mon Feb 25 04:49:04 2019 -0500

    app: merge layers in chunks, and show progress
    
    In gimp_image_merge_layers() -- the internal function used by the
    various layer-merging/flattenning functions -- process the merged-
    layer graph in chunks, using gimp_gegl_apply_operation(), instead
    of in one go, using gegl_node_blit_buffer().  Processing in chunks
    better utilizes the cache, since it reduces the size of
    intermediate buffers, reducing the chances of hitting the swap when
    merging large images (see, for example, issue #3012.)
    
    Additionally, this allows us to show progress indication.  Have the
    relevant gimpimage-merge functions take a GimpProgress, and pass it
    down to gimp_image_merge_layers().  Adapt all callers.

 app/actions/image-commands.c            | 33 +++++++++++-------
 app/actions/layers-commands.c           |  9 +++--
 app/core/gimpimage-merge.c              | 62 ++++++++++++++++++++++-----------
 app/core/gimpimage-merge.h              |  5 ++-
 app/dialogs/image-merge-layers-dialog.c |  3 +-
 app/dialogs/image-merge-layers-dialog.h |  3 +-
 app/file/file-open.c                    |  3 +-
 app/pdb/image-cmds.c                    |  8 +++--
 pdb/groups/image.pdb                    |  8 +++--
 9 files changed, 89 insertions(+), 45 deletions(-)
---
diff --git a/app/actions/image-commands.c b/app/actions/image-commands.c
index a2a108de2f..75544be59c 100644
--- a/app/actions/image-commands.c
+++ b/app/actions/image-commands.c
@@ -166,7 +166,8 @@ static void   image_merge_layers_callback      (GtkWidget              *dialog,
                                                 GimpContext            *context,
                                                 GimpMergeType           merge_type,
                                                 gboolean                merge_active_group,
-                                                gboolean                discard_invisible);
+                                                gboolean                discard_invisible,
+                                                gpointer                user_data);
 
 
 /*  private variables  */
@@ -898,10 +899,12 @@ void
 image_merge_layers_cmd_callback (GtkAction *action,
                                  gpointer   data)
 {
-  GtkWidget *dialog;
-  GimpImage *image;
-  GtkWidget *widget;
+  GtkWidget   *dialog;
+  GimpImage   *image;
+  GimpDisplay *display;
+  GtkWidget   *widget;
   return_if_no_image (image, data);
+  return_if_no_display (display, data);
   return_if_no_widget (widget, data);
 
 #define MERGE_LAYERS_DIALOG_KEY "gimp-merge-layers-dialog"
@@ -919,7 +922,7 @@ image_merge_layers_cmd_callback (GtkAction *action,
                                               config->layer_merge_active_group_only,
                                               config->layer_merge_discard_invisible,
                                               image_merge_layers_callback,
-                                              NULL);
+                                              display);
 
       dialogs_attach_dialog (G_OBJECT (image), MERGE_LAYERS_DIALOG_KEY, dialog);
     }
@@ -931,13 +934,16 @@ void
 image_flatten_image_cmd_callback (GtkAction *action,
                                   gpointer   data)
 {
-  GimpImage *image;
-  GtkWidget *widget;
-  GError    *error = NULL;
+  GimpImage   *image;
+  GimpDisplay *display;
+  GtkWidget   *widget;
+  GError      *error = NULL;
   return_if_no_image (image, data);
+  return_if_no_display (display, data);
   return_if_no_widget (widget, data);
 
-  if (! gimp_image_flatten (image, action_data_get_context (data), &error))
+  if (! gimp_image_flatten (image, action_data_get_context (data),
+                            GIMP_PROGRESS (display), &error))
     {
       gimp_message_literal (image->gimp,
                             G_OBJECT (widget), GIMP_MESSAGE_WARNING,
@@ -1458,9 +1464,11 @@ image_merge_layers_callback (GtkWidget     *dialog,
                              GimpContext   *context,
                              GimpMergeType  merge_type,
                              gboolean       merge_active_group,
-                             gboolean       discard_invisible)
+                             gboolean       discard_invisible,
+                             gpointer       user_data)
 {
-  GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+  GimpDialogConfig *config  = GIMP_DIALOG_CONFIG (image->gimp->config);
+  GimpDisplay      *display = user_data;
 
   g_object_set (config,
                 "layer-merge-type",              merge_type,
@@ -1472,7 +1480,8 @@ image_merge_layers_callback (GtkWidget     *dialog,
                                    context,
                                    config->layer_merge_type,
                                    config->layer_merge_active_group_only,
-                                   config->layer_merge_discard_invisible);
+                                   config->layer_merge_discard_invisible,
+                                   GIMP_PROGRESS (display));
 
   gimp_image_flush (image);
 
diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
index 4d15d0294b..289a0f0228 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -577,12 +577,15 @@ void
 layers_merge_down_cmd_callback (GtkAction *action,
                                 gpointer   data)
 {
-  GimpImage *image;
-  GimpLayer *layer;
+  GimpImage   *image;
+  GimpLayer   *layer;
+  GimpDisplay *display;
   return_if_no_layer (image, layer, data);
+  return_if_no_display (display, data);
 
   gimp_image_merge_down (image, layer, action_data_get_context (data),
-                         GIMP_EXPAND_AS_NECESSARY, NULL);
+                         GIMP_EXPAND_AS_NECESSARY,
+                         GIMP_PROGRESS (display), NULL);
   gimp_image_flush (image);
 }
 
diff --git a/app/core/gimpimage-merge.c b/app/core/gimpimage-merge.c
index f118a8d4e9..b8dc8cc11b 100644
--- a/app/core/gimpimage-merge.c
+++ b/app/core/gimpimage-merge.c
@@ -48,6 +48,7 @@
 #include "gimpmarshal.h"
 #include "gimpparasitelist.h"
 #include "gimppickable.h"
+#include "gimpprogress.h"
 #include "gimpprojectable.h"
 #include "gimpundostack.h"
 
@@ -58,7 +59,9 @@ static GimpLayer * gimp_image_merge_layers (GimpImage     *image,
                                             GimpContainer *container,
                                             GSList        *merge_list,
                                             GimpContext   *context,
-                                            GimpMergeType  merge_type);
+                                            GimpMergeType  merge_type,
+                                            const gchar   *undo_desc,
+                                            GimpProgress  *progress);
 
 
 /*  public functions  */
@@ -68,7 +71,8 @@ gimp_image_merge_visible_layers (GimpImage     *image,
                                  GimpContext   *context,
                                  GimpMergeType  merge_type,
                                  gboolean       merge_active_group,
-                                 gboolean       discard_invisible)
+                                 gboolean       discard_invisible,
+                                 GimpProgress  *progress)
 {
   GimpContainer *container;
   GList         *list;
@@ -77,6 +81,7 @@ gimp_image_merge_visible_layers (GimpImage     *image,
 
   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
 
   if (merge_active_group)
     {
@@ -126,13 +131,14 @@ gimp_image_merge_visible_layers (GimpImage     *image,
 
   if (merge_list)
     {
-      GimpLayer *layer;
+      GimpLayer   *layer;
+      const gchar *undo_desc = C_("undo-type", "Merge Visible Layers");
 
       gimp_set_busy (image->gimp);
 
       gimp_image_undo_group_start (image,
                                    GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE,
-                                   C_("undo-type", "Merge Visible Layers"));
+                                   undo_desc);
 
       /* if there's a floating selection, anchor it */
       if (gimp_image_get_floating_selection (image))
@@ -140,7 +146,8 @@ gimp_image_merge_visible_layers (GimpImage     *image,
 
       layer = gimp_image_merge_layers (image,
                                        container,
-                                       merge_list, context, merge_type);
+                                       merge_list, context, merge_type,
+                                       undo_desc, progress);
       g_slist_free (merge_list);
 
       if (invisible_list)
@@ -164,9 +171,10 @@ gimp_image_merge_visible_layers (GimpImage     *image,
 }
 
 GimpLayer *
-gimp_image_flatten (GimpImage    *image,
-                    GimpContext  *context,
-                    GError      **error)
+gimp_image_flatten (GimpImage     *image,
+                    GimpContext   *context,
+                    GimpProgress  *progress,
+                    GError       **error)
 {
   GList     *list;
   GSList    *merge_list = NULL;
@@ -174,6 +182,7 @@ gimp_image_flatten (GimpImage    *image,
 
   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
   for (list = gimp_image_get_layer_iter (image);
@@ -191,11 +200,13 @@ gimp_image_flatten (GimpImage    *image,
 
   if (merge_list)
     {
+      const gchar *undo_desc = C_("undo-type", "Flatten Image");
+
       gimp_set_busy (image->gimp);
 
       gimp_image_undo_group_start (image,
                                    GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE,
-                                   C_("undo-type", "Flatten Image"));
+                                   undo_desc);
 
       /* if there's a floating selection, anchor it */
       if (gimp_image_get_floating_selection (image))
@@ -204,7 +215,8 @@ gimp_image_flatten (GimpImage    *image,
       layer = gimp_image_merge_layers (image,
                                        gimp_image_get_layers (image),
                                        merge_list, context,
-                                       GIMP_FLATTEN_IMAGE);
+                                       GIMP_FLATTEN_IMAGE,
+                                       undo_desc, progress);
       g_slist_free (merge_list);
 
       gimp_image_alpha_changed (image);
@@ -226,17 +238,20 @@ gimp_image_merge_down (GimpImage      *image,
                        GimpLayer      *current_layer,
                        GimpContext    *context,
                        GimpMergeType   merge_type,
+                       GimpProgress   *progress,
                        GError        **error)
 {
-  GimpLayer *layer;
-  GList     *list;
-  GList     *layer_list = NULL;
-  GSList    *merge_list = NULL;
+  GimpLayer   *layer;
+  GList       *list;
+  GList       *layer_list = NULL;
+  GSList      *merge_list = NULL;
+  const gchar *undo_desc;
 
   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
   g_return_val_if_fail (GIMP_IS_LAYER (current_layer), NULL);
   g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (current_layer)), NULL);
   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
   if (gimp_layer_is_floating_sel (current_layer))
@@ -299,15 +314,18 @@ gimp_image_merge_down (GimpImage      *image,
 
   merge_list = g_slist_prepend (merge_list, current_layer);
 
+  undo_desc = C_("undo-type", "Merge Down");
+
   gimp_set_busy (image->gimp);
 
   gimp_image_undo_group_start (image,
                                GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE,
-                               C_("undo-type", "Merge Down"));
+                               undo_desc);
 
   layer = gimp_image_merge_layers (image,
                                    gimp_item_get_container (GIMP_ITEM (current_layer)),
-                                   merge_list, context, merge_type);
+                                   merge_list, context, merge_type,
+                                   undo_desc, progress);
   g_slist_free (merge_list);
 
   gimp_image_undo_group_end (image);
@@ -457,7 +475,9 @@ gimp_image_merge_layers (GimpImage     *image,
                          GimpContainer *container,
                          GSList        *merge_list,
                          GimpContext   *context,
-                         GimpMergeType  merge_type)
+                         GimpMergeType  merge_type,
+                         const gchar   *undo_desc,
+                         GimpProgress  *progress)
 {
   GimpLayer        *parent;
   gint              x1, y1;
@@ -478,6 +498,7 @@ gimp_image_merge_layers (GimpImage     *image,
 
   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
 
   top_layer = merge_list->data;
   parent    = gimp_layer_get_parent (top_layer);
@@ -660,9 +681,10 @@ gimp_image_merge_layers (GimpImage     *image,
   gegl_node_disconnect (last_node, "input");
 
   /*  Render the graph into the merge layer  */
-  gegl_node_blit_buffer (offset_node,
-                         gimp_drawable_get_buffer (GIMP_DRAWABLE (merge_layer)),
-                         NULL, 0, GEGL_ABYSS_NONE);
+  gimp_gegl_apply_operation (NULL, progress, undo_desc, offset_node,
+                             gimp_drawable_get_buffer (
+                               GIMP_DRAWABLE (merge_layer)),
+                             NULL, FALSE);
 
   /*  Reconnect the bottom-layer node's input  */
   if (last_node_source)
diff --git a/app/core/gimpimage-merge.h b/app/core/gimpimage-merge.h
index 4b7a916561..93aab4e53a 100644
--- a/app/core/gimpimage-merge.h
+++ b/app/core/gimpimage-merge.h
@@ -23,17 +23,20 @@ GimpLayer   * gimp_image_merge_visible_layers  (GimpImage      *image,
                                                 GimpContext    *context,
                                                 GimpMergeType   merge_type,
                                                 gboolean        merge_active_group,
-                                                gboolean        discard_invisible);
+                                                gboolean        discard_invisible,
+                                                GimpProgress   *progress);
 GimpLayer   * gimp_image_merge_down            (GimpImage      *image,
                                                 GimpLayer      *current_layer,
                                                 GimpContext    *context,
                                                 GimpMergeType   merge_type,
+                                                GimpProgress   *progress,
                                                 GError        **error);
 GimpLayer   * gimp_image_merge_group_layer     (GimpImage      *image,
                                                 GimpGroupLayer *group);
 
 GimpLayer   * gimp_image_flatten               (GimpImage      *image,
                                                 GimpContext    *context,
+                                                GimpProgress   *progress,
                                                 GError        **error);
 
 GimpVectors * gimp_image_merge_visible_vectors (GimpImage      *image,
diff --git a/app/dialogs/image-merge-layers-dialog.c b/app/dialogs/image-merge-layers-dialog.c
index 552d26bafa..67681eb779 100644
--- a/app/dialogs/image-merge-layers-dialog.c
+++ b/app/dialogs/image-merge-layers-dialog.c
@@ -182,7 +182,8 @@ image_merge_layers_dialog_response (GtkWidget              *dialog,
                          private->context,
                          private->merge_type,
                          private->merge_active_group,
-                         private->discard_invisible);
+                         private->discard_invisible,
+                         private->user_data);
     }
   else
     {
diff --git a/app/dialogs/image-merge-layers-dialog.h b/app/dialogs/image-merge-layers-dialog.h
index e763f91cc9..ee965150ee 100644
--- a/app/dialogs/image-merge-layers-dialog.h
+++ b/app/dialogs/image-merge-layers-dialog.h
@@ -24,7 +24,8 @@ typedef void (* GimpMergeLayersCallback) (GtkWidget     *dialog,
                                           GimpContext   *context,
                                           GimpMergeType  merge_type,
                                           gboolean       merge_active_group,
-                                          gboolean       discard_invisible);
+                                          gboolean       discard_invisible,
+                                          gpointer       user_data);
 
 
 GtkWidget *
diff --git a/app/file/file-open.c b/app/file/file-open.c
index 0747c7cf4a..fcb7fc3d5f 100644
--- a/app/file/file-open.c
+++ b/app/file/file-open.c
@@ -634,7 +634,8 @@ file_open_layers (Gimp                *gimp,
 
           layer = gimp_image_merge_visible_layers (new_image, context,
                                                    GIMP_CLIP_TO_IMAGE,
-                                                   FALSE, FALSE);
+                                                   FALSE, FALSE,
+                                                   NULL);
 
           layers = g_list_prepend (NULL, layer);
         }
diff --git a/app/pdb/image-cmds.c b/app/pdb/image-cmds.c
index 2ddf89b590..17c56d737b 100644
--- a/app/pdb/image-cmds.c
+++ b/app/pdb/image-cmds.c
@@ -1365,7 +1365,8 @@ image_flatten_invoker (GimpProcedure         *procedure,
 
   if (success)
     {
-      layer = gimp_image_flatten (image, context, error);
+      layer = gimp_image_flatten (image, context,
+                                  progress, error);
 
       if (! layer)
         success = FALSE;
@@ -1400,7 +1401,8 @@ image_merge_visible_layers_invoker (GimpProcedure         *procedure,
   if (success)
     {
       layer = gimp_image_merge_visible_layers (image, context, merge_type,
-                                               FALSE, FALSE);
+                                               FALSE, FALSE,
+                                               progress);
 
       if (! layer)
         success = FALSE;
@@ -1439,7 +1441,7 @@ image_merge_down_invoker (GimpProcedure         *procedure,
       if (gimp_pdb_item_is_attached (GIMP_ITEM (merge_layer), image, 0, error))
         {
           layer = gimp_image_merge_down (image, merge_layer, context, merge_type,
-                                         error);
+                                         progress, error);
 
           if (! layer)
             success = FALSE;
diff --git a/pdb/groups/image.pdb b/pdb/groups/image.pdb
index d67ce341e3..d51079082c 100644
--- a/pdb/groups/image.pdb
+++ b/pdb/groups/image.pdb
@@ -740,7 +740,8 @@ HELP
         code => <<'CODE'
 {
   layer = gimp_image_merge_visible_layers (image, context, merge_type,
-                                           FALSE, FALSE);
+                                           FALSE, FALSE,
+                                           progress);
 
   if (! layer)
     success = FALSE;
@@ -786,7 +787,7 @@ HELP
   if (gimp_pdb_item_is_attached (GIMP_ITEM (merge_layer), image, 0, error))
     {
       layer = gimp_image_merge_down (image, merge_layer, context, merge_type,
-                                     error);
+                                     progress, error);
 
       if (! layer)
         success = FALSE;
@@ -825,7 +826,8 @@ HELP
         headers => [ qw("core/gimpimage-merge.h") ],
         code => <<'CODE'
 {
-  layer = gimp_image_flatten (image, context, error);
+  layer = gimp_image_flatten (image, context,
+                              progress, error);
 
   if (! layer)
     success = FALSE;


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