1 /* LIBGIMP - The GIMP Library
2 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
5 * Copyright (C) 2014 Michael Natterer <mitch@gimp.org>
6 * Elle Stone <ellestone@ninedegreesbelow.com>
7 * Øyvind Kolås <pippin@gimp.org>
9 * This library is free software: you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 3 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library. If not, see
21 * <https://www.gnu.org/licenses/>.
33 #include "libgimpbase/gimpbase.h"
34 #include "libgimpconfig/gimpconfig.h"
36 #include "gimpcolortypes.h"
38 #include "gimpcolorprofile.h"
39 #include "gimpcolortransform.h"
41 #include "libgimp/libgimp-intl.h"
45 * SECTION: gimpcolortransform
46 * @title: GimpColorTransform
47 * @short_description: Definitions and Functions relating to LCMS.
49 * Definitions and Functions relating to LCMS.
55 * Simply a typedef to #gpointer, but actually is a cmsHTRANSFORM. It's
56 * used in public GIMP APIs in order to avoid having to include LCMS
68 struct _GimpColorTransformPrivate
70 GimpColorProfile
*src_profile
;
71 const Babl
*src_format
;
73 GimpColorProfile
*dest_profile
;
74 const Babl
*dest_format
;
76 cmsHTRANSFORM transform
;
81 static void gimp_color_transform_finalize (GObject
*object
);
84 G_DEFINE_TYPE (GimpColorTransform
, gimp_color_transform
,
87 #define parent_class gimp_color_transform_parent_class
89 static guint gimp_color_transform_signals
[LAST_SIGNAL
] = { 0 };
91 static gchar
*lcms_last_error
= NULL
;
95 lcms_error_clear (void)
99 g_free (lcms_last_error
);
100 lcms_last_error
= NULL
;
105 lcms_error_handler (cmsContext ContextID
,
106 cmsUInt32Number ErrorCode
,
111 lcms_last_error
= g_strdup_printf ("lcms2 error %d: %s", ErrorCode
, text
);
115 gimp_color_transform_class_init (GimpColorTransformClass
*klass
)
117 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
119 object_class
->finalize
= gimp_color_transform_finalize
;
121 gimp_color_transform_signals
[PROGRESS
] =
122 g_signal_new ("progress",
123 G_OBJECT_CLASS_TYPE (object_class
),
125 G_STRUCT_OFFSET (GimpColorTransformClass
,
128 g_cclosure_marshal_VOID__DOUBLE
,
132 g_type_class_add_private (klass
, sizeof (GimpColorTransformPrivate
));
134 cmsSetLogErrorHandler (lcms_error_handler
);
138 gimp_color_transform_init (GimpColorTransform
*transform
)
140 transform
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (transform
,
141 GIMP_TYPE_COLOR_TRANSFORM
,
142 GimpColorTransformPrivate
);
146 gimp_color_transform_finalize (GObject
*object
)
148 GimpColorTransform
*transform
= GIMP_COLOR_TRANSFORM (object
);
150 g_clear_object (&transform
->priv
->src_profile
);
151 g_clear_object (&transform
->priv
->dest_profile
);
153 g_clear_pointer (&transform
->priv
->transform
, cmsDeleteTransform
);
155 G_OBJECT_CLASS (parent_class
)->finalize (object
);
160 * gimp_color_transform_new:
161 * @src_profile: the source #GimpColorProfile
162 * @src_format: the source #Babl format
163 * @dest_profile: the destination #GimpColorProfile
164 * @dest_format: the destination #Babl format
165 * @rendering_intent: the rendering intent
166 * @flags: transform flags
168 * This function creates an color transform.
170 * The color transform is determined exclusively by @src_profile and
171 * @dest_profile. The color spaces of @src_format and @dest_format are
172 * ignored, the formats are only used to decide between what pixel
173 * encodings to transform.
175 * Note: this function used to return %NULL if
176 * gimp_color_transform_can_gegl_copy() returned %TRUE for
177 * @src_profile and @dest_profile. This is no longer the case because
178 * special care has to be taken not to perform multiple implicit color
179 * transforms caused by babl formats with color spaces. Now, it always
180 * returns a non-%NULL transform and the code takes care of doing only
181 * exactly the requested color transform.
183 * Return value: the #GimpColorTransform, or %NULL if there was an error.
188 gimp_color_transform_new (GimpColorProfile
*src_profile
,
189 const Babl
*src_format
,
190 GimpColorProfile
*dest_profile
,
191 const Babl
*dest_format
,
192 GimpColorRenderingIntent rendering_intent
,
193 GimpColorTransformFlags flags
)
195 GimpColorTransform
*transform
;
196 GimpColorTransformPrivate
*priv
;
197 cmsHPROFILE src_lcms
;
198 cmsHPROFILE dest_lcms
;
199 cmsUInt32Number lcms_src_format
;
200 cmsUInt32Number lcms_dest_format
;
201 GError
*error
= NULL
;
203 g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (src_profile
), NULL
);
204 g_return_val_if_fail (src_format
!= NULL
, NULL
);
205 g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (dest_profile
), NULL
);
206 g_return_val_if_fail (dest_format
!= NULL
, NULL
);
208 transform
= g_object_new (GIMP_TYPE_COLOR_TRANSFORM
, NULL
);
210 priv
= transform
->priv
;
212 /* only src_profile and dest_profile must determine the transform's
213 * color spaces, create formats with src_format's and dest_format's
214 * encoding, and the profiles' color spaces; see process_pixels()
215 * and process_buffer().
218 priv
->src_format
= gimp_color_profile_get_format (src_profile
,
220 BABL_ICC_INTENT_RELATIVE_COLORIMETRIC
,
222 if (! priv
->src_format
)
224 g_printerr ("%s: error making format: %s\n",
225 G_STRFUNC
, error
->message
);
226 g_clear_error (&error
);
229 priv
->dest_format
= gimp_color_profile_get_format (dest_profile
,
233 if (! priv
->dest_format
)
235 g_printerr ("%s: error making format: %s\n",
236 G_STRFUNC
, error
->message
);
237 g_clear_error (&error
);
240 if (! g_getenv ("GIMP_COLOR_TRANSFORM_DISABLE_BABL") &&
241 priv
->src_format
&& priv
->dest_format
)
243 priv
->fish
= babl_fish (priv
->src_format
,
246 g_printerr ("%s: using babl for '%s' -> '%s'\n",
248 gimp_color_profile_get_label (src_profile
),
249 gimp_color_profile_get_label (dest_profile
));
254 /* see above: when using lcms, don't mess with formats with color
255 * spaces, gimp_color_profile_get_lcms_format() might return the
256 * same format and it must be without space
258 src_format
= babl_format_with_space (babl_format_get_encoding (src_format
),
260 dest_format
= babl_format_with_space (babl_format_get_encoding (dest_format
),
263 priv
->src_format
= gimp_color_profile_get_lcms_format (src_format
,
265 priv
->dest_format
= gimp_color_profile_get_lcms_format (dest_format
,
268 src_lcms
= gimp_color_profile_get_lcms_profile (src_profile
);
269 dest_lcms
= gimp_color_profile_get_lcms_profile (dest_profile
);
273 priv
->transform
= cmsCreateTransform (src_lcms
, lcms_src_format
,
274 dest_lcms
, lcms_dest_format
,
277 cmsFLAGS_COPY_ALPHA
);
283 cmsDeleteTransform (priv
->transform
);
284 priv
->transform
= NULL
;
287 g_printerr ("%s: %s\n", G_STRFUNC
, lcms_last_error
);
290 if (! priv
->transform
)
292 g_object_unref (transform
);
300 * gimp_color_transform_new_proofing:
301 * @src_profile: the source #GimpColorProfile
302 * @src_format: the source #Babl format
303 * @dest_profile: the destination #GimpColorProfile
304 * @dest_format: the destination #Babl format
305 * @proof_profile: the proof #GimpColorProfile
306 * @proof_intent: the proof intent
307 * @display_intent: the display intent
308 * @flags: transform flags
310 * This function creates a simulation / proofing color transform.
312 * See gimp_color_transform_new() about the color spaces to transform
315 * Return value: the #GimpColorTransform, or %NULL if there was an error.
320 gimp_color_transform_new_proofing (GimpColorProfile
*src_profile
,
321 const Babl
*src_format
,
322 GimpColorProfile
*dest_profile
,
323 const Babl
*dest_format
,
324 GimpColorProfile
*proof_profile
,
325 GimpColorRenderingIntent proof_intent
,
326 GimpColorRenderingIntent display_intent
,
327 GimpColorTransformFlags flags
)
329 GimpColorTransform
*transform
;
330 GimpColorTransformPrivate
*priv
;
331 cmsHPROFILE src_lcms
;
332 cmsHPROFILE dest_lcms
;
333 cmsHPROFILE proof_lcms
;
334 cmsUInt32Number lcms_src_format
;
335 cmsUInt32Number lcms_dest_format
;
337 g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (src_profile
), NULL
);
338 g_return_val_if_fail (src_format
!= NULL
, NULL
);
339 g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (dest_profile
), NULL
);
340 g_return_val_if_fail (dest_format
!= NULL
, NULL
);
341 g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (proof_profile
), NULL
);
343 transform
= g_object_new (GIMP_TYPE_COLOR_TRANSFORM
, NULL
);
345 priv
= transform
->priv
;
347 src_lcms
= gimp_color_profile_get_lcms_profile (src_profile
);
348 dest_lcms
= gimp_color_profile_get_lcms_profile (dest_profile
);
349 proof_lcms
= gimp_color_profile_get_lcms_profile (proof_profile
);
351 /* see gimp_color_transform_new(), we can't have color spaces
354 src_format
= babl_format_with_space (babl_format_get_encoding (src_format
),
356 dest_format
= babl_format_with_space (babl_format_get_encoding (dest_format
),
359 priv
->src_format
= gimp_color_profile_get_lcms_format (src_format
,
361 priv
->dest_format
= gimp_color_profile_get_lcms_format (dest_format
,
366 priv
->transform
= cmsCreateProofingTransform (src_lcms
, lcms_src_format
,
367 dest_lcms
, lcms_dest_format
,
372 cmsFLAGS_SOFTPROOFING
|
373 cmsFLAGS_COPY_ALPHA
);
379 cmsDeleteTransform (priv
->transform
);
380 priv
->transform
= NULL
;
383 g_printerr ("%s: %s\n", G_STRFUNC
, lcms_last_error
);
386 if (! priv
->transform
)
388 g_object_unref (transform
);
396 * gimp_color_transform_process_pixels:
397 * @transform: a #GimpColorTransform
398 * @src_format: #Babl format of @src_pixels
399 * @src_pixels: pointer to the source pixels
400 * @dest_format: #Babl format of @dest_pixels
401 * @dest_pixels: pointer to the destination pixels
402 * @length: number of pixels to process
404 * This function transforms a contiguous line of pixels.
406 * See gimp_color_transform_new(): only the pixel encoding of
407 * @src_format and @dest_format is honored, their color spaces are
408 * ignored. The transform always takes place between the color spaces
409 * determined by @transform's color profiles.
414 gimp_color_transform_process_pixels (GimpColorTransform
*transform
,
415 const Babl
*src_format
,
416 gconstpointer src_pixels
,
417 const Babl
*dest_format
,
418 gpointer dest_pixels
,
421 GimpColorTransformPrivate
*priv
;
425 g_return_if_fail (GIMP_IS_COLOR_TRANSFORM (transform
));
426 g_return_if_fail (src_format
!= NULL
);
427 g_return_if_fail (src_pixels
!= NULL
);
428 g_return_if_fail (dest_format
!= NULL
);
429 g_return_if_fail (dest_pixels
!= NULL
);
431 priv
= transform
->priv
;
433 /* we must not do any babl color transforms when reading from
434 * src_pixels or writing to dest_pixels, so construct formats with
435 * src_format's and dest_format's encoding, and the transform's
436 * input and output color spaces.
439 babl_format_with_space (babl_format_get_encoding (src_format
),
440 babl_format_get_space (priv
->src_format
));
442 babl_format_with_space (babl_format_get_encoding (dest_format
),
443 babl_format_get_space (priv
->dest_format
));
445 if (src_format
!= priv
->src_format
)
447 src
= g_malloc (length
* babl_format_get_bytes_per_pixel (priv
->src_format
));
449 babl_process (babl_fish (src_format
,
451 src_pixels
, src
, length
);
455 src
= (gpointer
) src_pixels
;
458 if (dest_format
!= priv
->dest_format
)
460 dest
= g_malloc (length
* babl_format_get_bytes_per_pixel (priv
->dest_format
));
469 cmsDoTransform (priv
->transform
, src
, dest
, length
);
473 babl_process (priv
->fish
, src
, dest
, length
);
476 if (src_format
!= priv
->src_format
)
481 if (dest_format
!= priv
->dest_format
)
483 babl_process (babl_fish (priv
->dest_format
,
485 dest
, dest_pixels
, length
);
492 * gimp_color_transform_process_buffer:
493 * @transform: a #GimpColorTransform
494 * @src_buffer: source #GeglBuffer
495 * @src_rect: rectangle in @src_buffer
496 * @dest_buffer: destination #GeglBuffer
497 * @dest_rect: rectangle in @dest_buffer
499 * This function transforms buffer into another buffer.
501 * See gimp_color_transform_new(): only the pixel encoding of
502 * @src_buffer's and @dest_buffer's formats honored, their color
503 * spaces are ignored. The transform always takes place between the
504 * color spaces determined by @transform's color profiles.
509 gimp_color_transform_process_buffer (GimpColorTransform
*transform
,
510 GeglBuffer
*src_buffer
,
511 const GeglRectangle
*src_rect
,
512 GeglBuffer
*dest_buffer
,
513 const GeglRectangle
*dest_rect
)
515 GimpColorTransformPrivate
*priv
;
516 const Babl
*src_format
;
517 const Babl
*dest_format
;
518 GeglBufferIterator
*iter
;
520 gint done_pixels
= 0;
522 g_return_if_fail (GIMP_IS_COLOR_TRANSFORM (transform
));
523 g_return_if_fail (GEGL_IS_BUFFER (src_buffer
));
524 g_return_if_fail (GEGL_IS_BUFFER (dest_buffer
));
526 priv
= transform
->priv
;
530 total_pixels
= src_rect
->width
* src_rect
->height
;
534 total_pixels
= (gegl_buffer_get_width (src_buffer
) *
535 gegl_buffer_get_height (src_buffer
));
538 /* we must not do any babl color transforms when reading from
539 * src_buffer or writing to dest_buffer, so construct formats with
540 * the transform's expected input and output encoding and
541 * src_buffer's and dest_buffers's color spaces.
543 src_format
= gegl_buffer_get_format (src_buffer
);
544 dest_format
= gegl_buffer_get_format (dest_buffer
);
547 babl_format_with_space (babl_format_get_encoding (priv
->src_format
),
548 babl_format_get_space (src_format
));
550 babl_format_with_space (babl_format_get_encoding (priv
->dest_format
),
551 babl_format_get_space (dest_format
));
553 if (src_buffer
!= dest_buffer
)
555 iter
= gegl_buffer_iterator_new (src_buffer
, src_rect
, 0,
560 gegl_buffer_iterator_add (iter
, dest_buffer
, dest_rect
, 0,
565 while (gegl_buffer_iterator_next (iter
))
569 cmsDoTransform (priv
->transform
,
570 iter
->data
[0], iter
->data
[1], iter
->length
);
574 babl_process (priv
->fish
,
575 iter
->data
[0], iter
->data
[1], iter
->length
);
578 done_pixels
+= iter
->roi
[0].width
* iter
->roi
[0].height
;
580 g_signal_emit (transform
, gimp_color_transform_signals
[PROGRESS
], 0,
581 (gdouble
) done_pixels
/
582 (gdouble
) total_pixels
);
587 iter
= gegl_buffer_iterator_new (src_buffer
, src_rect
, 0,
589 GEGL_ACCESS_READWRITE
,
592 while (gegl_buffer_iterator_next (iter
))
596 cmsDoTransform (priv
->transform
,
597 iter
->data
[0], iter
->data
[0], iter
->length
);
601 babl_process (priv
->fish
,
602 iter
->data
[0], iter
->data
[0], iter
->length
);
605 done_pixels
+= iter
->roi
[0].width
* iter
->roi
[0].height
;
607 g_signal_emit (transform
, gimp_color_transform_signals
[PROGRESS
], 0,
608 (gdouble
) done_pixels
/
609 (gdouble
) total_pixels
);
613 g_signal_emit (transform
, gimp_color_transform_signals
[PROGRESS
], 0,
618 * gimp_color_transform_can_gegl_copy:
619 * @src_profile: source #GimpColorProfile
620 * @dest_profile: destination #GimpColorProfile
622 * This function checks if a GimpColorTransform is needed at all.
624 * Return value: %TRUE if pixels can be correctly converted between
625 * @src_profile and @dest_profile by simply using
626 * gegl_buffer_copy(), babl_process() or similar.
631 gimp_color_transform_can_gegl_copy (GimpColorProfile
*src_profile
,
632 GimpColorProfile
*dest_profile
)
634 g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (src_profile
), FALSE
);
635 g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (dest_profile
), FALSE
);
637 if (gimp_color_profile_is_equal (src_profile
, dest_profile
))
640 if (gimp_color_profile_get_space (src_profile
,
641 GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC
,
643 gimp_color_profile_get_space (dest_profile
,
644 GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC
,