[gimp] libgimpcolor: add new object GimpColorTransform



commit cc928879084a16d000366b8d8afe0f18a1aea2b3
Author: Michael Natterer <mitch gimp org>
Date:   Wed May 25 21:35:54 2016 +0200

    libgimpcolor: add new object GimpColorTransform
    
    which encapsulates a cmsHTRANSFORM and does all the pixel format
    conversion magic. It has API to create transforms and proofing
    transforms, and to convert pixels arrays and GeglBuffers.
    
    Before, each place which has a transform had to keep around the
    transform and its input and output Babl formats, and had to implement
    lots of stuff itself. Now all that lives in GimpColorTransform,
    removing lots of logic from many places, and pretty much removing lcms
    from the public API entirely.
    
    This removes including <lcms2.h>, LCMS_LIBS and LCMS_CFLAGS from
    almost all directories and potentially allows to replace lcms by
    something else.

 app/core/gimpdrawable-preview.c                |   26 +-
 app/core/gimpimage-color-profile.c             |  240 ++++----------
 app/core/gimpimage-color-profile.h             |   24 +-
 app/core/gimpimage-preview.c                   |   26 +-
 app/core/gimpimage-private.h                   |   13 +-
 app/display/gimpdisplayshell-profile.c         |   45 +--
 app/display/gimpdisplayshell-render.c          |    6 +-
 app/display/gimpdisplayshell.h                 |   11 +-
 app/gegl/gimp-gegl-loops.c                     |  101 +-----
 app/gegl/gimp-gegl-loops.h                     |   10 -
 app/operations/gimpoperationprofiletransform.c |   33 +--
 app/operations/gimpoperationprofiletransform.h |    2 +-
 app/widgets/gimpviewrenderer.c                 |   52 +--
 libgimpcolor/Makefile.am                       |    3 +
 libgimpcolor/gimpcolor.def                     |    5 +
 libgimpcolor/gimpcolor.h                       |    1 +
 libgimpcolor/gimpcolortransform.c              |  417 ++++++++++++++++++++++++
 libgimpcolor/gimpcolortransform.h              |  105 ++++++
 libgimpcolor/gimpcolortypes.h                  |    8 +-
 libgimpwidgets/gimpcolorarea.c                 |   24 +-
 libgimpwidgets/gimppreviewarea.c               |   26 +-
 libgimpwidgets/gimpwidgetsutils.c              |   49 +--
 libgimpwidgets/gimpwidgetsutils.h              |    6 +-
 modules/display-filter-lcms.c                  |   44 +--
 24 files changed, 759 insertions(+), 518 deletions(-)
---
diff --git a/app/core/gimpdrawable-preview.c b/app/core/gimpdrawable-preview.c
index 6e1ce74..3e93488 100644
--- a/app/core/gimpdrawable-preview.c
+++ b/app/core/gimpdrawable-preview.c
@@ -192,9 +192,7 @@ gimp_drawable_get_sub_pixbuf (GimpDrawable *drawable,
   gdouble             scale;
   gint                scaled_x;
   gint                scaled_y;
-  GimpColorTransform  transform;
-  const Babl         *src_format;
-  const Babl         *dest_format;
+  GimpColorTransform *transform;
 
   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
   g_return_val_if_fail (src_x >= 0, NULL);
@@ -225,9 +223,7 @@ gimp_drawable_get_sub_pixbuf (GimpDrawable *drawable,
   scaled_x = RINT ((gdouble) src_x * scale);
   scaled_y = RINT ((gdouble) src_y * scale);
 
-  transform = gimp_image_get_color_transform_to_srgb_u8 (image,
-                                                         &src_format,
-                                                         &dest_format);
+  transform = gimp_image_get_color_transform_to_srgb_u8 (image);
 
   if (transform)
     {
@@ -235,7 +231,8 @@ gimp_drawable_get_sub_pixbuf (GimpDrawable *drawable,
       GeglBuffer  *src_buf;
       GeglBuffer  *dest_buf;
 
-      temp_buf = gimp_temp_buf_new (dest_width, dest_height, src_format);
+      temp_buf = gimp_temp_buf_new (dest_width, dest_height,
+                                    gimp_drawable_get_format (drawable));
 
       gegl_buffer_get (buffer,
                        GEGL_RECTANGLE (scaled_x, scaled_y,
@@ -250,15 +247,12 @@ gimp_drawable_get_sub_pixbuf (GimpDrawable *drawable,
 
       gimp_temp_buf_unref (temp_buf);
 
-      gimp_gegl_convert_color_transform (src_buf,
-                                         GEGL_RECTANGLE (0, 0,
-                                                         dest_width, dest_height),
-                                         src_format,
-                                         dest_buf,
-                                         GEGL_RECTANGLE (0, 0, 0, 0),
-                                         dest_format,
-                                         transform,
-                                         NULL);
+      gimp_color_transform_process_buffer (transform,
+                                           src_buf,
+                                           GEGL_RECTANGLE (0, 0,
+                                                           dest_width, dest_height),
+                                           dest_buf,
+                                           GEGL_RECTANGLE (0, 0, 0, 0));
 
       g_object_unref (src_buf);
       g_object_unref (dest_buf);
diff --git a/app/core/gimpimage-color-profile.c b/app/core/gimpimage-color-profile.c
index 41791a6..5c4ffc2 100644
--- a/app/core/gimpimage-color-profile.c
+++ b/app/core/gimpimage-color-profile.c
@@ -497,110 +497,62 @@ gimp_image_import_color_profile (GimpImage    *image,
     }
 }
 
-GimpColorTransform
-gimp_image_get_color_transform_to_srgb_u8 (GimpImage   *image,
-                                           const Babl **pixel_format,
-                                           const Babl **srgb_u8_format)
+GimpColorTransform *
+gimp_image_get_color_transform_to_srgb_u8 (GimpImage *image)
 {
   GimpImagePrivate *private;
 
   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
-  g_return_val_if_fail (pixel_format != NULL, NULL);
-  g_return_val_if_fail (srgb_u8_format != NULL, NULL);
 
   private = GIMP_IMAGE_GET_PRIVATE (image);
 
   if (private->is_color_managed)
-    {
-      *pixel_format   = private->transform_layer_format;
-      *srgb_u8_format = private->transform_srgb_u8_format;
-
-      return private->transform_to_srgb_u8;
-    }
-
-  *pixel_format   = NULL;
-  *srgb_u8_format = NULL;
+    return private->transform_to_srgb_u8;
 
   return NULL;
 }
 
-GimpColorTransform
-gimp_image_get_color_transform_from_srgb_u8 (GimpImage   *image,
-                                             const Babl **pixel_format,
-                                             const Babl **srgb_u8_format)
+GimpColorTransform *
+gimp_image_get_color_transform_from_srgb_u8 (GimpImage *image)
 {
   GimpImagePrivate *private;
 
   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
-  g_return_val_if_fail (pixel_format != NULL, NULL);
-  g_return_val_if_fail (srgb_u8_format != NULL, NULL);
 
   private = GIMP_IMAGE_GET_PRIVATE (image);
 
   if (private->is_color_managed)
-    {
-      *pixel_format   = private->transform_layer_format;
-      *srgb_u8_format = private->transform_srgb_u8_format;
-
-      return private->transform_from_srgb_u8;
-    }
-
-  *pixel_format   = NULL;
-  *srgb_u8_format = NULL;
+    return private->transform_from_srgb_u8;
 
   return NULL;
 }
 
-GimpColorTransform
-gimp_image_get_color_transform_to_srgb_double (GimpImage   *image,
-                                               const Babl **pixel_format,
-                                               const Babl **srgb_double_format)
+GimpColorTransform *
+gimp_image_get_color_transform_to_srgb_double (GimpImage *image)
 {
   GimpImagePrivate *private;
 
   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
-  g_return_val_if_fail (pixel_format != NULL, NULL);
-  g_return_val_if_fail (srgb_double_format != NULL, NULL);
 
   private = GIMP_IMAGE_GET_PRIVATE (image);
 
   if (private->is_color_managed)
-    {
-      *pixel_format       = private->transform_layer_format;
-      *srgb_double_format = private->transform_srgb_double_format;
-
-      return private->transform_to_srgb_double;
-    }
-
-  *pixel_format       = NULL;
-  *srgb_double_format = NULL;
+    return private->transform_to_srgb_double;
 
   return NULL;
 }
 
-GimpColorTransform
-gimp_image_get_color_transform_from_srgb_double (GimpImage   *image,
-                                                 const Babl **pixel_format,
-                                                 const Babl **srgb_double_format)
+GimpColorTransform *
+gimp_image_get_color_transform_from_srgb_double (GimpImage *image)
 {
   GimpImagePrivate *private;
 
   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
-  g_return_val_if_fail (pixel_format != NULL, NULL);
-  g_return_val_if_fail (srgb_double_format != NULL, NULL);
 
   private = GIMP_IMAGE_GET_PRIVATE (image);
 
   if (private->is_color_managed)
-    {
-      *pixel_format       = private->transform_layer_format;
-      *srgb_double_format = private->transform_srgb_double_format;
-
-      return private->transform_from_srgb_double;
-    }
-
-  *pixel_format       = NULL;
-  *srgb_double_format = NULL;
+    return private->transform_from_srgb_double;
 
   return NULL;
 }
@@ -616,30 +568,12 @@ gimp_image_color_profile_pixel_to_srgb (GimpImage  *image,
   if (private->is_color_managed &&
       private->transform_to_srgb_double)
     {
-      guchar srgb_pixel[32];
-
-      /* for the alpha channel */
-      gimp_rgba_set_pixel (color, pixel_format, pixel);
-
-      if (pixel_format == private->transform_layer_format)
-        {
-          cmsDoTransform (private->transform_to_srgb_double,
-                          pixel, srgb_pixel, 1);
-        }
-      else
-        {
-          guchar src_pixel[32];
-
-          babl_process (babl_fish (pixel_format,
-                                   private->transform_layer_format),
-                        pixel, src_pixel, 1);
-
-          cmsDoTransform (private->transform_to_srgb_double,
-                          src_pixel, srgb_pixel, 1);
-        }
-
-      gimp_rgb_set_pixel (color, private->transform_srgb_double_format,
-                          srgb_pixel);
+      gimp_color_transform_process_pixels (private->transform_to_srgb_double,
+                                           pixel_format,
+                                           pixel,
+                                           babl_format ("R'G'B'A double"),
+                                           color,
+                                           1);
     }
   else
     {
@@ -658,34 +592,15 @@ gimp_image_color_profile_srgb_to_pixel (GimpImage     *image,
   if (private->is_color_managed &&
       private->transform_from_srgb_double)
     {
-      guchar srgb_pixel[32];
-
-      gimp_rgb_get_pixel (color, private->transform_srgb_double_format,
-                          srgb_pixel);
-
-      if (pixel_format == private->transform_layer_format)
-        {
-          /* for the alpha channel */
-          gimp_rgba_get_pixel (color, pixel_format, pixel);
-
-          cmsDoTransform (private->transform_from_srgb_double,
-                          srgb_pixel, pixel, 1);
-        }
-      else
-        {
-          guchar dest_pixel[32];
-
-          /* for the alpha channel */
-          gimp_rgba_get_pixel (color, private->transform_layer_format,
-                               dest_pixel);
-
-          cmsDoTransform (private->transform_from_srgb_double,
-                          srgb_pixel, dest_pixel, 1);
+      /* for the alpha channel */
+      gimp_rgba_get_pixel (color, pixel_format, pixel);
 
-          babl_process (babl_fish (private->transform_layer_format,
-                                   pixel_format),
-                        dest_pixel, pixel, 1);
-        }
+      gimp_color_transform_process_pixels (private->transform_from_srgb_double,
+                                           babl_format ("R'G'B'A double"),
+                                           color,
+                                           pixel_format,
+                                           pixel,
+                                           1);
     }
   else
     {
@@ -709,31 +624,27 @@ _gimp_image_free_color_profile (GimpImage *image)
 
   if (private->transform_to_srgb_u8)
     {
-      cmsDeleteTransform (private->transform_to_srgb_u8);
+      g_object_unref (private->transform_to_srgb_u8);
       private->transform_to_srgb_u8 = NULL;
     }
 
   if (private->transform_from_srgb_u8)
     {
-      cmsDeleteTransform (private->transform_from_srgb_u8);
+      g_object_unref (private->transform_from_srgb_u8);
       private->transform_from_srgb_u8 = NULL;
     }
 
   if (private->transform_to_srgb_double)
     {
-      cmsDeleteTransform (private->transform_to_srgb_double);
+      g_object_unref (private->transform_to_srgb_double);
       private->transform_to_srgb_double = NULL;
     }
 
   if (private->transform_from_srgb_double)
     {
-      cmsDeleteTransform (private->transform_from_srgb_double);
+      g_object_unref (private->transform_from_srgb_double);
       private->transform_from_srgb_double = NULL;
     }
-
-  private->transform_layer_format       = NULL;
-  private->transform_srgb_u8_format     = NULL;
-  private->transform_srgb_double_format = NULL;
 }
 
 void
@@ -754,61 +665,44 @@ _gimp_image_update_color_profile (GimpImage          *image,
       if (private->color_profile)
         {
           GimpColorProfile *srgb_profile;
-          cmsHPROFILE       image_lcms;
-          cmsHPROFILE       srgb_lcms;
-          cmsUInt32Number   image_lcms_format;
-          cmsUInt32Number   srgb_u8_lcms_format;
-          cmsUInt32Number   srgb_double_lcms_format;
           cmsUInt32Number   flags;
 
           srgb_profile = gimp_color_profile_new_rgb_srgb ();
 
-          image_lcms = gimp_color_profile_get_lcms_profile (private->color_profile);
-          srgb_lcms  = gimp_color_profile_get_lcms_profile (srgb_profile);
-
-          private->transform_layer_format = gimp_image_get_layer_format (image,
-                                                                         TRUE);
-          private->transform_srgb_u8_format     = babl_format ("R'G'B'A u8");
-          private->transform_srgb_double_format = babl_format ("R'G'B'A double");
-
-          private->transform_layer_format =
-            gimp_color_profile_get_format (private->transform_layer_format,
-                                           &image_lcms_format);
-
-          private->transform_srgb_u8_format =
-            gimp_color_profile_get_format (private->transform_srgb_u8_format,
-                                           &srgb_u8_lcms_format);
-
-          private->transform_srgb_double_format =
-            gimp_color_profile_get_format (private->transform_srgb_double_format,
-                                           &srgb_double_lcms_format);
-
           flags = cmsFLAGS_NOOPTIMIZE;
           flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
 
           private->transform_to_srgb_u8 =
-            cmsCreateTransform (image_lcms, image_lcms_format,
-                                srgb_lcms,  srgb_u8_lcms_format,
-                                GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
-                                flags);
+            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 =
-            cmsCreateTransform (srgb_lcms,  srgb_u8_lcms_format,
-                                image_lcms, image_lcms_format,
-                                GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
-                                flags);
+            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 =
-            cmsCreateTransform (image_lcms, image_lcms_format,
-                                srgb_lcms,  srgb_double_lcms_format,
-                                GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
-                                flags);
+            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 =
-            cmsCreateTransform (srgb_lcms,  srgb_double_lcms_format,
-                                image_lcms, image_lcms_format,
-                                GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
-                                flags);
+            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);
         }
@@ -891,28 +785,28 @@ gimp_image_convert_profile_colormap (GimpImage                *image,
                                      gboolean                  bpc,
                                      GimpProgress             *progress)
 {
-  cmsHPROFILE         src_lcms;
-  cmsHPROFILE         dest_lcms;
+  GimpColorTransform *transform;
   guchar             *cmap;
   gint                n_colors;
-  GimpColorTransform  transform;
-
-  src_lcms  = gimp_color_profile_get_lcms_profile (src_profile);
-  dest_lcms = gimp_color_profile_get_lcms_profile (dest_profile);
 
   n_colors = gimp_image_get_colormap_size (image);
   cmap     = g_memdup (gimp_image_get_colormap (image), n_colors * 3);
 
-  transform = cmsCreateTransform (src_lcms,  TYPE_RGB_8,
-                                  dest_lcms, TYPE_RGB_8,
-                                  intent,
-                                  cmsFLAGS_NOOPTIMIZE |
-                                  (bpc ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0));
+  transform = gimp_color_transform_new (src_profile,
+                                        babl_format ("R'G'B' u8"),
+                                        dest_profile,
+                                        babl_format ("R'G'B' u8"),
+                                        intent,
+                                        cmsFLAGS_NOOPTIMIZE |
+                                        (bpc ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0));
 
   if (transform)
     {
-      cmsDoTransform (transform, cmap, cmap, n_colors);
-      cmsDeleteTransform (transform);
+      gimp_color_transform_process_pixels (transform,
+                                           babl_format ("R'G'B' u8"), cmap,
+                                           babl_format ("R'G'B' u8"), cmap,
+                                           n_colors);
+      g_object_unref (transform);
 
       gimp_image_set_colormap (image, cmap, n_colors, TRUE);
     }
diff --git a/app/core/gimpimage-color-profile.h b/app/core/gimpimage-color-profile.h
index 8698c36..f076770 100644
--- a/app/core/gimpimage-color-profile.h
+++ b/app/core/gimpimage-color-profile.h
@@ -80,23 +80,15 @@ void                 gimp_image_import_color_profile   (GimpImage           *ima
                                                         GimpProgress        *progress,
                                                         gboolean             interactive);
 
-GimpColorTransform   gimp_image_get_color_transform_to_srgb_u8
-                                                       (GimpImage           *image,
-                                                        const Babl         **pixel_format,
-                                                        const Babl         **srgb_u8_format);
-GimpColorTransform   gimp_image_get_color_transform_from_srgb_u8
-                                                       (GimpImage           *image,
-                                                        const Babl         **pixel_format,
-                                                        const Babl         **srgb_u8_format);
+GimpColorTransform * gimp_image_get_color_transform_to_srgb_u8
+                                                       (GimpImage           *image);
+GimpColorTransform * gimp_image_get_color_transform_from_srgb_u8
+                                                       (GimpImage           *image);
 
-GimpColorTransform   gimp_image_get_color_transform_to_srgb_double
-                                                       (GimpImage           *image,
-                                                        const Babl         **pixel_format,
-                                                        const Babl         **srgb_double_format);
-GimpColorTransform   gimp_image_get_color_transform_from_srgb_double
-                                                       (GimpImage           *image,
-                                                        const Babl         **pixel_format,
-                                                        const Babl         **srgb_double_format);
+GimpColorTransform * gimp_image_get_color_transform_to_srgb_double
+                                                       (GimpImage           *image);
+GimpColorTransform * gimp_image_get_color_transform_from_srgb_double
+                                                       (GimpImage           *image);
 
 void                 gimp_image_color_profile_pixel_to_srgb
                                                        (GimpImage           *image,
diff --git a/app/core/gimpimage-preview.c b/app/core/gimpimage-preview.c
index 374ce9c..b64d74d 100644
--- a/app/core/gimpimage-preview.c
+++ b/app/core/gimpimage-preview.c
@@ -145,9 +145,7 @@ gimp_image_get_new_pixbuf (GimpViewable *viewable,
   GdkPixbuf          *pixbuf;
   gdouble             scale_x;
   gdouble             scale_y;
-  GimpColorTransform  transform;
-  const Babl         *src_format;
-  const Babl         *dest_format;
+  GimpColorTransform *transform;
 
   scale_x = (gdouble) width  / (gdouble) gimp_image_get_width  (image);
   scale_y = (gdouble) height / (gdouble) gimp_image_get_height (image);
@@ -155,9 +153,7 @@ gimp_image_get_new_pixbuf (GimpViewable *viewable,
   pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
                            width, height);
 
-  transform = gimp_image_get_color_transform_to_srgb_u8 (image,
-                                                         &src_format,
-                                                         &dest_format);
+  transform = gimp_image_get_color_transform_to_srgb_u8 (image);
 
   if (transform)
     {
@@ -165,7 +161,8 @@ gimp_image_get_new_pixbuf (GimpViewable *viewable,
       GeglBuffer  *src_buf;
       GeglBuffer  *dest_buf;
 
-      temp_buf = gimp_temp_buf_new (width, height, src_format);
+      temp_buf = gimp_temp_buf_new (width, height,
+                                    gimp_pickable_get_format (GIMP_PICKABLE (image)));
 
       gegl_buffer_get (gimp_pickable_get_buffer (GIMP_PICKABLE (image)),
                        GEGL_RECTANGLE (0, 0, width, height),
@@ -179,15 +176,12 @@ gimp_image_get_new_pixbuf (GimpViewable *viewable,
 
       gimp_temp_buf_unref (temp_buf);
 
-      gimp_gegl_convert_color_transform (src_buf,
-                                         GEGL_RECTANGLE (0, 0,
-                                                         width, height),
-                                         src_format,
-                                         dest_buf,
-                                         GEGL_RECTANGLE (0, 0, 0, 0),
-                                         dest_format,
-                                         transform,
-                                         NULL);
+      gimp_color_transform_process_buffer (transform,
+                                           src_buf,
+                                           GEGL_RECTANGLE (0, 0,
+                                                           width, height),
+                                           dest_buf,
+                                           GEGL_RECTANGLE (0, 0, 0, 0));
 
       g_object_unref (src_buf);
       g_object_unref (dest_buf);
diff --git a/app/core/gimpimage-private.h b/app/core/gimpimage-private.h
index 0a5d468..14123d6 100644
--- a/app/core/gimpimage-private.h
+++ b/app/core/gimpimage-private.h
@@ -60,15 +60,10 @@ struct _GimpImagePrivate
   GimpColorProfile  *color_profile;         /*  image's color profile        */
 
   /*  Cached color transforms: from layer to sRGB u8 and double, and back    */
-  GimpColorTransform transform_to_srgb_u8;
-  GimpColorTransform transform_from_srgb_u8;
-  GimpColorTransform transform_to_srgb_double;
-  GimpColorTransform transform_from_srgb_double;
-
-  /*  Babl formats for above transforms: layer, sRGB u8, sRGB double         */
-  const Babl        *transform_layer_format;
-  const Babl        *transform_srgb_u8_format;
-  const Babl        *transform_srgb_double_format;
+  GimpColorTransform *transform_to_srgb_u8;
+  GimpColorTransform *transform_from_srgb_u8;
+  GimpColorTransform *transform_to_srgb_double;
+  GimpColorTransform *transform_from_srgb_double;
 
   GimpMetadata      *metadata;              /*  image's metadata             */
 
diff --git a/app/display/gimpdisplayshell-profile.c b/app/display/gimpdisplayshell-profile.c
index a2c9599..7128d25 100644
--- a/app/display/gimpdisplayshell-profile.c
+++ b/app/display/gimpdisplayshell-profile.c
@@ -129,17 +129,14 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
     gimp_widget_get_color_transform (gtk_widget_get_toplevel (GTK_WIDGET (shell)),
                                      gimp_display_shell_get_color_config (shell),
                                      src_profile,
-                                     &src_format,
-                                     &dest_format);
+                                     src_format,
+                                     dest_format);
 
   if (shell->profile_transform)
     {
       gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH  * GIMP_DISPLAY_RENDER_MAX_SCALE;
       gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;
 
-      shell->profile_src_format  = src_format;
-      shell->profile_dest_format = dest_format;
-
       shell->profile_data =
         gegl_malloc (w * h * babl_format_get_bytes_per_pixel (src_format));
 
@@ -192,34 +189,10 @@ gimp_display_shell_profile_convert_buffer (GimpDisplayShell *shell,
                                            GeglBuffer       *dest_buffer,
                                            GeglRectangle    *dest_area)
 {
-  GeglBufferIterator *iter;
-  const Babl         *fish;
-
-  if (! shell->profile_transform)
-    return;
-
-  iter = gegl_buffer_iterator_new (src_buffer, src_area, 0,
-                                   shell->profile_src_format,
-                                   GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
-
-  gegl_buffer_iterator_add (iter, dest_buffer, dest_area, 0,
-                            shell->profile_dest_format,
-                            GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
-
-  fish = babl_fish (shell->profile_src_format,
-                    shell->profile_dest_format);
-
-  while (gegl_buffer_iterator_next (iter))
-    {
-      gpointer src_data  = iter->data[0];
-      gpointer dest_data = iter->data[1];
-
-      babl_process (fish, src_data, dest_data, iter->length);
-
-      cmsDoTransform (shell->profile_transform,
-                      src_data, dest_data,
-                      iter->length);
-    }
+  if (shell->profile_transform)
+    gimp_color_transform_process_buffer (shell->profile_transform,
+                                         src_buffer,  src_area,
+                                         dest_buffer, dest_area);
 }
 
 
@@ -230,10 +203,8 @@ gimp_display_shell_profile_free (GimpDisplayShell *shell)
 {
   if (shell->profile_transform)
     {
-      cmsDeleteTransform (shell->profile_transform);
-      shell->profile_transform   = NULL;
-      shell->profile_src_format  = NULL;
-      shell->profile_dest_format = NULL;
+      g_object_unref (shell->profile_transform);
+      shell->profile_transform = NULL;
     }
 
   if (shell->profile_buffer)
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index e39ec8d..65f432a 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -33,9 +33,7 @@
 #include "core/gimpdrawable.h"
 #include "core/gimpimage.h"
 #include "core/gimppickable.h"
-#ifdef USE_NODE_BLIT
 #include "core/gimpprojectable.h"
-#endif
 
 #include "gimpdisplay.h"
 #include "gimpdisplayshell.h"
@@ -204,7 +202,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
                            GEGL_RECTANGLE (scaled_x, scaled_y,
                                            scaled_width, scaled_height),
                            buffer_scale,
-                           shell->profile_src_format,
+                           gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
                            shell->profile_data, shell->profile_stride,
                            GEGL_ABYSS_CLAMP);
 #else
@@ -212,7 +210,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
                           buffer_scale,
                           GEGL_RECTANGLE (scaled_x, scaled_y,
                                           scaled_width, scaled_height),
-                          shell->profile_src_format,
+                          gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
                           shell->profile_data, shell->profile_stride,
                           GEGL_BLIT_CACHE);
 #endif
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index 30fa249..951663b 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -153,13 +153,10 @@ struct _GimpDisplayShell
   GimpColorConfig   *color_config;     /*  color management settings          */
   gboolean           color_config_set; /*  settings changed from defaults     */
 
-  GimpColorTransform profile_transform;
-  const Babl        *profile_src_format;
-  const Babl        *profile_dest_format;
-
-  GeglBuffer        *profile_buffer;   /*  buffer for profile transform       */
-  guchar            *profile_data;     /*  profile_buffer's pixels            */
-  gint               profile_stride;   /*  profile_buffer's stride            */
+  GimpColorTransform *profile_transform;
+  GeglBuffer         *profile_buffer;  /*  buffer for profile transform       */
+  guchar             *profile_data;    /*  profile_buffer's pixels            */
+  gint                profile_stride;  /*  profile_buffer's stride            */
 
   GimpColorDisplayStack *filter_stack;   /* color display conversion stuff    */
   guint                  filter_idle_id;
diff --git a/app/gegl/gimp-gegl-loops.c b/app/gegl/gimp-gegl-loops.c
index d27e1f0..673621c 100644
--- a/app/gegl/gimp-gegl-loops.c
+++ b/app/gegl/gimp-gegl-loops.c
@@ -710,14 +710,10 @@ gimp_gegl_convert_color_profile (GeglBuffer               *src_buffer,
                                  gboolean                  bpc,
                                  GimpProgress             *progress)
 {
-  const Babl       *src_format;
-  const Babl       *dest_format;
-  cmsHPROFILE       src_lcms;
-  cmsHPROFILE       dest_lcms;
-  cmsUInt32Number   lcms_src_format;
-  cmsUInt32Number   lcms_dest_format;
-  cmsUInt32Number   flags;
-  cmsHTRANSFORM     transform;
+  GimpColorTransform *transform;
+  const Babl         *src_format;
+  const Babl         *dest_format;
+  cmsUInt32Number     flags;
 
   src_format  = gegl_buffer_get_format (src_buffer);
   dest_format = gegl_buffer_get_format (dest_buffer);
@@ -729,28 +725,27 @@ gimp_gegl_convert_color_profile (GeglBuffer               *src_buffer,
       return;
     }
 
-  src_lcms  = gimp_color_profile_get_lcms_profile (src_profile);
-  dest_lcms = gimp_color_profile_get_lcms_profile (dest_profile);
-
-  src_format  = gimp_color_profile_get_format (src_format,  &lcms_src_format);
-  dest_format = gimp_color_profile_get_format (dest_format, &lcms_dest_format);
-
   flags = cmsFLAGS_NOOPTIMIZE;
 
   if (bpc)
     flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
 
-  transform = cmsCreateTransform (src_lcms,  lcms_src_format,
-                                  dest_lcms, lcms_dest_format,
-                                  intent, flags);
+  transform = gimp_color_transform_new (src_profile,  src_format,
+                                        dest_profile, dest_format,
+                                        intent, flags);
 
   if (transform)
     {
-      gimp_gegl_convert_color_transform (src_buffer,  src_rect,  src_format,
-                                         dest_buffer, dest_rect, dest_format,
-                                         transform, progress);
+      if (progress)
+        g_signal_connect_swapped (transform, "progress",
+                                  G_CALLBACK (gimp_progress_set_value),
+                                  progress);
+
+      gimp_color_transform_process_buffer (transform,
+                                           src_buffer,  src_rect,
+                                           dest_buffer, dest_rect);
 
-      cmsDeleteTransform (transform);
+      g_object_unref (transform);
     }
   else
     {
@@ -762,67 +757,3 @@ gimp_gegl_convert_color_profile (GeglBuffer               *src_buffer,
         gimp_progress_set_value (progress, 1.0);
     }
 }
-
-void
-gimp_gegl_convert_color_transform (GeglBuffer          *src_buffer,
-                                   const GeglRectangle *src_rect,
-                                   const Babl          *src_format,
-                                   GeglBuffer          *dest_buffer,
-                                   const GeglRectangle *dest_rect,
-                                   const Babl          *dest_format,
-                                   GimpColorTransform   transform,
-                                   GimpProgress        *progress)
-{
-  GeglBufferIterator *iter;
-  gboolean            has_alpha;
-  gint                total_pixels;
-  gint                done_pixels = 0;
-
-  if (src_rect)
-    {
-      total_pixels = src_rect->width * src_rect->height;
-    }
-  else
-    {
-      total_pixels = (gegl_buffer_get_width  (src_buffer) *
-                      gegl_buffer_get_height (src_buffer));
-    }
-
-  has_alpha = babl_format_has_alpha (dest_format);
-
-  /* make sure the alpha channel is copied too, lcms doesn't copy it */
-  if (has_alpha)
-    gegl_buffer_copy (src_buffer,  src_rect, GEGL_ABYSS_NONE,
-                      dest_buffer, dest_rect);
-
-  iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0,
-                                   src_format,
-                                   GEGL_ACCESS_READ,
-                                   GEGL_ABYSS_NONE);
-
-  gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0,
-                            dest_format,
-                            /* use READWRITE for alpha surfaces
-                             * because we must use the alpha channel
-                             * that is already copied, see above
-                             */
-                            has_alpha ?
-                            GEGL_ACCESS_READWRITE: GEGL_ACCESS_WRITE,
-                            GEGL_ABYSS_NONE);
-
-  while (gegl_buffer_iterator_next (iter))
-    {
-      cmsDoTransform (transform,
-                      iter->data[0], iter->data[1], iter->length);
-
-      done_pixels += iter->roi[0].width * iter->roi[0].height;
-
-      if (progress)
-        gimp_progress_set_value (progress,
-                                 (gdouble) done_pixels /
-                                 (gdouble) total_pixels);
-    }
-
-  if (progress)
-    gimp_progress_set_value (progress, 1.0);
-}
diff --git a/app/gegl/gimp-gegl-loops.h b/app/gegl/gimp-gegl-loops.h
index 73747c8..e7dcc68 100644
--- a/app/gegl/gimp-gegl-loops.h
+++ b/app/gegl/gimp-gegl-loops.h
@@ -98,15 +98,5 @@ void   gimp_gegl_convert_color_profile (GeglBuffer               *src_buffer,
                                         gboolean                  bpc,
                                         GimpProgress             *progress);
 
-void   gimp_gegl_convert_color_transform
-                                       (GeglBuffer               *src_buffer,
-                                        const GeglRectangle      *src_rect,
-                                        const Babl               *src_format,
-                                        GeglBuffer               *dest_buffer,
-                                        const GeglRectangle      *dest_rect,
-                                        const Babl               *dest_format,
-                                        GimpColorTransform        transform,
-                                        GimpProgress             *progress);
-
 
 #endif /* __GIMP_GEGL_LOOPS_H__ */
diff --git a/app/operations/gimpoperationprofiletransform.c b/app/operations/gimpoperationprofiletransform.c
index 9e31f02..55b0ad6 100644
--- a/app/operations/gimpoperationprofiletransform.c
+++ b/app/operations/gimpoperationprofiletransform.c
@@ -153,7 +153,7 @@ gimp_operation_profile_transform_finalize (GObject *object)
 
   if (self->transform)
     {
-      cmsDeleteTransform (self->transform);
+      g_object_unref (self->transform);
       self->transform = NULL;
     }
 
@@ -241,7 +241,7 @@ gimp_operation_profile_transform_prepare (GeglOperation *operation)
 
   if (self->transform)
     {
-      cmsDeleteTransform (self->transform);
+      g_object_unref (self->transform);
       self->transform = NULL;
     }
 
@@ -250,28 +250,14 @@ gimp_operation_profile_transform_prepare (GeglOperation *operation)
 
   if (self->src_profile && self->dest_profile)
     {
-      cmsHPROFILE     src_lcms;
-      cmsHPROFILE     dest_lcms;
-      cmsUInt32Number lcms_src_format;
-      cmsUInt32Number lcms_dest_format;
-      cmsUInt32Number flags;
-
-      src_lcms  = gimp_color_profile_get_lcms_profile (self->src_profile);
-      dest_lcms = gimp_color_profile_get_lcms_profile (self->dest_profile);
-
-      self->src_format  = gimp_color_profile_get_format (format,
-                                                         &lcms_src_format);
-      self->dest_format = gimp_color_profile_get_format (format,
-                                                         &lcms_dest_format);
-
-      flags = cmsFLAGS_NOOPTIMIZE;
+      cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE;
 
       if (self->bpc)
         flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
 
-      self->transform = cmsCreateTransform (src_lcms,  lcms_src_format,
-                                            dest_lcms, lcms_dest_format,
-                                            self->intent, flags);
+      self->transform = gimp_color_transform_new (self->src_profile,  format,
+                                                  self->dest_profile, format,
+                                                  self->intent, flags);
     }
 
   gegl_operation_set_format (operation, "input",  self->src_format);
@@ -298,7 +284,12 @@ gimp_operation_profile_transform_process (GeglOperation       *operation,
                                  self->dest_format),
                       src, dest, samples);
 
-      cmsDoTransform (self->transform, src, dest, samples);
+      gimp_color_transform_process_pixels (self->transform,
+                                           self->src_format,
+                                           src,
+                                           self->dest_format,
+                                           dest,
+                                           samples);
     }
   else
     {
diff --git a/app/operations/gimpoperationprofiletransform.h b/app/operations/gimpoperationprofiletransform.h
index fef191f..d4ab3b0 100644
--- a/app/operations/gimpoperationprofiletransform.h
+++ b/app/operations/gimpoperationprofiletransform.h
@@ -50,7 +50,7 @@ struct _GimpOperationProfileTransform
   GimpColorRenderingIntent  intent;
   gboolean                  bpc;
 
-  GimpColorTransform        transform;
+  GimpColorTransform       *transform;
 };
 
 struct _GimpOperationProfileTransformClass
diff --git a/app/widgets/gimpviewrenderer.c b/app/widgets/gimpviewrenderer.c
index 550060e..2144809 100644
--- a/app/widgets/gimpviewrenderer.c
+++ b/app/widgets/gimpviewrenderer.c
@@ -69,9 +69,7 @@ struct _GimpViewRendererPrivate
   gchar              *bg_icon_name;
 
   GimpColorConfig    *color_config;
-  GimpColorTransform  profile_transform;
-  const Babl         *profile_src_format;
-  const Babl         *profile_dest_format;
+  GimpColorTransform *profile_transform;
 
   gboolean            needs_render;
   guint               idle_id;
@@ -1119,16 +1117,13 @@ gimp_view_render_temp_buf_to_surface (GimpViewRenderer *renderer,
 
       if (renderer->priv->profile_transform)
         {
-          gimp_gegl_convert_color_transform (src_buffer,
-                                             GEGL_RECTANGLE (x - temp_buf_x,
-                                                             y - temp_buf_y,
-                                                             width, height),
-                                             renderer->priv->profile_src_format,
-                                             dest_buffer,
-                                             GEGL_RECTANGLE (0, 0, 0, 0),
-                                             renderer->priv->profile_dest_format,
-                                             renderer->priv->profile_transform,
-                                             NULL);
+          gimp_color_transform_process_buffer (renderer->priv->profile_transform,
+                                               src_buffer,
+                                               GEGL_RECTANGLE (x - temp_buf_x,
+                                                               y - temp_buf_y,
+                                                               width, height),
+                                               dest_buffer,
+                                               GEGL_RECTANGLE (0, 0, 0, 0));
         }
       else
         {
@@ -1169,16 +1164,13 @@ gimp_view_render_temp_buf_to_surface (GimpViewRenderer *renderer,
 
       if (renderer->priv->profile_transform)
         {
-          gimp_gegl_convert_color_transform (src_buffer,
-                                             GEGL_RECTANGLE (x - temp_buf_x,
-                                                             y - temp_buf_y,
-                                                             width, height),
-                                             renderer->priv->profile_src_format,
-                                             dest_buffer,
-                                             GEGL_RECTANGLE (x, y, 0, 0),
-                                             renderer->priv->profile_dest_format,
-                                             renderer->priv->profile_transform,
-                                             NULL);
+          gimp_color_transform_process_buffer (renderer->priv->profile_transform,
+                                               src_buffer,
+                                               GEGL_RECTANGLE (x - temp_buf_x,
+                                                               y - temp_buf_y,
+                                                               width, height),
+                                               dest_buffer,
+                                               GEGL_RECTANGLE (x, y, 0, 0));
         }
       else
         {
@@ -1313,15 +1305,11 @@ gimp_view_renderer_transform_create (GimpViewRenderer *renderer,
           if (! config)
             config = renderer->context->gimp->config->color_management;
 
-          renderer->priv->profile_src_format  = gegl_buffer_get_format (src_buffer);
-
-          renderer->priv->profile_dest_format = gegl_buffer_get_format (dest_buffer);
-
           renderer->priv->profile_transform =
             gimp_widget_get_color_transform (widget, config,
                                              profile,
-                                             &renderer->priv->profile_src_format,
-                                             &renderer->priv->profile_dest_format);
+                                             gegl_buffer_get_format (src_buffer),
+                                             gegl_buffer_get_format (dest_buffer));
         }
     }
 }
@@ -1331,9 +1319,7 @@ gimp_view_renderer_transform_free (GimpViewRenderer *renderer)
 {
   if (renderer->priv->profile_transform)
     {
-      cmsDeleteTransform (renderer->priv->profile_transform);
-      renderer->priv->profile_transform   = NULL;
-      renderer->priv->profile_src_format  = NULL;
-      renderer->priv->profile_dest_format = NULL;
+      g_object_unref (renderer->priv->profile_transform);
+      renderer->priv->profile_transform = NULL;
     }
 }
diff --git a/libgimpcolor/Makefile.am b/libgimpcolor/Makefile.am
index 84c56c3..767f3b9 100644
--- a/libgimpcolor/Makefile.am
+++ b/libgimpcolor/Makefile.am
@@ -78,6 +78,8 @@ libgimpcolor_ GIMP_API_VERSION@_la_SOURCES = \
        gimpcolorprofile.h              \
        gimpcolorspace.c                \
        gimpcolorspace.h                \
+       gimpcolortransform.c            \
+       gimpcolortransform.h            \
        gimphsl.c                       \
        gimphsl.h                       \
        gimphsv.c                       \
@@ -98,6 +100,7 @@ libgimpcolorinclude_HEADERS = \
        gimpcolormanaged.h              \
        gimpcolorprofile.h              \
        gimpcolorspace.h                \
+       gimpcolortransform.h            \
        gimphsl.h                       \
        gimphsv.h                       \
        gimppixbuf.h                    \
diff --git a/libgimpcolor/gimpcolor.def b/libgimpcolor/gimpcolor.def
index 6178706..24ab7f8 100644
--- a/libgimpcolor/gimpcolor.def
+++ b/libgimpcolor/gimpcolor.def
@@ -52,6 +52,11 @@ EXPORTS
        gimp_color_profile_new_rgb_srgb_linear
        gimp_color_profile_new_srgb_trc_from_color_profile
        gimp_color_profile_save_to_file
+       gimp_color_transform_get_type
+       gimp_color_transform_new
+       gimp_color_transform_new_proofing
+       gimp_color_transform_process_buffer
+       gimp_color_transform_process_pixels
        gimp_hsl_get_type
        gimp_hsl_set
        gimp_hsl_set_alpha
diff --git a/libgimpcolor/gimpcolor.h b/libgimpcolor/gimpcolor.h
index 59e6241..4bddf34 100644
--- a/libgimpcolor/gimpcolor.h
+++ b/libgimpcolor/gimpcolor.h
@@ -29,6 +29,7 @@
 #include <libgimpcolor/gimpcolormanaged.h>
 #include <libgimpcolor/gimpcolorprofile.h>
 #include <libgimpcolor/gimpcolorspace.h>
+#include <libgimpcolor/gimpcolortransform.h>
 #include <libgimpcolor/gimpcmyk.h>
 #include <libgimpcolor/gimphsl.h>
 #include <libgimpcolor/gimphsv.h>
diff --git a/libgimpcolor/gimpcolortransform.c b/libgimpcolor/gimpcolortransform.c
new file mode 100644
index 0000000..986fbcb
--- /dev/null
+++ b/libgimpcolor/gimpcolortransform.c
@@ -0,0 +1,417 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimpcolortransform.c
+ * Copyright (C) 2014  Michael Natterer <mitch gimp org>
+ *                     Elle Stone <ellestone ninedegreesbelow com>
+ *                     Øyvind Kolås <pippin gimp org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <lcms2.h>
+
+#include <gio/gio.h>
+#include <gegl.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpconfig/gimpconfig.h"
+
+#include "gimpcolortypes.h"
+
+#include "gimpcolorprofile.h"
+#include "gimpcolortransform.h"
+
+#include "libgimp/libgimp-intl.h"
+
+
+/**
+ * SECTION: gimpcolortransform
+ * @title: GimpColorTransform
+ * @short_description: Definitions and Functions relating to LCMS.
+ *
+ * Definitions and Functions relating to LCMS.
+ **/
+
+/**
+ * GimpColorTransform:
+ *
+ * Simply a typedef to #gpointer, but actually is a cmsHTRANSFORM. It's
+ * used in public GIMP APIs in order to avoid having to include LCMS
+ * headers.
+ **/
+
+
+enum
+{
+  PROGRESS,
+  LAST_SIGNAL
+};
+
+
+struct _GimpColorTransformPrivate
+{
+  GimpColorProfile *src_profile;
+  const Babl       *src_format;
+
+  GimpColorProfile *dest_profile;
+  const Babl       *dest_format;
+
+  cmsHTRANSFORM     transform;
+};
+
+
+static void   gimp_color_transform_finalize (GObject *object);
+
+
+G_DEFINE_TYPE (GimpColorTransform, gimp_color_transform,
+               G_TYPE_OBJECT);
+
+#define parent_class gimp_color_transform_parent_class
+
+static guint gimp_color_transform_signals[LAST_SIGNAL] = { 0 };
+
+
+static void
+gimp_color_transform_class_init (GimpColorTransformClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gimp_color_transform_finalize;
+
+  gimp_color_transform_signals[PROGRESS] =
+    g_signal_new ("progress",
+                  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GimpColorTransformClass,
+                                   progress),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__DOUBLE,
+                  G_TYPE_NONE, 1,
+                  G_TYPE_DOUBLE);
+
+  g_type_class_add_private (klass, sizeof (GimpColorTransformPrivate));
+}
+
+static void
+gimp_color_transform_init (GimpColorTransform *transform)
+{
+  transform->priv = G_TYPE_INSTANCE_GET_PRIVATE (transform,
+                                                 GIMP_TYPE_COLOR_TRANSFORM,
+                                                 GimpColorTransformPrivate);
+}
+
+static void
+gimp_color_transform_finalize (GObject *object)
+{
+  GimpColorTransform *transform = GIMP_COLOR_TRANSFORM (object);
+
+  if (transform->priv->src_profile)
+    {
+      g_object_unref (transform->priv->src_profile);
+      transform->priv->src_profile = NULL;
+    }
+
+  if (transform->priv->dest_profile)
+    {
+      g_object_unref (transform->priv->dest_profile);
+      transform->priv->dest_profile = NULL;
+    }
+
+  if (transform->priv->transform)
+    {
+      cmsDeleteTransform (transform->priv->transform);
+      transform->priv->transform = NULL;
+    }
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+/**
+ * gimp_color_transform_new:
+ * @src_profile:
+ * @src_format:
+ * @desr_profile:
+ * @dest_format:
+ * @rendering_intent:
+ * @flags:
+ *
+ * This function creates an color transform.
+ *
+ * Return value: the #GimpColorTransform, or %NULL.
+ *
+ * Since: 2.10
+ **/
+GimpColorTransform *
+gimp_color_transform_new (GimpColorProfile         *src_profile,
+                          const Babl               *src_format,
+                          GimpColorProfile         *dest_profile,
+                          const Babl               *dest_format,
+                          GimpColorRenderingIntent  rendering_intent,
+                          guint32                   flags)
+{
+  GimpColorTransform        *transform;
+  GimpColorTransformPrivate *priv;
+  cmsHPROFILE                src_lcms;
+  cmsHPROFILE                dest_lcms;
+  cmsUInt32Number            lcms_src_format;
+  cmsUInt32Number            lcms_dest_format;
+
+  g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (src_profile), NULL);
+  g_return_val_if_fail (src_format != NULL, NULL);
+  g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (dest_profile), NULL);
+  g_return_val_if_fail (dest_format != NULL, NULL);
+
+  transform = g_object_new (GIMP_TYPE_COLOR_TRANSFORM, NULL);
+
+  priv = transform->priv;
+
+  src_lcms  = gimp_color_profile_get_lcms_profile (src_profile);
+  dest_lcms = gimp_color_profile_get_lcms_profile (dest_profile);
+
+  priv->src_format  = gimp_color_profile_get_format (src_format,
+                                                     &lcms_src_format);
+  priv->dest_format = gimp_color_profile_get_format (dest_format,
+                                                     &lcms_dest_format);
+
+  priv->transform = cmsCreateTransform (src_lcms,  lcms_src_format,
+                                        dest_lcms, lcms_dest_format,
+                                        rendering_intent,
+                                        flags);
+
+  return transform;
+}
+
+/**
+ * gimp_color_transform_new_proofing:
+ * @src_profile:
+ * @src_format:
+ * @desr_profile:
+ * @dest_format:
+ * @proof_profile:
+ * @proof_intent:
+ * @display_intent:
+ * @flags:
+ *
+ * This function creates a simulation / proofing color transform.
+ *
+ * Return value: the #GimpColorTransform, or %NULL.
+ *
+ * Since: 2.10
+ **/
+GimpColorTransform *
+gimp_color_transform_new_proofing (GimpColorProfile         *src_profile,
+                                   const Babl               *src_format,
+                                   GimpColorProfile         *dest_profile,
+                                   const Babl               *dest_format,
+                                   GimpColorProfile         *proof_profile,
+                                   GimpColorRenderingIntent  proof_intent,
+                                   GimpColorRenderingIntent  display_intent,
+                                   guint32                   flags)
+{
+  GimpColorTransform        *transform;
+  GimpColorTransformPrivate *priv;
+  cmsHPROFILE                src_lcms;
+  cmsHPROFILE                dest_lcms;
+  cmsHPROFILE                proof_lcms;
+  cmsUInt32Number            lcms_src_format;
+  cmsUInt32Number            lcms_dest_format;
+
+  g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (src_profile), NULL);
+  g_return_val_if_fail (src_format != NULL, NULL);
+  g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (dest_profile), NULL);
+  g_return_val_if_fail (dest_format != NULL, NULL);
+  g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (proof_profile), NULL);
+
+  transform = g_object_new (GIMP_TYPE_COLOR_TRANSFORM, NULL);
+
+  priv = transform->priv;
+
+  src_lcms   = gimp_color_profile_get_lcms_profile (src_profile);
+  dest_lcms  = gimp_color_profile_get_lcms_profile (dest_profile);
+  proof_lcms = gimp_color_profile_get_lcms_profile (proof_profile);
+
+  priv->src_format  = gimp_color_profile_get_format (src_format,
+                                                     &lcms_src_format);
+  priv->dest_format = gimp_color_profile_get_format (dest_format,
+                                                     &lcms_dest_format);
+
+  priv->transform = cmsCreateProofingTransform (src_lcms,  lcms_src_format,
+                                                dest_lcms, lcms_dest_format,
+                                                proof_lcms,
+                                                proof_intent,
+                                                display_intent,
+                                                flags | cmsFLAGS_SOFTPROOFING);
+
+  return transform;
+}
+
+/**
+ * gimp_color_transform_process_pixels:
+ * @transform:
+ * @src_format:
+ * @src_pixels:
+ * @dest_format:
+ * @dest_pixels:
+ * @length:
+ *
+ * This function transforms a contiguous line of pixels.
+ *
+ * Since: 2.10
+ **/
+void
+gimp_color_transform_process_pixels (GimpColorTransform *transform,
+                                     const Babl         *src_format,
+                                     gconstpointer       src_pixels,
+                                     const Babl         *dest_format,
+                                     gpointer            dest_pixels,
+                                     gsize               length)
+{
+  GimpColorTransformPrivate *priv;
+  gpointer                  *src;
+  gpointer                  *dest;
+
+  g_return_if_fail (GIMP_IS_COLOR_TRANSFORM (transform));
+  g_return_if_fail (src_format != NULL);
+  g_return_if_fail (src_pixels != NULL);
+  g_return_if_fail (dest_format != NULL);
+  g_return_if_fail (dest_pixels != NULL);
+
+  priv = transform->priv;
+
+  if (src_format != priv->src_format)
+    {
+      src = g_malloc (length * babl_format_get_bytes_per_pixel (priv->src_format));
+
+      babl_process (babl_fish (src_format,
+                               priv->src_format),
+                    src_pixels, src, length);
+    }
+  else
+    {
+      src = (gpointer) src_pixels;
+    }
+
+  if (dest_format != priv->dest_format)
+    {
+      dest = g_malloc (length * babl_format_get_bytes_per_pixel (priv->dest_format));
+    }
+  else
+    {
+      dest = dest_pixels;
+    }
+
+  /* copy the alpha channel */
+  if (babl_format_has_alpha (dest_format))
+    babl_process (babl_fish (src_format,
+                             priv->dest_format),
+                  src, dest, length);
+
+  cmsDoTransform (priv->transform, src, dest, length);
+
+  if (src_format != priv->src_format)
+    {
+      g_free (src);
+    }
+
+  if (dest_format != priv->dest_format)
+    {
+      babl_process (babl_fish (priv->dest_format,
+                               dest_format),
+                    dest, dest_pixels, length);
+
+      g_free (dest);
+    }
+}
+
+/**
+ * gimp_color_transform_process_buffer:
+ * @transform:
+ * @src_format:
+ * @src_rect:
+ * @dest_format:
+ * @dest_rect:
+ *
+ * This function transforms a contiguous line of pixels.
+ *
+ * Since: 2.10
+ **/
+void
+gimp_color_transform_process_buffer (GimpColorTransform  *transform,
+                                     GeglBuffer          *src_buffer,
+                                     const GeglRectangle *src_rect,
+                                     GeglBuffer          *dest_buffer,
+                                     const GeglRectangle *dest_rect)
+{
+  GimpColorTransformPrivate *priv;
+  GeglBufferIterator        *iter;
+  const Babl                *fish = NULL;
+  gint                       total_pixels;
+  gint                       done_pixels = 0;
+
+  g_return_if_fail (GIMP_IS_COLOR_TRANSFORM (transform));
+  g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
+  g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
+
+  priv = transform->priv;
+
+  if (src_rect)
+    {
+      total_pixels = src_rect->width * src_rect->height;
+    }
+  else
+    {
+      total_pixels = (gegl_buffer_get_width  (src_buffer) *
+                      gegl_buffer_get_height (src_buffer));
+    }
+
+  if (babl_format_has_alpha (priv->dest_format))
+    fish = babl_fish (priv->src_format,
+                      priv->dest_format);
+
+  iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0,
+                                   priv->src_format,
+                                   GEGL_ACCESS_READ,
+                                   GEGL_ABYSS_NONE);
+
+  gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0,
+                            priv->dest_format,
+                            GEGL_ACCESS_WRITE,
+                            GEGL_ABYSS_NONE);
+
+  while (gegl_buffer_iterator_next (iter))
+    {
+      /* make sure the alpha channel is copied too, lcms doesn't copy it */
+      if (fish)
+        babl_process (fish, iter->data[0], iter->data[1], iter->length);
+
+      cmsDoTransform (priv->transform,
+                      iter->data[0], iter->data[1], iter->length);
+
+      done_pixels += iter->roi[0].width * iter->roi[0].height;
+
+      g_signal_emit (transform, gimp_color_transform_signals[PROGRESS], 0,
+                     (gdouble) done_pixels /
+                     (gdouble) total_pixels);
+    }
+
+  g_signal_emit (transform, gimp_color_transform_signals[PROGRESS], 0,
+                 1.0);
+}
diff --git a/libgimpcolor/gimpcolortransform.h b/libgimpcolor/gimpcolortransform.h
new file mode 100644
index 0000000..c4a9230
--- /dev/null
+++ b/libgimpcolor/gimpcolortransform.h
@@ -0,0 +1,105 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimpcolortransform.h
+ * Copyright (C) 2014  Michael Natterer <mitch gimp org>
+ *                     Elle Stone <ellestone ninedegreesbelow com>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_COLOR_H_INSIDE__) && !defined (GIMP_COLOR_COMPILATION)
+#error "Only <libgimpcolor/gimpcolor.h> can be included directly."
+#endif
+
+#ifndef __GIMP_COLOR_TRANSFORM_H__
+#define __GIMP_COLOR_TRANSFORM_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+#define GIMP_TYPE_COLOR_TRANSFORM            (gimp_color_transform_get_type ())
+#define GIMP_COLOR_TRANSFORM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_COLOR_TRANSFORM, 
GimpColorTransform))
+#define GIMP_COLOR_TRANSFORM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_COLOR_TRANSFORM, 
GimpColorTransformClass))
+#define GIMP_IS_COLOR_TRANSFORM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_COLOR_TRANSFORM))
+#define GIMP_IS_COLOR_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_COLOR_TRANSFORM))
+#define GIMP_COLOR_TRANSFORM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_COLOR_TRANSFORM, 
GimpColorTransformClass))
+
+
+typedef struct _GimpColorTransformClass   GimpColorTransformClass;
+typedef struct _GimpColorTransformPrivate GimpColorTransformPrivate;
+
+struct _GimpColorTransform
+{
+  GObject                    parent_instance;
+
+  GimpColorTransformPrivate *priv;
+};
+
+struct _GimpColorTransformClass
+{
+  GObjectClass  parent_class;
+
+  /* signals */
+  void (* progress) (GimpColorTransform *transform,
+                     gdouble             fraction);
+
+  /* Padding for future expansion */
+  void (* _gimp_reserved1) (void);
+  void (* _gimp_reserved2) (void);
+  void (* _gimp_reserved3) (void);
+  void (* _gimp_reserved4) (void);
+};
+
+
+GType   gimp_color_transform_get_type (void) G_GNUC_CONST;
+
+GimpColorTransform *
+        gimp_color_transform_new              (GimpColorProfile         *src_profile,
+                                               const Babl               *src_format,
+                                               GimpColorProfile         *dest_profile,
+                                               const Babl               *dest_format,
+                                               GimpColorRenderingIntent  rendering_intent,
+                                               guint32                   flags);
+
+GimpColorTransform *
+        gimp_color_transform_new_proofing     (GimpColorProfile         *src_profile,
+                                               const Babl               *src_format,
+                                               GimpColorProfile         *dest_profile,
+                                               const Babl               *dest_format,
+                                               GimpColorProfile         *proof_profile,
+                                               GimpColorRenderingIntent  proof_intent,
+                                               GimpColorRenderingIntent  display_intent,
+                                               guint32                   flags);
+
+void    gimp_color_transform_process_pixels   (GimpColorTransform       *transform,
+                                               const Babl               *src_format,
+                                               gconstpointer             src,
+                                               const Babl               *dest_format,
+                                               gpointer                  dest,
+                                               gsize                     length);
+
+void    gimp_color_transform_process_buffer   (GimpColorTransform       *transform,
+                                               GeglBuffer               *src_buffer,
+                                               const GeglRectangle      *src_rect,
+                                               GeglBuffer               *dest_buffer,
+                                               const GeglRectangle      *dest_rect);
+
+
+G_END_DECLS
+
+#endif  /* __GIMP_COLOR_TRANSFORM_H__ */
diff --git a/libgimpcolor/gimpcolortypes.h b/libgimpcolor/gimpcolortypes.h
index 0022202..6f04c1e 100644
--- a/libgimpcolor/gimpcolortypes.h
+++ b/libgimpcolor/gimpcolortypes.h
@@ -21,6 +21,7 @@
 
 
 #include <libgimpbase/gimpbasetypes.h>
+#include <libgimpconfig/gimpconfigtypes.h>
 
 
 G_BEGIN_DECLS
@@ -28,10 +29,9 @@ G_BEGIN_DECLS
 /* For information look into the C source or the html documentation */
 
 
-typedef struct _GimpColorManaged GimpColorManaged;  /* dummy typedef */
-typedef struct _GimpColorProfile GimpColorProfile;
-
-typedef gpointer GimpColorTransform;
+typedef struct _GimpColorManaged   GimpColorManaged;  /* dummy typedef */
+typedef struct _GimpColorProfile   GimpColorProfile;
+typedef struct _GimpColorTransform GimpColorTransform;
 
 
 /*  usually we don't keep the structure definitions in the types file
diff --git a/libgimpwidgets/gimpcolorarea.c b/libgimpwidgets/gimpcolorarea.c
index 854c6fc..b75deb4 100644
--- a/libgimpwidgets/gimpcolorarea.c
+++ b/libgimpwidgets/gimpcolorarea.c
@@ -72,7 +72,7 @@ typedef struct _GimpColorAreaPrivate GimpColorAreaPrivate;
 struct _GimpColorAreaPrivate
 {
   GimpColorConfig    *config;
-  GimpColorTransform  transform;
+  GimpColorTransform *transform;
 };
 
 #define GET_PRIVATE(obj) \
@@ -402,14 +402,18 @@ gimp_color_area_expose (GtkWidget      *widget,
 
   if (priv->transform)
     {
-      guchar *buf  = g_new (guchar, area->rowstride * area->height);
-      guchar *src  = area->buf;
-      guchar *dest = buf;
-      gint    i;
+      const Babl *format = babl_format ("cairo-RGB24");
+      guchar     *buf    = g_new (guchar, area->rowstride * area->height);
+      guchar     *src    = area->buf;
+      guchar     *dest   = buf;
+      gint        i;
 
       for (i = 0; i < area->height; i++)
         {
-          cmsDoTransform (priv->transform, src, dest, area->width);
+          gimp_color_transform_process_pixels (priv->transform,
+                                               format, src,
+                                               format, dest,
+                                               area->width);
 
           src  += area->rowstride;
           dest += area->rowstride;
@@ -621,7 +625,7 @@ gimp_color_area_set_color_config (GimpColorArea   *area,
 
       if (priv->transform)
         {
-          cmsDeleteTransform (priv->transform);
+          g_object_unref (priv->transform);
           priv->transform = NULL;
         }
     }
@@ -919,7 +923,7 @@ gimp_color_area_config_notify (GimpColorConfig  *config,
 
   if (priv->transform)
     {
-      cmsDeleteTransform (priv->transform);
+      g_object_unref (priv->transform);
       priv->transform = NULL;
     }
 
@@ -943,7 +947,7 @@ gimp_color_area_create_transform (GimpColorArea *area)
       priv->transform = gimp_widget_get_color_transform (GTK_WIDGET (area),
                                                          priv->config,
                                                          profile,
-                                                         &format,
-                                                         &format);
+                                                         format,
+                                                         format);
     }
 }
diff --git a/libgimpwidgets/gimppreviewarea.c b/libgimpwidgets/gimppreviewarea.c
index 496fa8c..6f53dbf 100644
--- a/libgimpwidgets/gimppreviewarea.c
+++ b/libgimpwidgets/gimppreviewarea.c
@@ -67,7 +67,7 @@ typedef struct _GimpPreviewAreaPrivate GimpPreviewAreaPrivate;
 struct _GimpPreviewAreaPrivate
 {
   GimpColorConfig    *config;
-  GimpColorTransform  transform;
+  GimpColorTransform *transform;
 };
 
 #define GET_PRIVATE(obj) \
@@ -291,15 +291,19 @@ gimp_preview_area_expose (GtkWidget      *widget,
 
   if (priv->transform)
     {
-      gint    rowstride = ((area->width * 3) + 3) & ~3;
-      guchar *buf       = g_new (guchar, rowstride * area->height);
-      guchar *src       = area->buf;
-      guchar *dest      = buf;
-      gint    i;
+      const Babl *format    = babl_format ("R'G'B' u8");
+      gint        rowstride = ((area->width * 3) + 3) & ~3;
+      guchar     *buf       = g_new (guchar, rowstride * area->height);
+      guchar     *src       = area->buf;
+      guchar     *dest      = buf;
+      gint        i;
 
       for (i = 0; i < area->height; i++)
         {
-          cmsDoTransform (priv->transform, src, dest, area->width);
+          gimp_color_transform_process_pixels (priv->transform,
+                                               format, src,
+                                               format, dest,
+                                               area->width);
 
           src  += area->rowstride;
           dest += rowstride;
@@ -392,7 +396,7 @@ gimp_preview_area_config_notify (GimpColorConfig  *config,
 
   if (priv->transform)
     {
-      cmsDeleteTransform (priv->transform);
+      g_object_unref (priv->transform);
       priv->transform = NULL;
     }
 
@@ -416,8 +420,8 @@ gimp_preview_area_create_transform (GimpPreviewArea *area)
       priv->transform = gimp_widget_get_color_transform (GTK_WIDGET (area),
                                                          priv->config,
                                                          profile,
-                                                         &format,
-                                                         &format);
+                                                         format,
+                                                         format);
     }
 }
 
@@ -1805,7 +1809,7 @@ gimp_preview_area_set_color_config (GimpPreviewArea *area,
 
       if (priv->transform)
         {
-          cmsDeleteTransform (priv->transform);
+          g_object_unref (priv->transform);
           priv->transform = NULL;
         }
     }
diff --git a/libgimpwidgets/gimpwidgetsutils.c b/libgimpwidgets/gimpwidgetsutils.c
index 4557e9e..8a3dfcb 100644
--- a/libgimpwidgets/gimpwidgetsutils.c
+++ b/libgimpwidgets/gimpwidgetsutils.c
@@ -479,20 +479,16 @@ get_display_profile (GtkWidget       *widget,
   return profile;
 }
 
-GimpColorTransform
-gimp_widget_get_color_transform (GtkWidget         *widget,
-                                 GimpColorConfig   *config,
-                                 GimpColorProfile  *src_profile,
-                                 const Babl       **src_format,
-                                 const Babl       **dest_format)
+GimpColorTransform *
+gimp_widget_get_color_transform (GtkWidget        *widget,
+                                 GimpColorConfig  *config,
+                                 GimpColorProfile *src_profile,
+                                 const Babl       *src_format,
+                                 const Babl       *dest_format)
 {
-  GimpColorTransform  transform     = NULL;
+  GimpColorTransform *transform     = NULL;
   GimpColorProfile   *dest_profile  = NULL;
   GimpColorProfile   *proof_profile = NULL;
-  cmsHPROFILE         src_lcms;
-  cmsHPROFILE         dest_lcms;
-  cmsUInt32Number     lcms_src_format;
-  cmsUInt32Number     lcms_dest_format;
   cmsUInt16Number     alarmCodes[cmsMAXCHANNELS] = { 0, };
 
   g_return_val_if_fail (widget == NULL || GTK_IS_WIDGET (widget), NULL);
@@ -515,19 +511,10 @@ gimp_widget_get_color_transform (GtkWidget         *widget,
       break;
     }
 
-  src_lcms  = gimp_color_profile_get_lcms_profile (src_profile);
-  dest_lcms = gimp_color_profile_get_lcms_profile (dest_profile);
-
-  *src_format  = gimp_color_profile_get_format (*src_format,  &lcms_src_format);
-  *dest_format = gimp_color_profile_get_format (*dest_format, &lcms_dest_format);
-
   if (proof_profile)
     {
-      cmsHPROFILE     proof_lcms;
       cmsUInt32Number softproof_flags = cmsFLAGS_SOFTPROOFING;
 
-      proof_lcms = gimp_color_profile_get_lcms_profile (proof_profile);
-
       if (config->simulation_use_black_point_compensation)
         {
           softproof_flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
@@ -548,28 +535,28 @@ gimp_widget_get_color_transform (GtkWidget         *widget,
           cmsSetAlarmCodes (alarmCodes);
         }
 
-      transform = cmsCreateProofingTransform (src_lcms,  lcms_src_format,
-                                              dest_lcms, lcms_dest_format,
-                                              proof_lcms,
-                                              config->simulation_intent,
-                                              config->display_intent,
-                                              softproof_flags);
+      transform = gimp_color_transform_new_proofing (src_profile,  src_format,
+                                                     dest_profile, dest_format,
+                                                     proof_profile,
+                                                     config->simulation_intent,
+                                                     config->display_intent,
+                                                     softproof_flags);
 
       g_object_unref (proof_profile);
     }
   else if (! gimp_color_profile_is_equal (src_profile, dest_profile))
     {
-      cmsUInt32Number display_flags = 0;
+      guint32 display_flags = 0;
 
       if (config->display_use_black_point_compensation)
         {
           display_flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
         }
 
-      transform = cmsCreateTransform (src_lcms,  lcms_src_format,
-                                      dest_lcms, lcms_dest_format,
-                                      config->display_intent,
-                                      display_flags);
+      transform = gimp_color_transform_new (src_profile,  src_format,
+                                            dest_profile, dest_format,
+                                            config->display_intent,
+                                            display_flags);
     }
 
   g_object_unref (dest_profile);
diff --git a/libgimpwidgets/gimpwidgetsutils.h b/libgimpwidgets/gimpwidgetsutils.h
index cb32f10..29ef6cb 100644
--- a/libgimpwidgets/gimpwidgetsutils.h
+++ b/libgimpwidgets/gimpwidgetsutils.h
@@ -48,11 +48,11 @@ gint                 gimp_get_monitor_at_pointer     (GdkScreen        **screen)
 
 GimpColorProfile   * gimp_widget_get_color_profile   (GtkWidget         *widget);
 
-GimpColorTransform   gimp_widget_get_color_transform (GtkWidget         *widget,
+GimpColorTransform * gimp_widget_get_color_transform (GtkWidget         *widget,
                                                       GimpColorConfig   *config,
                                                       GimpColorProfile  *src_profile,
-                                                      const Babl       **src_format,
-                                                      const Babl       **dest_format);
+                                                      const Babl        *src_format,
+                                                      const Babl        *dest_format);
 
 
 G_END_DECLS
diff --git a/modules/display-filter-lcms.c b/modules/display-filter-lcms.c
index c30615a..0b41b10 100644
--- a/modules/display-filter-lcms.c
+++ b/modules/display-filter-lcms.c
@@ -62,9 +62,7 @@ struct _CdisplayLcms
 {
   GimpColorDisplay    parent_instance;
 
-  GimpColorTransform  transform;
-  const Babl         *src_format;
-  const Babl         *dest_format;
+  GimpColorTransform *transform;
 };
 
 struct _CdisplayLcmsClass
@@ -148,7 +146,6 @@ cdisplay_lcms_class_finalize (CdisplayLcmsClass *klass)
 static void
 cdisplay_lcms_init (CdisplayLcms *lcms)
 {
-  lcms->transform = NULL;
 }
 
 static void
@@ -158,7 +155,7 @@ cdisplay_lcms_finalize (GObject *object)
 
   if (lcms->transform)
     {
-      cmsDeleteTransform (lcms->transform);
+      g_object_unref (lcms->transform);
       lcms->transform = NULL;
     }
 
@@ -234,22 +231,12 @@ cdisplay_lcms_convert_buffer (GimpColorDisplay *display,
                               GeglBuffer       *buffer,
                               GeglRectangle    *area)
 {
-  CdisplayLcms       *lcms = CDISPLAY_LCMS (display);
-  GeglBufferIterator *iter;
+  CdisplayLcms *lcms = CDISPLAY_LCMS (display);
 
-  if (! lcms->transform)
-    return;
-
-  iter = gegl_buffer_iterator_new (buffer, area, 0,
-                                   lcms->src_format,
-                                   GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE);
-
-  while (gegl_buffer_iterator_next (iter))
-    {
-      gfloat *data = iter->data[0];
-
-      cmsDoTransform (lcms->transform, data, data, iter->length);
-    }
+  if (lcms->transform)
+    gimp_color_transform_process_buffer (lcms->transform,
+                                         buffer, area,
+                                         buffer, area);
 }
 
 static void
@@ -263,7 +250,7 @@ cdisplay_lcms_changed (GimpColorDisplay *display)
 
   if (lcms->transform)
     {
-      cmsDeleteTransform (lcms->transform);
+      g_object_unref (lcms->transform);
       lcms->transform = NULL;
     }
 
@@ -278,16 +265,11 @@ cdisplay_lcms_changed (GimpColorDisplay *display)
 
   src_profile = gimp_color_managed_get_color_profile (managed);
 
-  if (src_profile)
-    {
-      lcms->src_format  = babl_format ("R'G'B'A float");
-      lcms->dest_format = babl_format ("R'G'B'A float");
-
-      lcms->transform = gimp_widget_get_color_transform (widget,
-                                                         config, src_profile,
-                                                         &lcms->src_format,
-                                                         &lcms->dest_format);
-    }
+  lcms->transform =
+    gimp_widget_get_color_transform (widget,
+                                     config, src_profile,
+                                     babl_format ("R'G'B'A float"),
+                                     babl_format ("R'G'B'A float"));
 }
 
 static GimpColorProfile *


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]