Bug 768952 - Select by color works correctly only in srgb

Separate clearing/creating the image's cached color transforms from
clearing/creating its color profile. Clear the transforms when the
color profile changes, and when image type or precision change. Create
the transforms only on demand, so clearing them multiple times doesn't
trigger any redundant (and expensive) transform creations.
This commit is contained in:
Michael Natterer 2016-07-25 00:04:12 +02:00
parent 4ea518fee3
commit f06f691a92
4 changed files with 102 additions and 59 deletions

View File

@ -68,6 +68,8 @@ static void gimp_image_convert_profile_colormap (GimpImage *ima
gboolean bpc, gboolean bpc,
GimpProgress *progress); GimpProgress *progress);
static void gimp_image_create_color_transforms (GimpImage *image);
/* public functions */ /* public functions */
@ -502,6 +504,8 @@ gimp_image_get_color_transform_to_srgb_u8 (GimpImage *image)
private = GIMP_IMAGE_GET_PRIVATE (image); private = GIMP_IMAGE_GET_PRIVATE (image);
gimp_image_create_color_transforms (image);
if (private->is_color_managed) if (private->is_color_managed)
return private->transform_to_srgb_u8; return private->transform_to_srgb_u8;
@ -517,6 +521,8 @@ gimp_image_get_color_transform_from_srgb_u8 (GimpImage *image)
private = GIMP_IMAGE_GET_PRIVATE (image); private = GIMP_IMAGE_GET_PRIVATE (image);
gimp_image_create_color_transforms (image);
if (private->is_color_managed) if (private->is_color_managed)
return private->transform_from_srgb_u8; return private->transform_from_srgb_u8;
@ -532,6 +538,8 @@ gimp_image_get_color_transform_to_srgb_double (GimpImage *image)
private = GIMP_IMAGE_GET_PRIVATE (image); private = GIMP_IMAGE_GET_PRIVATE (image);
gimp_image_create_color_transforms (image);
if (private->is_color_managed) if (private->is_color_managed)
return private->transform_to_srgb_double; return private->transform_to_srgb_double;
@ -547,6 +555,8 @@ gimp_image_get_color_transform_from_srgb_double (GimpImage *image)
private = GIMP_IMAGE_GET_PRIVATE (image); private = GIMP_IMAGE_GET_PRIVATE (image);
gimp_image_create_color_transforms (image);
if (private->is_color_managed) if (private->is_color_managed)
return private->transform_from_srgb_double; return private->transform_from_srgb_double;
@ -559,12 +569,15 @@ gimp_image_color_profile_pixel_to_srgb (GimpImage *image,
gpointer pixel, gpointer pixel,
GimpRGB *color) GimpRGB *color)
{ {
GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); GimpColorTransform *transform;
if (private->is_color_managed && g_return_if_fail (GIMP_IS_IMAGE (image));
private->transform_to_srgb_double)
transform = gimp_image_get_color_transform_to_srgb_double (image);
if (transform)
{ {
gimp_color_transform_process_pixels (private->transform_to_srgb_double, gimp_color_transform_process_pixels (transform,
pixel_format, pixel_format,
pixel, pixel,
babl_format ("R'G'B'A double"), babl_format ("R'G'B'A double"),
@ -583,15 +596,18 @@ gimp_image_color_profile_srgb_to_pixel (GimpImage *image,
const Babl *pixel_format, const Babl *pixel_format,
gpointer pixel) gpointer pixel)
{ {
GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); GimpColorTransform *transform;
if (private->is_color_managed && g_return_if_fail (GIMP_IS_IMAGE (image));
private->transform_from_srgb_double)
transform = gimp_image_get_color_transform_from_srgb_double (image);
if (transform)
{ {
/* for the alpha channel */ /* for the alpha channel */
gimp_rgba_get_pixel (color, pixel_format, pixel); gimp_rgba_get_pixel (color, pixel_format, pixel);
gimp_color_transform_process_pixels (private->transform_from_srgb_double, gimp_color_transform_process_pixels (transform,
babl_format ("R'G'B'A double"), babl_format ("R'G'B'A double"),
color, color,
pixel_format, pixel_format,
@ -618,6 +634,14 @@ _gimp_image_free_color_profile (GimpImage *image)
private->color_profile = NULL; private->color_profile = NULL;
} }
_gimp_image_free_color_transforms (image);
}
void
_gimp_image_free_color_transforms (GimpImage *image)
{
GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
if (private->transform_to_srgb_u8) if (private->transform_to_srgb_u8)
{ {
g_object_unref (private->transform_to_srgb_u8); g_object_unref (private->transform_to_srgb_u8);
@ -641,6 +665,8 @@ _gimp_image_free_color_profile (GimpImage *image)
g_object_unref (private->transform_from_srgb_double); g_object_unref (private->transform_from_srgb_double);
private->transform_from_srgb_double = NULL; private->transform_from_srgb_double = NULL;
} }
private->color_transforms_created = FALSE;
} }
void void
@ -657,51 +683,6 @@ _gimp_image_update_color_profile (GimpImage *image,
gimp_color_profile_new_from_icc_profile (gimp_parasite_data (icc_parasite), gimp_color_profile_new_from_icc_profile (gimp_parasite_data (icc_parasite),
gimp_parasite_data_size (icc_parasite), gimp_parasite_data_size (icc_parasite),
NULL); NULL);
if (private->color_profile)
{
GimpColorProfile *srgb_profile;
GimpColorTransformFlags flags = 0;
srgb_profile = gimp_color_profile_new_rgb_srgb ();
flags |= GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE;
flags |= GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION;
private->transform_to_srgb_u8 =
gimp_color_transform_new (private->color_profile,
gimp_image_get_layer_format (image, TRUE),
srgb_profile,
babl_format ("R'G'B'A u8"),
GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
flags);
private->transform_from_srgb_u8 =
gimp_color_transform_new (srgb_profile,
babl_format ("R'G'B'A u8"),
private->color_profile,
gimp_image_get_layer_format (image, TRUE),
GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
flags);
private->transform_to_srgb_double =
gimp_color_transform_new (private->color_profile,
gimp_image_get_layer_format (image, TRUE),
srgb_profile,
babl_format ("R'G'B'A double"),
GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
flags);
private->transform_from_srgb_double =
gimp_color_transform_new (srgb_profile,
babl_format ("R'G'B'A double"),
private->color_profile,
gimp_image_get_layer_format (image, TRUE),
GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
flags);
g_object_unref (srgb_profile);
}
} }
gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (image)); gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (image));
@ -815,3 +796,59 @@ gimp_image_convert_profile_colormap (GimpImage *image,
g_free (cmap); g_free (cmap);
} }
static void
gimp_image_create_color_transforms (GimpImage *image)
{
GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
if (private->color_profile &&
! private->color_transforms_created)
{
GimpColorProfile *srgb_profile;
GimpColorTransformFlags flags = 0;
g_printerr ("XXXXXX %s XXXXXX\n", G_STRFUNC);
srgb_profile = gimp_color_profile_new_rgb_srgb ();
flags |= GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE;
flags |= GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION;
private->transform_to_srgb_u8 =
gimp_color_transform_new (private->color_profile,
gimp_image_get_layer_format (image, TRUE),
srgb_profile,
babl_format ("R'G'B'A u8"),
GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
flags);
private->transform_from_srgb_u8 =
gimp_color_transform_new (srgb_profile,
babl_format ("R'G'B'A u8"),
private->color_profile,
gimp_image_get_layer_format (image, TRUE),
GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
flags);
private->transform_to_srgb_double =
gimp_color_transform_new (private->color_profile,
gimp_image_get_layer_format (image, TRUE),
srgb_profile,
babl_format ("R'G'B'A double"),
GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
flags);
private->transform_from_srgb_double =
gimp_color_transform_new (srgb_profile,
babl_format ("R'G'B'A double"),
private->color_profile,
gimp_image_get_layer_format (image, TRUE),
GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
flags);
g_object_unref (srgb_profile);
private->color_transforms_created = TRUE;
}
}

View File

@ -105,6 +105,7 @@ void gimp_image_color_profile_srgb_to_pixel
/* internal API, to be called only from gimpimage.c */ /* internal API, to be called only from gimpimage.c */
void _gimp_image_free_color_profile (GimpImage *image); void _gimp_image_free_color_profile (GimpImage *image);
void _gimp_image_free_color_transforms (GimpImage *image);
void _gimp_image_update_color_profile (GimpImage *image, void _gimp_image_update_color_profile (GimpImage *image,
const GimpParasite *icc_parasite); const GimpParasite *icc_parasite);

View File

@ -60,6 +60,7 @@ struct _GimpImagePrivate
GimpColorProfile *color_profile; /* image's color profile */ GimpColorProfile *color_profile; /* image's color profile */
/* Cached color transforms: from layer to sRGB u8 and double, and back */ /* Cached color transforms: from layer to sRGB u8 and double, and back */
gboolean color_transforms_created;
GimpColorTransform *transform_to_srgb_u8; GimpColorTransform *transform_to_srgb_u8;
GimpColorTransform *transform_from_srgb_u8; GimpColorTransform *transform_from_srgb_u8;
GimpColorTransform *transform_to_srgb_double; GimpColorTransform *transform_to_srgb_double;

View File

@ -865,24 +865,24 @@ gimp_image_set_property (GObject *object,
case PROP_GIMP: case PROP_GIMP:
image->gimp = g_value_get_object (value); image->gimp = g_value_get_object (value);
break; break;
case PROP_ID:
g_assert_not_reached ();
break;
case PROP_WIDTH: case PROP_WIDTH:
private->width = g_value_get_int (value); private->width = g_value_get_int (value);
break; break;
case PROP_HEIGHT: case PROP_HEIGHT:
private->height = g_value_get_int (value); private->height = g_value_get_int (value);
break; break;
case PROP_BASE_TYPE: case PROP_BASE_TYPE:
private->base_type = g_value_get_enum (value); private->base_type = g_value_get_enum (value);
_gimp_image_free_color_transforms (image);
break; break;
case PROP_PRECISION: case PROP_PRECISION:
private->precision = g_value_get_enum (value); private->precision = g_value_get_enum (value);
_gimp_image_free_color_transforms (image);
break; break;
case PROP_METADATA:
case PROP_BUFFER:
break;
case PROP_SYMMETRY: case PROP_SYMMETRY:
{ {
GList *iter; GList *iter;
@ -919,6 +919,10 @@ gimp_image_set_property (GObject *object,
NULL); NULL);
} }
break; break;
case PROP_ID:
case PROP_METADATA:
case PROP_BUFFER:
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break; break;