Commit 8226265b authored by Michael Natterer's avatar Michael Natterer 😴

Issue #1954 - GIMP-2.99 color changes when converting between...

...linear and perceptual precision

Under certain circumstances (e.g. the image has no color profile),
GimpLayer's implementation of GimpDrawable::convert_type() didn't have
enough information to do the right color space conversion.

Intead of messing with stuff like "set profile in between doing a and b",
simply add a "src_profile" parameter to GimpDrawable::convert_type() so
the complete color space conversion information is available without
relying on obscure states that could change in the future.

Make sure all callers pass the right src_profile, particularly in
gimp_image_convert_precision(), which also needed fixing.
parent d9737ba1
......@@ -287,7 +287,7 @@ gimp_edit_paste_get_layer (GimpImage *image,
gimp_drawable_get_base_type (drawable),
gimp_drawable_get_precision (drawable),
TRUE,
NULL,
NULL, NULL,
GEGL_DITHER_NONE, GEGL_DITHER_NONE,
FALSE, NULL);
}
......
......@@ -149,6 +149,7 @@ static void gimp_channel_to_selection (GimpItem *item,
static void gimp_channel_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -584,7 +585,7 @@ gimp_channel_convert (GimpItem *item,
GIMP_GRAY,
gimp_image_get_precision (dest_image),
gimp_drawable_has_alpha (drawable),
NULL,
NULL, NULL,
GEGL_DITHER_NONE, GEGL_DITHER_NONE,
FALSE, NULL);
}
......@@ -954,6 +955,7 @@ static void
gimp_channel_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......
......@@ -169,6 +169,7 @@ static gint64 gimp_drawable_real_estimate_memsize (GimpDrawable *drawable,
static void gimp_drawable_real_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -775,6 +776,7 @@ static void
gimp_drawable_real_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -789,9 +791,9 @@ gimp_drawable_real_convert_type (GimpDrawable *drawable,
gimp_item_get_height (GIMP_ITEM (drawable))),
new_format);
gimp_gegl_buffer_copy (
gimp_drawable_get_buffer (drawable), NULL, GEGL_ABYSS_NONE,
dest_buffer, NULL);
gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable), NULL,
GEGL_ABYSS_NONE,
dest_buffer, NULL);
gimp_drawable_set_buffer (drawable, push_undo, NULL, dest_buffer);
g_object_unref (dest_buffer);
......@@ -1107,6 +1109,7 @@ gimp_drawable_convert_type (GimpDrawable *drawable,
GimpImageBaseType new_base_type,
GimpPrecision new_precision,
gboolean new_has_alpha,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -1124,6 +1127,7 @@ gimp_drawable_convert_type (GimpDrawable *drawable,
new_precision != gimp_drawable_get_precision (drawable) ||
new_has_alpha != gimp_drawable_has_alpha (drawable) ||
dest_profile);
g_return_if_fail (src_profile == NULL || GIMP_IS_COLOR_PROFILE (src_profile));
g_return_if_fail (dest_profile == NULL || GIMP_IS_COLOR_PROFILE (dest_profile));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
......@@ -1154,6 +1158,7 @@ gimp_drawable_convert_type (GimpDrawable *drawable,
GIMP_DRAWABLE_GET_CLASS (drawable)->convert_type (drawable, dest_image,
new_format,
src_profile,
dest_profile,
layer_dither_type,
mask_dither_type,
......
......@@ -64,6 +64,7 @@ struct _GimpDrawableClass
void (* convert_type) (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -147,6 +148,7 @@ void gimp_drawable_convert_type (GimpDrawable *drawable,
GimpImageBaseType new_base_type,
GimpPrecision new_precision,
gboolean new_has_alpha,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......
......@@ -159,6 +159,7 @@ static void gimp_group_layer_transform (GimpLayer *layer,
static void gimp_group_layer_convert_type (GimpLayer *layer,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -995,6 +996,7 @@ static void
gimp_group_layer_convert_type (GimpLayer *layer,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......
......@@ -227,7 +227,7 @@ gimp_group_layer_undo_pop (GimpUndo *undo,
group_layer_undo->prev_type,
group_layer_undo->prev_precision,
group_layer_undo->prev_has_alpha,
NULL,
NULL, NULL,
0, 0,
FALSE, NULL);
......
......@@ -764,6 +764,7 @@ gimp_image_convert_indexed (GimpImage *image,
GimpImageBaseType old_type;
GList *all_layers;
GList *list;
GimpColorProfile *src_profile = NULL;
GimpColorProfile *dest_profile = NULL;
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
......@@ -801,6 +802,8 @@ gimp_image_convert_indexed (GimpImage *image,
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_CONVERT,
C_("undo-type", "Convert Image to Indexed"));
src_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
/* Push the image type to the stack */
gimp_image_undo_push_image_type (image, NULL);
......@@ -1008,6 +1011,7 @@ gimp_image_convert_indexed (GimpImage *image,
GIMP_INDEXED,
gimp_drawable_get_precision (GIMP_DRAWABLE (layer)),
gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)),
src_profile,
dest_profile,
GEGL_DITHER_NONE, GEGL_DITHER_NONE,
TRUE, sub_progress);
......
......@@ -101,7 +101,7 @@ gimp_image_convert_precision (GimpImage *image,
/* Push the image precision to the stack */
gimp_image_undo_push_image_precision (image, NULL);
old_profile = gimp_image_get_color_profile (image);
old_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
old_format = gimp_image_get_layer_format (image, FALSE);
/* Set the new precision */
......@@ -109,49 +109,41 @@ gimp_image_convert_precision (GimpImage *image,
new_format = gimp_image_get_layer_format (image, FALSE);
if (old_profile)
/* we use old_format and new_format just for looking at their
* TRCs, new_format's space might be incorrect, don't use it
* for anything else.
*/
if (gimp_babl_format_get_trc (old_format) !=
gimp_babl_format_get_trc (new_format))
{
/* we use old_format and new_format just for looking at their
* TRCs, new_format's space might be incorrect, don't use it
* for anything else.
/* when converting between linear and non-linear, we create a
* new profile using the original profile's chromacities and
* whitepoint, but a linear/sRGB-gamma TRC.
*/
if (gimp_babl_format_get_trc (old_format) !=
gimp_babl_format_get_trc (new_format))
if (gimp_babl_format_get_trc (new_format) == GIMP_TRC_LINEAR)
{
/* when converting between linear and gamma, we create a new
* profile using the original profile's chromacities and
* whitepoint, but a linear/sRGB-gamma TRC.
*/
if (gimp_babl_format_get_trc (new_format) == GIMP_TRC_LINEAR)
{
new_profile =
gimp_color_profile_new_linear_from_color_profile (old_profile);
}
else
{
new_profile =
gimp_color_profile_new_srgb_trc_from_color_profile (old_profile);
}
new_profile =
gimp_color_profile_new_linear_from_color_profile (old_profile);
}
else
{
new_profile =
gimp_color_profile_new_srgb_trc_from_color_profile (old_profile);
}
/* we always need a profile for convert_type with changing TRC
* on the same image, use the new precision's builtin profile as
* a fallback if the profile couldn't be converted
*/
if (! new_profile)
new_profile = g_object_ref (old_profile);
}
/* we always need a profile for convert_type on the same image, use
* the new precision's builtin profile as a fallback if the image
* didn't have a profile before, or it couldn't be converted
*/
if (! new_profile)
{
GimpImageBaseType base_type = gimp_image_get_base_type (image);
GimpTRCType trc = gimp_babl_trc (precision);
{
GimpImageBaseType base_type = gimp_image_get_base_type (image);
GimpTRCType trc = gimp_babl_trc (precision);
new_profile = gimp_babl_get_builtin_color_profile (base_type,
trc);
g_object_ref (new_profile);
new_profile = gimp_babl_get_builtin_color_profile (base_type,
trc);
g_object_ref (new_profile);
}
}
while ((drawable = gimp_object_queue_pop (queue)))
......@@ -179,7 +171,7 @@ gimp_image_convert_precision (GimpImage *image,
}
else
{
gint dither_type;
GeglDitherMethod dither_type;
if (gimp_item_is_text_layer (GIMP_ITEM (drawable)))
dither_type = text_layer_dither_type;
......@@ -190,6 +182,7 @@ gimp_image_convert_precision (GimpImage *image,
gimp_drawable_get_base_type (drawable),
precision,
gimp_drawable_has_alpha (drawable),
old_profile,
new_profile,
dither_type,
mask_dither_type,
......@@ -197,7 +190,7 @@ gimp_image_convert_precision (GimpImage *image,
}
}
if (new_profile != old_profile)
if (new_profile)
gimp_image_set_color_profile (image, new_profile, NULL);
else
gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (image));
......
......@@ -48,6 +48,7 @@ gimp_image_convert_type (GimpImage *image,
GimpProgress *progress,
GError **error)
{
GimpColorProfile *src_profile;
GimpImageBaseType old_type;
const Babl *new_layer_format;
GimpObjectQueue *queue;
......@@ -107,6 +108,8 @@ gimp_image_convert_type (GimpImage *image,
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_CONVERT,
undo_desc);
src_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
/* Push the image type to the stack */
gimp_image_undo_push_image_type (image, NULL);
......@@ -132,6 +135,7 @@ gimp_image_convert_type (GimpImage *image,
new_type,
gimp_drawable_get_precision (drawable),
gimp_drawable_has_alpha (drawable),
src_profile,
dest_profile,
GEGL_DITHER_NONE, GEGL_DITHER_NONE,
TRUE, progress);
......
......@@ -186,6 +186,7 @@ static gint64 gimp_layer_estimate_memsize (GimpDrawable *drawable,
static void gimp_layer_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -256,6 +257,7 @@ static void gimp_layer_real_transform (GimpLayer *layer,
static void gimp_layer_real_convert_type (GimpLayer *layer,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -981,6 +983,7 @@ gimp_layer_convert (GimpItem *item,
GimpImageBaseType new_base_type;
GimpPrecision old_precision;
GimpPrecision new_precision;
GimpColorProfile *src_profile = NULL;
GimpColorProfile *dest_profile = NULL;
old_base_type = gimp_drawable_get_base_type (drawable);
......@@ -992,14 +995,17 @@ gimp_layer_convert (GimpItem *item,
if (g_type_is_a (old_type, GIMP_TYPE_LAYER) &&
gimp_image_get_is_color_managed (dest_image))
{
GimpColorProfile *src_profile =
src_profile =
gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (item));
dest_profile =
gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (dest_image));
if (gimp_color_profile_is_equal (dest_profile, src_profile))
dest_profile = NULL;
{
src_profile = NULL;
dest_profile = NULL;
}
}
if (old_base_type != new_base_type ||
......@@ -1010,6 +1016,7 @@ gimp_layer_convert (GimpItem *item,
new_base_type,
new_precision,
gimp_drawable_has_alpha (drawable),
src_profile,
dest_profile,
GEGL_DITHER_NONE, GEGL_DITHER_NONE,
FALSE, NULL);
......@@ -1364,6 +1371,7 @@ static void
gimp_layer_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -1422,7 +1430,8 @@ gimp_layer_convert_type (GimpDrawable *drawable,
dest_space);
GIMP_LAYER_GET_CLASS (layer)->convert_type (layer, dest_image, space_format,
dest_profile, layer_dither_type,
src_profile, dest_profile,
layer_dither_type,
mask_dither_type, push_undo,
progress);
......@@ -1435,7 +1444,7 @@ gimp_layer_convert_type (GimpDrawable *drawable,
GIMP_GRAY,
gimp_babl_format_get_precision (new_format),
gimp_drawable_has_alpha (GIMP_DRAWABLE (layer->mask)),
NULL,
NULL, NULL,
layer_dither_type, mask_dither_type,
push_undo, progress);
}
......@@ -1692,6 +1701,7 @@ static void
gimp_layer_real_convert_type (GimpLayer *layer,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -1732,8 +1742,9 @@ gimp_layer_real_convert_type (GimpLayer *layer,
if (dest_profile)
{
GimpColorProfile *src_profile =
gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (layer));
if (! src_profile)
src_profile =
gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (layer));
gimp_gegl_convert_color_profile (src_buffer, NULL, src_profile,
dest_buffer, NULL, dest_profile,
......
......@@ -125,6 +125,7 @@ struct _GimpLayerClass
void (* convert_type) (GimpLayer *layer,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......
......@@ -46,6 +46,7 @@ static gboolean gimp_layer_mask_rename (GimpItem *it
static void gimp_layer_mask_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -158,6 +159,7 @@ static void
gimp_layer_mask_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -169,6 +171,7 @@ gimp_layer_mask_convert_type (GimpDrawable *drawable,
GIMP_DRAWABLE_CLASS (parent_class)->convert_type (drawable, dest_image,
new_format,
src_profile,
dest_profile,
layer_dither_type,
mask_dither_type,
......
......@@ -93,6 +93,7 @@ static gboolean gimp_selection_stroke (GimpItem *item,
static void gimp_selection_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -357,6 +358,7 @@ static void
gimp_selection_convert_type (GimpDrawable *drawable,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -368,6 +370,7 @@ gimp_selection_convert_type (GimpDrawable *drawable,
GIMP_DRAWABLE_CLASS (parent_class)->convert_type (drawable, dest_image,
new_format,
src_profile,
dest_profile,
layer_dither_type,
mask_dither_type,
......
......@@ -108,6 +108,7 @@ static void gimp_text_layer_push_undo (GimpDrawable *drawable,
static void gimp_text_layer_convert_type (GimpLayer *layer,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -389,6 +390,7 @@ static void
gimp_text_layer_convert_type (GimpLayer *layer,
GimpImage *dest_image,
const Babl *new_format,
GimpColorProfile *src_profile,
GimpColorProfile *dest_profile,
GeglDitherMethod layer_dither_type,
GeglDitherMethod mask_dither_type,
......@@ -404,6 +406,7 @@ gimp_text_layer_convert_type (GimpLayer *layer,
{
GIMP_LAYER_CLASS (parent_class)->convert_type (layer, dest_image,
new_format,
src_profile,
dest_profile,
layer_dither_type,
mask_dither_type,
......
......@@ -274,7 +274,7 @@ gimp_text_undo_pop (GimpUndo *undo,
gimp_babl_format_get_base_type (text_undo->format),
gimp_babl_format_get_precision (text_undo->format),
babl_format_has_alpha (text_undo->format),
NULL,
NULL, NULL,
GEGL_DITHER_NONE, GEGL_DITHER_NONE,
FALSE, NULL);
text_undo->format = format;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment