app: s/sprintf/g_snprintf/ in xcf_save_image()
[gimp.git] / libgimpcolor / gimpcolortransform.c
blob2ddc0f65630f61e2c2ec1c08ff836e083156caaf
1 /* LIBGIMP - The GIMP Library
2 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
4 * gimpcolortransform.c
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/>.
24 #include "config.h"
26 #include <string.h>
28 #include <lcms2.h>
30 #include <gio/gio.h>
31 #include <gegl.h>
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"
44 /**
45 * SECTION: gimpcolortransform
46 * @title: GimpColorTransform
47 * @short_description: Definitions and Functions relating to LCMS.
49 * Definitions and Functions relating to LCMS.
50 **/
52 /**
53 * GimpColorTransform:
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
57 * headers.
58 **/
61 enum
63 PROGRESS,
64 LAST_SIGNAL
68 struct _GimpColorTransformPrivate
70 GimpColorProfile *src_profile;
71 const Babl *src_format;
73 GimpColorProfile *dest_profile;
74 const Babl *dest_format;
76 cmsHTRANSFORM transform;
77 const Babl *fish;
81 static void gimp_color_transform_finalize (GObject *object);
84 G_DEFINE_TYPE (GimpColorTransform, gimp_color_transform,
85 G_TYPE_OBJECT);
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;
94 static void
95 lcms_error_clear (void)
97 if (lcms_last_error)
99 g_free (lcms_last_error);
100 lcms_last_error = NULL;
104 static void
105 lcms_error_handler (cmsContext ContextID,
106 cmsUInt32Number ErrorCode,
107 const gchar *text)
109 lcms_error_clear ();
111 lcms_last_error = g_strdup_printf ("lcms2 error %d: %s", ErrorCode, text);
114 static void
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),
124 G_SIGNAL_RUN_FIRST,
125 G_STRUCT_OFFSET (GimpColorTransformClass,
126 progress),
127 NULL, NULL,
128 g_cclosure_marshal_VOID__DOUBLE,
129 G_TYPE_NONE, 1,
130 G_TYPE_DOUBLE);
132 g_type_class_add_private (klass, sizeof (GimpColorTransformPrivate));
134 cmsSetLogErrorHandler (lcms_error_handler);
137 static void
138 gimp_color_transform_init (GimpColorTransform *transform)
140 transform->priv = G_TYPE_INSTANCE_GET_PRIVATE (transform,
141 GIMP_TYPE_COLOR_TRANSFORM,
142 GimpColorTransformPrivate);
145 static void
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.
185 * Since: 2.10
187 GimpColorTransform *
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,
219 src_format,
220 BABL_ICC_INTENT_RELATIVE_COLORIMETRIC,
221 &error);
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,
230 dest_format,
231 rendering_intent,
232 &error);
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,
244 priv->dest_format);
246 g_printerr ("%s: using babl for '%s' -> '%s'\n",
247 G_STRFUNC,
248 gimp_color_profile_get_label (src_profile),
249 gimp_color_profile_get_label (dest_profile));
251 return transform;
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),
259 NULL);
260 dest_format = babl_format_with_space (babl_format_get_encoding (dest_format),
261 NULL);
263 priv->src_format = gimp_color_profile_get_lcms_format (src_format,
264 &lcms_src_format);
265 priv->dest_format = gimp_color_profile_get_lcms_format (dest_format,
266 &lcms_dest_format);
268 src_lcms = gimp_color_profile_get_lcms_profile (src_profile);
269 dest_lcms = gimp_color_profile_get_lcms_profile (dest_profile);
271 lcms_error_clear ();
273 priv->transform = cmsCreateTransform (src_lcms, lcms_src_format,
274 dest_lcms, lcms_dest_format,
275 rendering_intent,
276 flags |
277 cmsFLAGS_COPY_ALPHA);
279 if (lcms_last_error)
281 if (priv->transform)
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);
293 transform = NULL;
296 return 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
313 * between.
315 * Return value: the #GimpColorTransform, or %NULL if there was an error.
317 * Since: 2.10
319 GimpColorTransform *
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
352 * on the formats
354 src_format = babl_format_with_space (babl_format_get_encoding (src_format),
355 NULL);
356 dest_format = babl_format_with_space (babl_format_get_encoding (dest_format),
357 NULL);
359 priv->src_format = gimp_color_profile_get_lcms_format (src_format,
360 &lcms_src_format);
361 priv->dest_format = gimp_color_profile_get_lcms_format (dest_format,
362 &lcms_dest_format);
364 lcms_error_clear ();
366 priv->transform = cmsCreateProofingTransform (src_lcms, lcms_src_format,
367 dest_lcms, lcms_dest_format,
368 proof_lcms,
369 proof_intent,
370 display_intent,
371 flags |
372 cmsFLAGS_SOFTPROOFING |
373 cmsFLAGS_COPY_ALPHA);
375 if (lcms_last_error)
377 if (priv->transform)
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);
389 transform = NULL;
392 return 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.
411 * Since: 2.10
413 void
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,
419 gsize length)
421 GimpColorTransformPrivate *priv;
422 gpointer *src;
423 gpointer *dest;
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.
438 src_format =
439 babl_format_with_space (babl_format_get_encoding (src_format),
440 babl_format_get_space (priv->src_format));
441 dest_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,
450 priv->src_format),
451 src_pixels, src, length);
453 else
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));
462 else
464 dest = dest_pixels;
467 if (priv->transform)
469 cmsDoTransform (priv->transform, src, dest, length);
471 else
473 babl_process (priv->fish, src, dest, length);
476 if (src_format != priv->src_format)
478 g_free (src);
481 if (dest_format != priv->dest_format)
483 babl_process (babl_fish (priv->dest_format,
484 dest_format),
485 dest, dest_pixels, length);
487 g_free (dest);
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.
506 * Since: 2.10
508 void
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;
519 gint total_pixels;
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;
528 if (src_rect)
530 total_pixels = src_rect->width * src_rect->height;
532 else
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);
546 src_format =
547 babl_format_with_space (babl_format_get_encoding (priv->src_format),
548 babl_format_get_space (src_format));
549 dest_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,
556 src_format,
557 GEGL_ACCESS_READ,
558 GEGL_ABYSS_NONE);
560 gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0,
561 dest_format,
562 GEGL_ACCESS_WRITE,
563 GEGL_ABYSS_NONE);
565 while (gegl_buffer_iterator_next (iter))
567 if (priv->transform)
569 cmsDoTransform (priv->transform,
570 iter->data[0], iter->data[1], iter->length);
572 else
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);
585 else
587 iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0,
588 src_format,
589 GEGL_ACCESS_READWRITE,
590 GEGL_ABYSS_NONE);
592 while (gegl_buffer_iterator_next (iter))
594 if (priv->transform)
596 cmsDoTransform (priv->transform,
597 iter->data[0], iter->data[0], iter->length);
599 else
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,
614 1.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.
628 * Since: 2.10
630 gboolean
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))
638 return TRUE;
640 if (gimp_color_profile_get_space (src_profile,
641 GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
642 NULL) &&
643 gimp_color_profile_get_space (dest_profile,
644 GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
645 NULL))
647 return TRUE;
650 return FALSE;