[gimp] app: improve alpha to selection with multiple items.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: improve alpha to selection with multiple items.
- Date: Wed, 20 May 2020 16:47:39 +0000 (UTC)
commit 32740ac0decc821436e443fb6a687564fa95538b
Author: Jehan <jehan girinstud io>
Date: Wed May 20 18:16:30 2020 +0200
app: improve alpha to selection with multiple items.
I created a new function gimp_channel_combine_items() which combines a
list of items with a channel. The list of items is first combined
together as an union set, then only combined with the channel with the
desired operation (this is important for operations such as intersect
which was broken in my previous commit because all items would be
intersected with each other and the selection, whereas we actually want
the union of all items to be intersected with the selection). This new
function is now used for "Alpha to Selection".
Also similarly to copy or color-pick on multi-layers, alpha to selection
will now use the composited result of the multi-layers as visible. In
particular it means that opacity, modes and visible properties on the
layers are taken into account. Alpha to selection on a single layer
though still works as previously, only taking the non-composited layer
data into account.
I am actually struggling if alpha to selection on uncomposited layers
(just an union on alpha to selection result for each layer) would not
make sense to on some workflows. To be experimented.
Finally it is to be noted that this function should also work on
channels and vectors (both single or multiple; and of course in such
cases, compositing does not matter) though I haven't tested yet. It
could even work with a source mix of layers, channels and vectors,
though our GUI does not allow such action currently.
app/actions/layers-commands.c | 16 ++----
app/core/gimpchannel-combine.c | 110 +++++++++++++++++++++++++++++++++++++++++
app/core/gimpchannel-combine.h | 4 ++
3 files changed, 119 insertions(+), 11 deletions(-)
---
diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
index ee67147f05..6b8be0922f 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -35,6 +35,7 @@
#include "core/gimp.h"
#include "core/gimpchannel.h"
+#include "core/gimpchannel-combine.h"
#include "core/gimpcontainer.h"
#include "core/gimpcontext.h"
#include "core/gimpdrawable-fill.h"
@@ -1556,22 +1557,15 @@ layers_alpha_to_selection_cmd_callback (GimpAction *action,
{
GimpImage *image;
GList *layers;
- GList *iter;
GimpChannelOps operation;
return_if_no_layers (image, layers, data);
operation = (GimpChannelOps) g_variant_get_int32 (value);
- for (iter = layers; iter; iter = iter->next)
- {
- if (operation != GIMP_CHANNEL_OP_REPLACE || iter == layers)
- gimp_item_to_selection (GIMP_ITEM (iter->data), operation,
- TRUE, FALSE, 0.0, 0.0);
- else
- gimp_item_to_selection (GIMP_ITEM (iter->data),
- GIMP_CHANNEL_OP_ADD,
- TRUE, FALSE, 0.0, 0.0);
- }
+ gimp_channel_push_undo (gimp_image_get_mask (image),
+ C_("undo-type", "Alpha to Selection"));
+ gimp_channel_combine_items (gimp_image_get_mask (image),
+ layers, operation);
gimp_image_flush (image);
}
diff --git a/app/core/gimpchannel-combine.c b/app/core/gimpchannel-combine.c
index 8326f65b0c..2d87078f57 100644
--- a/app/core/gimpchannel-combine.c
+++ b/app/core/gimpchannel-combine.c
@@ -29,8 +29,15 @@
#include "gegl/gimp-gegl-mask-combine.h"
+#include "gimp.h"
#include "gimpchannel.h"
#include "gimpchannel-combine.h"
+#include "gimpimage.h"
+#include "gimpimage-merge.h"
+#include "gimpimage-new.h"
+#include "gimplayer.h"
+
+#include "vectors/gimpvectors.h"
typedef struct
@@ -469,3 +476,106 @@ gimp_channel_combine_buffer (GimpChannel *mask,
gimp_channel_combine_end (mask, &data);
}
+
+/**
+ * gimp_channel_combine_items:
+ * @channel:
+ * @items:
+ * @op:
+ *
+ * Edit @channel with the given @items, according to the boolean @op.
+ * @items need to belong to the same image, but it doesn't have to be
+ * the owner image of @channel.
+ * If @items contain a single layer, it will be used as-is, without
+ * caring about opacity, mode or visibility.
+ * If @items contain several layers, they will be used composited using
+ * their opacity, mode, visibility, etc. properties within the image
+ * (similar as if a "merge visible" had been applied to the image then
+ * the resulting layer used alone).
+ * If @items contain channels or vectors, they will be added as a set
+ * (i.e. as a single item which is an union of other items). E.g. an
+ * combine in GIMP_CHANNEL_OP_INTERSECT mode does not intersect all
+ * @items with each other and @channel. It first adds-alike all @items
+ * together, then intersects the result with @channel.
+ */
+void
+gimp_channel_combine_items (GimpChannel *mask,
+ GList *items,
+ GimpChannelOps op)
+{
+ GimpImage *image;
+ GimpImage *items_image = NULL;
+ GimpImage *temp_image = NULL;
+
+ GimpChannel *channel = NULL;
+ GList *layers = NULL;
+ GList *iter;
+
+ g_return_if_fail (GIMP_IS_CHANNEL (mask));
+ g_return_if_fail (g_list_length (items) > 0);
+
+ for (iter = items; iter; iter = iter->next)
+ {
+ g_return_if_fail (GIMP_IS_LAYER (iter->data) ||
+ GIMP_IS_CHANNEL (iter->data) ||
+ GIMP_IS_VECTORS (iter->data));
+
+ if (items_image == NULL)
+ items_image = gimp_item_get_image (iter->data);
+ else
+ g_return_if_fail (items_image == gimp_item_get_image (iter->data));
+
+ if (GIMP_IS_LAYER (iter->data))
+ layers = g_list_prepend (layers, iter->data);
+ }
+
+ image = gimp_item_get_image (GIMP_ITEM (mask));
+ if (g_list_length (layers) > 1)
+ {
+ GList *merged_layers;
+
+ temp_image = gimp_image_new_from_drawables (image->gimp, items, FALSE);
+ merged_layers = gimp_image_merge_visible_layers (temp_image,
+ gimp_get_user_context (temp_image->gimp),
+ GIMP_CLIP_TO_IMAGE,
+ FALSE, TRUE, NULL);
+ g_return_if_fail (g_list_length (merged_layers) == 1);
+ gimp_item_to_selection (GIMP_ITEM (merged_layers->data),
+ GIMP_CHANNEL_OP_REPLACE,
+ TRUE, FALSE, 0.0, 0.0);
+ channel = gimp_image_get_mask (temp_image);
+ }
+
+ if (! channel)
+ {
+ channel = gimp_channel_new (image,
+ gimp_image_get_width (image),
+ gimp_image_get_height (image),
+ NULL, NULL);
+ gimp_channel_clear (channel, NULL, FALSE);
+
+ if (g_list_length (layers) == 1)
+ gimp_channel_combine_buffer (channel,
+ gimp_drawable_get_buffer (GIMP_DRAWABLE (layers->data)),
+ GIMP_CHANNEL_OP_REPLACE, 0, 0);
+ }
+
+ for (iter = items; iter; iter = iter->next)
+ {
+ if (! GIMP_IS_LAYER (iter->data))
+ gimp_channel_combine_buffer (channel,
+ gimp_drawable_get_buffer (GIMP_DRAWABLE (iter->data)),
+ GIMP_CHANNEL_OP_ADD, 0, 0);
+ }
+
+ gimp_channel_combine_buffer (mask,
+ gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
+ op, 0, 0);
+
+ if (temp_image)
+ g_object_unref (temp_image);
+ else
+ g_object_unref (channel);
+
+ g_list_free (layers);
+}
diff --git a/app/core/gimpchannel-combine.h b/app/core/gimpchannel-combine.h
index de1f125c5c..fdee026745 100644
--- a/app/core/gimpchannel-combine.h
+++ b/app/core/gimpchannel-combine.h
@@ -52,5 +52,9 @@ void gimp_channel_combine_buffer (GimpChannel *mask,
gint off_x,
gint off_y);
+void gimp_channel_combine_items (GimpChannel *mask,
+ GList *items,
+ GimpChannelOps op);
+
#endif /* __GIMP_CHANNEL_COMBINE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]