Bug 751553 - Linear precision doesn't display the image correctly

When converting and image with a color profileimage between linear and
gamma, create a new profile using the new API in GimpColorProfile,
convert the layers to that profile and tag the image with the new
profile.

If creating a new profile fails, convert to the right builtin profile
(linear rgb or sRGB from GimpColorProfile), but that code should be
considered a fallback that will be prevented from happening in the
convert dialog (at least the user will be informed).
This commit is contained in:
Michael Natterer
2015-10-20 23:53:47 +02:00
parent 6eb9f9d4aa
commit ecd4752072
2 changed files with 98 additions and 10 deletions

View File

@ -20,15 +20,19 @@
#include "config.h"
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gegl.h>
#include "libgimpcolor/gimpcolor.h"
#include "core-types.h"
#include "gegl/gimp-gegl-utils.h"
#include "gegl/gimp-babl.h"
#include "gimpdrawable.h"
#include "gimpimage.h"
#include "gimpimage-color-profile.h"
#include "gimpimage-convert-precision.h"
#include "gimpimage-undo.h"
#include "gimpimage-undo-push.h"
@ -47,10 +51,13 @@ gimp_image_convert_precision (GimpImage *image,
gint mask_dither_type,
GimpProgress *progress)
{
GList *all_drawables;
GList *list;
const gchar *undo_desc = NULL;
gint nth_drawable, n_drawables;
GimpColorProfile *old_profile;
const Babl *old_format;
const Babl *new_format;
GList *all_drawables;
GList *list;
const gchar *undo_desc = NULL;
gint nth_drawable, n_drawables;
g_return_if_fail (GIMP_IS_IMAGE (image));
g_return_if_fail (precision != gimp_image_get_precision (image));
@ -114,9 +121,14 @@ 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_format = gimp_image_get_layer_format (image, FALSE);
/* Set the new precision */
g_object_set (image, "precision", precision, NULL);
new_format = gimp_image_get_layer_format (image, FALSE);
for (list = all_drawables, nth_drawable = 0;
list;
list = g_list_next (list), nth_drawable++)
@ -134,15 +146,42 @@ gimp_image_convert_precision (GimpImage *image,
precision,
dither_type,
mask_dither_type,
FALSE,
old_profile != NULL,
TRUE);
if (progress)
gimp_progress_set_value (progress,
(gdouble) nth_drawable / (gdouble) n_drawables);
}
g_list_free (all_drawables);
if (old_profile &&
gimp_babl_format_get_linear (old_format) !=
gimp_babl_format_get_linear (new_format))
{
GimpColorProfile *new_profile;
/* the comments in gimp_layer_convert_type() explain the logic
* here
*/
if (gimp_babl_format_get_linear (new_format))
{
new_profile =
gimp_color_profile_new_linear_rgb_from_color_profile (old_profile);
}
else
{
new_profile =
gimp_color_profile_new_srgb_gamma_from_color_profile (old_profile);
}
gimp_image_set_color_profile (image, new_profile, NULL);
if (new_profile)
g_object_unref (new_profile);
}
/* convert the selection mask */
{
GimpChannel *mask = gimp_image_get_mask (image);

View File

@ -33,6 +33,7 @@
#include "config/gimpcoreconfig.h" /* FIXME profile convert config */
#include "gegl/gimp-babl.h"
#include "gegl/gimp-gegl-apply-operation.h"
#include "gegl/gimp-gegl-loops.h"
#include "gegl/gimp-gegl-nodes.h"
@ -46,6 +47,7 @@
#include "gimpimage-undo-push.h"
#include "gimpimage-undo.h"
#include "gimpimage.h"
#include "gimpimage-color-profile.h"
#include "gimplayer-floating-sel.h"
#include "gimplayer.h"
#include "gimplayermask.h"
@ -1103,11 +1105,55 @@ gimp_layer_convert_type (GimpDrawable *drawable,
if (convert_profile)
{
src_profile =
gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (layer));
GimpImage *src_image = gimp_item_get_image (GIMP_ITEM (layer));
dest_profile =
gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (dest_image));
if (src_image != dest_image)
{
src_profile =
gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (layer));
dest_profile =
gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (dest_image));
g_object_ref (dest_profile);
}
else if (gimp_image_get_color_profile (src_image))
{
const Babl *src_format = gimp_drawable_get_format (drawable);
/* 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.
* gimp_image_convert_precision() will use the same profile.
*/
if (gimp_babl_format_get_linear (src_format) !=
gimp_babl_format_get_linear (new_format))
{
src_profile =
gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (layer));
if (gimp_babl_format_get_linear (new_format))
{
dest_profile =
gimp_color_profile_new_linear_rgb_from_color_profile (src_profile);
}
else
{
dest_profile =
gimp_color_profile_new_srgb_gamma_from_color_profile (src_profile);
}
/* if a new profile cannot be be generated, convert to the
* builtin profile, which is better than leaving the user
* with broken colors
*/
if (! dest_profile)
{
dest_profile =
gimp_image_get_builtin_color_profile (dest_image);
g_object_ref (dest_profile);
}
}
}
}
if (src_profile && dest_profile)
@ -1122,6 +1168,9 @@ gimp_layer_convert_type (GimpDrawable *drawable,
gegl_buffer_copy (src_buffer, NULL, GEGL_ABYSS_NONE, dest_buffer, NULL);
}
if (dest_profile)
g_object_unref (dest_profile);
gimp_drawable_set_buffer (drawable, push_undo, NULL, dest_buffer);
g_object_unref (src_buffer);