From 37a3d423e99bacb1d146cf59f220589b31b47263 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Wed, 26 Aug 2015 01:06:34 +0200 Subject: [PATCH] Bug 679387 - Add "select pixels with this color" from colormap Add gimp_gegl_index_to_mask() and gimp_channel_select_by_index() and around it actions, callbacks and GUI in the colormap dialog. --- app/actions/colormap-actions.c | 68 +++++++++++++++++++++++++++----- app/actions/colormap-commands.c | 22 +++++++++++ app/actions/colormap-commands.h | 13 +++--- app/core/gimpchannel-select.c | 40 +++++++++++++++++++ app/core/gimpchannel-select.h | 7 ++++ app/gegl/gimp-gegl-loops.c | 37 +++++++++++++++++ app/gegl/gimp-gegl-loops.h | 7 ++++ app/widgets/gimpcolormapeditor.c | 17 ++++++++ app/widgets/gimphelp-ids.h | 4 ++ menus/colormap-menu.xml | 5 +++ 10 files changed, 206 insertions(+), 14 deletions(-) diff --git a/app/actions/colormap-actions.c b/app/actions/colormap-actions.c index b81454843a..5e1f860da5 100644 --- a/app/actions/colormap-actions.c +++ b/app/actions/colormap-actions.c @@ -25,6 +25,7 @@ #include "actions-types.h" #include "core/gimpcontext.h" +#include "core/gimpdrawable.h" #include "core/gimpimage.h" #include "core/gimpimage-colormap.h" @@ -66,6 +67,32 @@ static const GimpEnumActionEntry colormap_add_color_actions[] = GIMP_HELP_INDEXED_PALETTE_ADD } }; +static const GimpEnumActionEntry colormap_to_selection_actions[] = +{ + { "colormap-selection-replace", GIMP_STOCK_SELECTION_REPLACE, + NC_("colormap-action", "_Select this Color"), NULL, + NC_("colormap-action", "Select all pixels with this color"), + GIMP_CHANNEL_OP_REPLACE, FALSE, + GIMP_HELP_INDEXED_PALETTE_SELECTION_REPLACE }, + + { "colormap-selection-add", GIMP_STOCK_SELECTION_ADD, + NC_("colormap-action", "_Add to Selection"), NULL, + NC_("colormap-action", "Add all pixels with this color to the current selection"), + GIMP_CHANNEL_OP_ADD, FALSE, + GIMP_HELP_INDEXED_PALETTE_SELECTION_ADD }, + + { "colormap-selection-subtract", GIMP_STOCK_SELECTION_SUBTRACT, + NC_("colormap-action", "_Subtract from Selection"), NULL, + NC_("colormap-action", "Subtract all pixels with this color from the current selection"), + GIMP_CHANNEL_OP_SUBTRACT, FALSE, + GIMP_HELP_INDEXED_PALETTE_SELECTION_SUBTRACT }, + + { "colormap-selection-intersect", GIMP_STOCK_SELECTION_INTERSECT, + NC_("colormap-action", "_Intersect with Selection"), NULL, + NC_("colormap-action", "Intersect all pixels with this color with the current selection"), + GIMP_CHANNEL_OP_INTERSECT, FALSE, + GIMP_HELP_INDEXED_PALETTE_SELECTION_INTERSECT } +}; void colormap_actions_setup (GimpActionGroup *group) @@ -78,23 +105,36 @@ colormap_actions_setup (GimpActionGroup *group) colormap_add_color_actions, G_N_ELEMENTS (colormap_add_color_actions), G_CALLBACK (colormap_add_color_cmd_callback)); + + gimp_action_group_add_enum_actions (group, "colormap-action", + colormap_to_selection_actions, + G_N_ELEMENTS (colormap_to_selection_actions), + G_CALLBACK (colormap_to_selection_cmd_callback)); } void colormap_actions_update (GimpActionGroup *group, gpointer data) { - GimpImage *image = action_data_get_image (data); - GimpContext *context = action_data_get_context (data); - gboolean indexed = FALSE; - gint num_colors = 0; + GimpImage *image = action_data_get_image (data); + GimpContext *context = action_data_get_context (data); + gboolean indexed = FALSE; + gboolean drawable_indexed = FALSE; + gint num_colors = 0; GimpRGB fg; GimpRGB bg; if (image) { - indexed = (gimp_image_get_base_type (image) == GIMP_INDEXED); - num_colors = gimp_image_get_colormap_size (image); + indexed = (gimp_image_get_base_type (image) == GIMP_INDEXED); + + if (indexed) + { + GimpDrawable *drawable = gimp_image_get_active_drawable (image); + + num_colors = gimp_image_get_colormap_size (image); + drawable_indexed = gimp_drawable_is_indexed (drawable); + } } if (context) @@ -109,15 +149,25 @@ colormap_actions_update (GimpActionGroup *group, gimp_action_group_set_action_color (group, action, color, FALSE); SET_SENSITIVE ("colormap-edit-color", - image && indexed && num_colors > 0); + indexed && num_colors > 0); + SET_SENSITIVE ("colormap-add-color-from-fg", - image && indexed && num_colors < 256); + indexed && num_colors < 256); SET_SENSITIVE ("colormap-add-color-from-bg", - image && indexed && num_colors < 256); + indexed && num_colors < 256); SET_COLOR ("colormap-add-color-from-fg", context ? &fg : NULL); SET_COLOR ("colormap-add-color-from-bg", context ? &bg : NULL); + SET_SENSITIVE ("colormap-selection-replace", + drawable_indexed && num_colors > 0); + SET_SENSITIVE ("colormap-selection-add", + drawable_indexed && num_colors > 0); + SET_SENSITIVE ("colormap-selection-subtract", + drawable_indexed && num_colors > 0); + SET_SENSITIVE ("colormap-selection-intersect", + drawable_indexed && num_colors > 0); + #undef SET_SENSITIVE #undef SET_COLOR } diff --git a/app/actions/colormap-commands.c b/app/actions/colormap-commands.c index 7ac5fa7c24..aeceb575a8 100644 --- a/app/actions/colormap-commands.c +++ b/app/actions/colormap-commands.c @@ -25,6 +25,7 @@ #include "actions-types.h" +#include "core/gimpchannel-select.h" #include "core/gimpcontext.h" #include "core/gimpimage.h" #include "core/gimpimage-colormap.h" @@ -133,6 +134,27 @@ colormap_add_color_cmd_callback (GtkAction *action, } } +void +colormap_to_selection_cmd_callback (GtkAction *action, + gint value, + gpointer data) +{ + GimpColormapEditor *editor; + GimpImage *image; + GimpChannelOps op; + return_if_no_image (image, data); + + editor = GIMP_COLORMAP_EDITOR (data); + + op = (GimpChannelOps) value; + + gimp_channel_select_by_index (gimp_image_get_mask (image), + gimp_image_get_active_drawable (image), + editor->col_index, + op, + FALSE, 0.0, 0.0); +} + /* private functions */ diff --git a/app/actions/colormap-commands.h b/app/actions/colormap-commands.h index b8b529cca0..4cba353d93 100644 --- a/app/actions/colormap-commands.h +++ b/app/actions/colormap-commands.h @@ -19,11 +19,14 @@ #define __COLORMAP_COMMANDS_H__ -void colormap_edit_color_cmd_callback (GtkAction *action, - gpointer data); -void colormap_add_color_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void colormap_edit_color_cmd_callback (GtkAction *action, + gpointer data); +void colormap_add_color_cmd_callback (GtkAction *action, + gint value, + gpointer data); +void colormap_to_selection_cmd_callback (GtkAction *action, + gint value, + gpointer data); #endif /* __COLORMAP_COMMANDS_H__ */ diff --git a/app/core/gimpchannel-select.c b/app/core/gimpchannel-select.c index de9c513341..896f4a9ea6 100644 --- a/app/core/gimpchannel-select.c +++ b/app/core/gimpchannel-select.c @@ -29,6 +29,7 @@ #include "core-types.h" #include "gegl/gimp-gegl-apply-operation.h" +#include "gegl/gimp-gegl-loops.h" #include "gegl/gimp-gegl-mask-combine.h" #include "gimpchannel.h" @@ -579,3 +580,42 @@ gimp_channel_select_by_color (GimpChannel *channel, feather_radius_y); g_object_unref (add_on); } + +void +gimp_channel_select_by_index (GimpChannel *channel, + GimpDrawable *drawable, + gint index, + GimpChannelOps op, + gboolean feather, + gdouble feather_radius_x, + gdouble feather_radius_y) +{ + GeglBuffer *add_on; + gint add_on_x = 0; + gint add_on_y = 0; + + g_return_if_fail (GIMP_IS_CHANNEL (channel)); + g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel))); + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + g_return_if_fail (gimp_drawable_is_indexed (drawable)); + + add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0, + gimp_item_get_width (GIMP_ITEM (drawable)), + gimp_item_get_height (GIMP_ITEM (drawable))), + babl_format ("Y float")); + + gimp_gegl_index_to_mask (gimp_drawable_get_buffer (drawable), NULL, + gimp_drawable_get_format_without_alpha (drawable), + add_on, NULL, + index); + + gimp_item_get_offset (GIMP_ITEM (drawable), &add_on_x, &add_on_y); + + gimp_channel_select_buffer (channel, C_("undo-type", "Select by Indexed Color"), + add_on, add_on_x, add_on_y, + op, + feather, + feather_radius_x, + feather_radius_y); + g_object_unref (add_on); +} diff --git a/app/core/gimpchannel-select.h b/app/core/gimpchannel-select.h index c81f0de5d7..e3353805e4 100644 --- a/app/core/gimpchannel-select.h +++ b/app/core/gimpchannel-select.h @@ -147,6 +147,13 @@ void gimp_channel_select_by_color (GimpChannel *channel, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y); +void gimp_channel_select_by_index (GimpChannel *channel, + GimpDrawable *drawable, + gint index, + GimpChannelOps op, + gboolean feather, + gdouble feather_radius_x, + gdouble feather_radius_y); #endif /* __GIMP_CHANNEL_SELECT_H__ */ diff --git a/app/gegl/gimp-gegl-loops.c b/app/gegl/gimp-gegl-loops.c index 52c535953c..5d6ac18ba9 100644 --- a/app/gegl/gimp-gegl-loops.c +++ b/app/gegl/gimp-gegl-loops.c @@ -624,6 +624,43 @@ gimp_gegl_replace (GeglBuffer *top_buffer, } } +void +gimp_gegl_index_to_mask (GeglBuffer *indexed_buffer, + const GeglRectangle *indexed_rect, + const Babl *indexed_format, + GeglBuffer *mask_buffer, + const GeglRectangle *mask_rect, + gint index) +{ + GeglBufferIterator *iter; + + iter = gegl_buffer_iterator_new (indexed_buffer, indexed_rect, 0, + indexed_format, + GEGL_ACCESS_READ, GEGL_ABYSS_NONE); + + gegl_buffer_iterator_add (iter, mask_buffer, mask_rect, 0, + babl_format ("Y float"), + GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); + + while (gegl_buffer_iterator_next (iter)) + { + const guchar *indexed = iter->data[0]; + gfloat *mask = iter->data[1]; + gint count = iter->length; + + while (count--) + { + if (*indexed == index) + *mask = 1.0; + else + *mask = 0.0; + + indexed++; + mask++; + } + } +} + static gboolean gimp_color_profile_can_gegl_copy (GimpColorProfile *src_profile, GimpColorProfile *dest_profile) diff --git a/app/gegl/gimp-gegl-loops.h b/app/gegl/gimp-gegl-loops.h index 1938af9329..be6a87a6f2 100644 --- a/app/gegl/gimp-gegl-loops.h +++ b/app/gegl/gimp-gegl-loops.h @@ -81,6 +81,13 @@ void gimp_gegl_replace (GeglBuffer *top_buffer, gdouble opacity, const gboolean *affect); +void gimp_gegl_index_to_mask (GeglBuffer *indexed_buffer, + const GeglRectangle *indexed_rect, + const Babl *indexed_format, + GeglBuffer *mask_buffer, + const GeglRectangle *mask_rect, + gint index); + void gimp_gegl_convert_color_profile (GeglBuffer *src_buffer, const GeglRectangle *src_rect, GimpColorProfile *src_profile, diff --git a/app/widgets/gimpcolormapeditor.c b/app/widgets/gimpcolormapeditor.c index 05fb232f35..4c56076e34 100644 --- a/app/widgets/gimpcolormapeditor.c +++ b/app/widgets/gimpcolormapeditor.c @@ -222,9 +222,16 @@ static void gimp_colormap_editor_constructed (GObject *object) { GimpColormapEditor *editor = GIMP_COLORMAP_EDITOR (object); + GdkModifierType extend_mask; + GdkModifierType modify_mask; G_OBJECT_CLASS (parent_class)->constructed (object); + extend_mask = gtk_widget_get_modifier_mask (GTK_WIDGET (object), + GDK_MODIFIER_INTENT_EXTEND_SELECTION); + modify_mask = gtk_widget_get_modifier_mask (GTK_WIDGET (object), + GDK_MODIFIER_INTENT_MODIFY_SELECTION); + gimp_editor_add_action_button (GIMP_EDITOR (editor), "colormap", "colormap-edit-color", NULL); @@ -234,6 +241,16 @@ gimp_colormap_editor_constructed (GObject *object) "colormap-add-color-from-bg", gimp_get_toggle_behavior_mask (), NULL); + + gimp_editor_add_action_button (GIMP_EDITOR (editor), "colormap", + "colormap-selection-replace", + "colormap-selection-add", + extend_mask, + "colormap-selection-subtract", + modify_mask, + "colormap-selection-intersect", + extend_mask | modify_mask, + NULL); } static void diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h index e1fd38af6e..5531b489ab 100644 --- a/app/widgets/gimphelp-ids.h +++ b/app/widgets/gimphelp-ids.h @@ -504,6 +504,10 @@ #define GIMP_HELP_INDEXED_PALETTE_DIALOG "gimp-indexed-palette-dialog" #define GIMP_HELP_INDEXED_PALETTE_EDIT "gimp-indexed-palette-edit" #define GIMP_HELP_INDEXED_PALETTE_ADD "gimp-indexed-palette-add" +#define GIMP_HELP_INDEXED_PALETTE_SELECTION_REPLACE "gimp-indexed-palette-selection-replace" +#define GIMP_HELP_INDEXED_PALETTE_SELECTION_ADD "gimp-indexed-palette-selection-add" +#define GIMP_HELP_INDEXED_PALETTE_SELECTION_SUBTRACT "gimp-indexed-palette-selection-subtract" +#define GIMP_HELP_INDEXED_PALETTE_SELECTION_INTERSECT "gimp-indexed-palette-selection-intersect" #define GIMP_HELP_POINTER_INFO_DIALOG "gimp-pointer-info-dialog" #define GIMP_HELP_POINTER_INFO_SAMPLE_MERGED "gimp-pointer-info-sample-merged" diff --git a/menus/colormap-menu.xml b/menus/colormap-menu.xml index bec068c760..b984bf17ef 100644 --- a/menus/colormap-menu.xml +++ b/menus/colormap-menu.xml @@ -7,5 +7,10 @@ + + + + +