diff --git a/plug-ins/common/Makefile.am b/plug-ins/common/Makefile.am
index 417fb87..7c4d718 100644
--- a/plug-ins/common/Makefile.am
+++ b/plug-ins/common/Makefile.am
@@ -1789,6 +1789,7 @@ lcms_LDADD = \
 	$(libgimpcolor)		\
 	$(libgimpbase)		\
 	$(GTK_LIBS)		\
+	$(GEGL_LIBS)		\
 	$(LCMS_LIBS)		\
 	$(RT_LIBS)		\
 	$(INTLLIBS)		\
diff --git a/plug-ins/common/lcms.c b/plug-ins/common/lcms.c
index 954d52a..68407a2 100644
--- a/plug-ins/common/lcms.c
+++ b/plug-ins/common/lcms.c
@@ -128,8 +128,8 @@ static void         lcms_image_transform_indexed (gint32           image,
                                                   cmsHPROFILE      dest_profile,
                                                   GimpColorRenderingIntent intent,
                                                   gboolean          bpc);
-
-static void         lcms_drawable_transform      (GimpDrawable    *drawable,
+static void         lcms_drawable_transform      (gint32           layer_id,
+                                                  gboolean         has_alpha,
                                                   cmsHTRANSFORM    transform,
                                                   gdouble          progress_start,
                                                   gdouble          progress_end);
@@ -334,6 +334,8 @@ run (const gchar      *name,
 
   INIT_I18N ();
 
+  gegl_init (NULL, NULL);
+
   values[0].type = GIMP_PDB_STATUS;
 
   *nreturn_vals = 1;
@@ -982,64 +984,96 @@ lcms_image_transform_rgb (gint32                    image,
                           gboolean                  bpc)
 {
   cmsHTRANSFORM    transform   = NULL;
-  cmsUInt32Number  last_format = 0;
+  cmsUInt32Number  lcms_format = 0;
   gint            *layers;
   gint             num_layers;
   gint             i;
+  gboolean         has_alpha = FALSE;
 
   layers = gimp_image_get_layers (image, &num_layers);
 
   for (i = 0; i < num_layers; i++)
     {
-      GimpDrawable    *drawable = gimp_drawable_get (layers[i]);
-      cmsUInt32Number  format;
+      gint32      layer_id     = layers[i];
+      const Babl *layer_format = gimp_drawable_get_format (layer_id);
+      const Babl *type         = babl_format_get_type (layer_format, 0);
 
-      switch (drawable->bpp)
+      if (type == babl_type ("u8"))
         {
-        case 3:
-          format = TYPE_RGB_8;
-          break;
-        case 4:
-          format = TYPE_RGBA_8;
-          break;
+          lcms_format = TYPE_RGB_8;
 
-        default:
-          g_warning ("%s: unexpected bpp", G_STRLOC);
-          continue;
+          if (babl_format_has_alpha (layer_format))
+            {
+              lcms_format = TYPE_RGBA_8;
+              has_alpha   = TRUE;
+            }
         }
-
-      if (! transform || format != last_format)
+      else if (type == babl_type ("u16"))
         {
-          if (transform)
-            cmsDeleteTransform (transform);
+          lcms_format = TYPE_RGB_16;
 
-          transform = cmsCreateTransform (src_profile,  format,
-                                          dest_profile, format,
-                                          intent,
-                                          bpc ?
-                                          cmsFLAGS_BLACKPOINTCOMPENSATION : 0);
+          if (babl_format_has_alpha (layer_format))
+            {
+              lcms_format = TYPE_RGBA_16;
+              has_alpha   = TRUE;
+            }
+        }
+      else if (type == babl_type ("float"))
+        {
+          lcms_format = TYPE_RGB_FLT;
 
-          last_format = format;
+          if (babl_format_has_alpha (layer_format))
+            {
+              lcms_format = TYPE_RGBA_FLT;
+              has_alpha   = TRUE;
+            }
+        }
+      else
+        {
+          g_warning ("layer format has not been coded yet; unable to create transform\n ");
         }
 
       if (transform)
         {
-          lcms_drawable_transform (drawable, transform,
-                                   (gdouble) i / num_layers,
-                                   (gdouble) (i + 1) / num_layers);
+          cmsDeleteTransform (transform);
+        }
+
+      if (lcms_format != 0)
+        {
+          transform = cmsCreateTransform (src_profile,  lcms_format,
+                                          dest_profile, lcms_format,
+                                          intent,
+                                          cmsFLAGS_NOOPTIMIZE);
+          if (bpc)
+            {
+              transform = cmsCreateTransform (src_profile,  lcms_format,
+                                              dest_profile, lcms_format,
+                                              intent,
+                                              cmsFLAGS_BLACKPOINTCOMPENSATION |
+                                              cmsFLAGS_NOOPTIMIZE);
+            }
+
+          if (transform)
+            {
+              lcms_drawable_transform (layer_id,
+                                       has_alpha,
+                                       transform,
+                                       (gdouble) i / num_layers,
+                                       (gdouble) (i + 1) / num_layers);
+            }
         }
       else
         {
           g_warning ("cmsCreateTransform() failed!");
         }
-
-      gimp_drawable_detach (drawable);
     }
 
   if (transform)
-    cmsDeleteTransform(transform);
+    {
+      cmsDeleteTransform (transform);
+    }
 
-  g_free (layers);
+   g_free (layers);
 }
 
 static void
@@ -1052,18 +1086,27 @@ lcms_image_transform_indexed (gint32                    image,
   cmsHTRANSFORM   transform;
   guchar         *cmap;
   gint            num_colors;
+  cmsUInt32Number format = TYPE_RGB_8;
 
   cmap = gimp_image_get_colormap (image, &num_colors);
 
-  transform = cmsCreateTransform (src_profile,  TYPE_RGB_8,
-                                  dest_profile, TYPE_RGB_8,
+  transform = cmsCreateTransform (src_profile,  format,
+                                  dest_profile, format,
                                   intent,
-                                  bpc ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0);
+                                  cmsFLAGS_NOOPTIMIZE  );
+  if (bpc)
+    {
+      transform = cmsCreateTransform (src_profile,  format,
+                                      dest_profile, format,
+                                      intent,
+                                      cmsFLAGS_BLACKPOINTCOMPENSATION |
+                                      cmsFLAGS_NOOPTIMIZE);
+    }
 
   if (transform)
     {
       cmsDoTransform (transform, cmap, cmap, num_colors);
-      cmsDeleteTransform(transform);
+      cmsDeleteTransform (transform);
     }
   else
     {
@@ -1074,70 +1117,97 @@ lcms_image_transform_indexed (gint32                    image,
 }
 
 static void
-lcms_drawable_transform (GimpDrawable  *drawable,
+lcms_drawable_transform (gint32         layer_id,
+                         gboolean       has_alpha,
                          cmsHTRANSFORM  transform,
                          gdouble        progress_start,
                          gdouble        progress_end)
 {
-  GimpPixelRgn   src_rgn;
-  GimpPixelRgn   dest_rgn;
-  gpointer       pr;
-  const gboolean alpha = gimp_drawable_has_alpha (drawable->drawable_id);
-  gdouble        range = progress_end - progress_start;
-  guint          count = 0;
-  guint          done  = 0;
-
-  gimp_pixel_rgn_init (&src_rgn, drawable,
-                       0, 0, drawable->width, drawable->height, FALSE, FALSE);
-  gimp_pixel_rgn_init (&dest_rgn, drawable,
-                       0, 0, drawable->width, drawable->height, TRUE, TRUE);
-
-  for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn);
-       pr != NULL;
-       pr = gimp_pixel_rgns_process (pr))
+  gdouble             range           = progress_end - progress_start;
+  guint               count           = 0;
+  guint               done            = 0;
+  GeglBuffer         *src_buffer      = gimp_drawable_get_buffer (layer_id);
+  const Babl         *layer_format    = gegl_buffer_get_format (src_buffer);
+  gint                bytes_per_pixel = babl_format_get_bytes_per_pixel (layer_format);
+  GeglBuffer         *dest_buffer     = gimp_drawable_get_buffer (layer_id);
+  guint               layer_width     = gegl_buffer_get_width (src_buffer);
+  guint               layer_height    = gegl_buffer_get_height (src_buffer);
+  GeglBufferIterator *iter;
+
+  iter = gegl_buffer_iterator_new (src_buffer,
+                                   GEGL_RECTANGLE (0, 0,
+                                                   layer_width, layer_height),
+                                   0, NULL,
+                                   GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
+
+  gegl_buffer_iterator_add (iter,
+                            dest_buffer,
+                            GEGL_RECTANGLE (0, 0, layer_width, layer_height),
+                            0, NULL,
+                            GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
+
+  while (gegl_buffer_iterator_next (iter))
     {
-      guchar *src  = src_rgn.data;
-      guchar *dest = dest_rgn.data;
-      gint    y;
+      const gfloat *src  = iter->data[0];
+      gfloat       *dest = iter->data[1];
 
-      for (y = 0; y < dest_rgn.h; y++)
+      cmsDoTransform (transform, src, dest, iter->length);
+
+      if (has_alpha)
         {
-          cmsDoTransform (transform, src, dest, dest_rgn.w);
+          const gfloat *src  = iter->data[0];
+          gfloat       *dest = iter->data[1];
 
-          /* copy the alpha values, cmsDoTransform() leaves them untouched */
-          if (alpha)
+          if (bytes_per_pixel == 4)
             {
               const guchar *s = src;
               guchar       *d = dest;
-              gint          w = dest_rgn.w;
 
-              while (w--)
+              while (iter->length--)
                 {
                   d[3] = s[3];
+                  s += 4;
+                  d += 4;
+                }
+            }
+          else if (bytes_per_pixel == 8)
+            {
+              const guint16 *s = src;
+              guint16       *d = dest;
 
+              while (iter->length--)
+                {
+                  d[3] = s[3];
                   s += 4;
                   d += 4;
                 }
             }
+          else if (bytes_per_pixel == 16)
+            {
+              const gfloat *s = src;
+              gfloat       *d = dest;
 
-          src  += src_rgn.rowstride;
-          dest += dest_rgn.rowstride;
+              while (iter->length--)
+                {
+                  d[3] = s[3];
+                  s += 4;
+                  d += 4;
+                }
+            }
         }
+     }
 
-      done += dest_rgn.h * dest_rgn.w;
-
-      if (count++ % 32 == 0)
-        gimp_progress_update (progress_start +
-                              (gdouble) done /
-                              (drawable->width * drawable->height) * range);
-    }
+  g_object_unref (src_buffer);
+  g_object_unref (dest_buffer);
 
-  gimp_progress_update (progress_end);
+  gimp_drawable_update (layer_id, 0, 0, layer_width, layer_height);
 
-  gimp_drawable_flush (drawable);
-  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
-  gimp_drawable_update (drawable->drawable_id,
-                        0, 0, drawable->width, drawable->height);
+  if (count++ % 32 == 0)
+    {
+      gimp_progress_update (progress_start +
+                            (gdouble) done /
+                            (layer_width * layer_height) * range);
+    }
 }
 
 static cmsHPROFILE
diff --git a/plug-ins/common/plugin-defs.pl b/plug-ins/common/plugin-defs.pl
index aecb938..d68b324 100644
--- a/plug-ins/common/plugin-defs.pl
+++ b/plug-ins/common/plugin-defs.pl
@@ -90,7 +90,7 @@
     'illusion' => { ui => 1 },
     'iwarp' => { ui => 1 },
     'jigsaw' => { ui => 1 },
-    'lcms' => { ui => 1, optional => 1, libs => 'LCMS_LIBS', cflags => 'LCMS_CFLAGS' },
+    'lcms' => { ui => 1, gegl => 1, optional => 1, libs => 'LCMS_LIBS', cflags => 'LCMS_CFLAGS' },
     'lens-apply' => { ui => 1 },
     'lens-distortion' => { ui => 1 },
     'lens-flare' => { ui => 1 },
