Bug 791519 - Unexpected selection from channel

Make sure a channel -> selection -> channel roundtrip never does any
gamma conversion.

In gimp_channel_duplicate(), make sure a created channel has the
right format, and the right data. Fixes selection -> channel.

When switching off quick mask, call gimp_item_to_selection() instead
if gimp_selection_load(), the latter was implementing a shortcut which
is now wrong.

Remove gimp_selection_load() which is now unused.

Unrelated: also remove gimp_selection_save(), it was an obvious
3-liner used only twice.
This commit is contained in:
Michael Natterer 2018-04-10 02:00:23 +02:00
parent 6effffba93
commit 3f95dc52d3
7 changed files with 68 additions and 67 deletions

View File

@ -386,12 +386,20 @@ void
select_save_cmd_callback (GtkAction *action,
gpointer data)
{
GimpImage *image;
GtkWidget *widget;
GimpImage *image;
GimpChannel *channel;
GtkWidget *widget;
return_if_no_image (image, data);
return_if_no_widget (widget, data);
gimp_selection_save (GIMP_SELECTION (gimp_image_get_mask (image)));
channel = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (gimp_image_get_mask (image)),
GIMP_TYPE_CHANNEL));
/* saved selections are not visible by default */
gimp_item_set_visible (GIMP_ITEM (channel), FALSE, FALSE);
gimp_image_add_channel (image, channel,
GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
gimp_image_flush (image);
gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (image->gimp)),

View File

@ -529,6 +529,38 @@ gimp_channel_duplicate (GimpItem *item,
new_channel->y1 = channel->y1;
new_channel->x2 = channel->x2;
new_channel->y2 = channel->y2;
if (new_type == GIMP_TYPE_CHANNEL)
{
/* 8-bit channel hack: make sure pixels between all sorts
* of channels of an image is always copied without any
* gamma conversion
*/
GimpDrawable *new_drawable = GIMP_DRAWABLE (new_item);
GimpImage *image = gimp_item_get_image (item);
const Babl *format = gimp_image_get_channel_format (image);
if (format != gimp_drawable_get_format (new_drawable))
{
GeglBuffer *new_buffer;
new_buffer =
gegl_buffer_new (GEGL_RECTANGLE (0, 0,
gimp_item_get_width (new_item),
gimp_item_get_height (new_item)),
format);
gegl_buffer_set_format (new_buffer,
gimp_drawable_get_format (new_drawable));
gegl_buffer_copy (gimp_drawable_get_buffer (new_drawable), NULL,
GEGL_ABYSS_NONE,
new_buffer, NULL);
gegl_buffer_set_format (new_buffer, NULL);
gimp_drawable_set_buffer (new_drawable, FALSE, NULL, new_buffer);
g_object_unref (new_buffer);
}
}
}
return new_item;

View File

@ -34,7 +34,6 @@
#include "gimpimage-undo-push.h"
#include "gimplayer.h"
#include "gimplayer-floating-selection.h"
#include "gimpselection.h"
#include "gimp-intl.h"
@ -127,8 +126,9 @@ gimp_image_set_quick_mask_state (GimpImage *image,
gimp_layer_get_floating_sel_drawable (floating_sel) == GIMP_DRAWABLE (mask))
floating_sel_anchor (floating_sel);
gimp_selection_load (GIMP_SELECTION (gimp_image_get_mask (image)),
mask);
gimp_item_to_selection (GIMP_ITEM (mask),
GIMP_CHANNEL_OP_REPLACE,
TRUE, FALSE, 0.0, 0.0);
gimp_image_remove_channel (image, mask, TRUE, NULL);
if (! channel_was_active)

View File

@ -634,59 +634,6 @@ gimp_selection_resume (GimpSelection *selection)
return selection->suspend_count;
}
void
gimp_selection_load (GimpSelection *selection,
GimpChannel *channel)
{
gint width;
gint height;
g_return_if_fail (GIMP_IS_SELECTION (selection));
g_return_if_fail (GIMP_IS_CHANNEL (channel));
width = gimp_item_get_width (GIMP_ITEM (selection));
height = gimp_item_get_height (GIMP_ITEM (selection));
g_return_if_fail (width == gimp_item_get_width (GIMP_ITEM (channel)));
g_return_if_fail (height == gimp_item_get_height (GIMP_ITEM (channel)));
gimp_channel_push_undo (GIMP_CHANNEL (selection),
C_("undo-type", "Channel to Selection"));
/* copy the channel to the mask */
gegl_buffer_copy (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
NULL,
GEGL_ABYSS_NONE,
gimp_drawable_get_buffer (GIMP_DRAWABLE (selection)),
NULL);
GIMP_CHANNEL (selection)->bounds_known = FALSE;
gimp_drawable_update (GIMP_DRAWABLE (selection), 0, 0, -1, -1);
}
GimpChannel *
gimp_selection_save (GimpSelection *selection)
{
GimpImage *image;
GimpChannel *new_channel;
g_return_val_if_fail (GIMP_IS_SELECTION (selection), NULL);
image = gimp_item_get_image (GIMP_ITEM (selection));
new_channel = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (selection),
GIMP_TYPE_CHANNEL));
/* saved selections are not visible by default */
gimp_item_set_visible (GIMP_ITEM (new_channel), FALSE, FALSE);
gimp_image_add_channel (image, new_channel,
GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
return new_channel;
}
GeglBuffer *
gimp_selection_extract (GimpSelection *selection,
GimpPickable *pickable,

View File

@ -54,10 +54,6 @@ GimpChannel * gimp_selection_new (GimpImage *image,
gint gimp_selection_suspend (GimpSelection *selection);
gint gimp_selection_resume (GimpSelection *selection);
void gimp_selection_load (GimpSelection *selection,
GimpChannel *channel);
GimpChannel * gimp_selection_save (GimpSelection *selection);
GeglBuffer * gimp_selection_extract (GimpSelection *selection,
GimpPickable *pickable,
GimpContext *context,

View File

@ -516,9 +516,18 @@ selection_save_invoker (GimpProcedure *procedure,
if (success)
{
channel = gimp_selection_save (GIMP_SELECTION (gimp_image_get_mask (image)));
channel = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (gimp_image_get_mask (image)),
GIMP_TYPE_CHANNEL));
if (! channel)
if (channel)
{
/* saved selections are not visible by default */
gimp_item_set_visible (GIMP_ITEM (channel), FALSE, FALSE);
gimp_image_add_channel (image, channel,
GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
}
else
success = FALSE;
}

View File

@ -547,9 +547,18 @@ HELP
headers => [qw("core/gimpselection.h") ],
code => <<'CODE'
{
channel = gimp_selection_save (GIMP_SELECTION (gimp_image_get_mask (image)));
channel = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (gimp_image_get_mask (image)),
GIMP_TYPE_CHANNEL));
if (! channel)
if (channel)
{
/* saved selections are not visible by default */
gimp_item_set_visible (GIMP_ITEM (channel), FALSE, FALSE);
gimp_image_add_channel (image, channel,
GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
}
else
success = FALSE;
}
CODE