diff --git a/configure.in b/configure.in
index e835274..ebe5463 100644
--- a/configure.in
+++ b/configure.in
@@ -1950,6 +1950,33 @@ AC_ARG_ENABLE(test-print-backend,
               [enable_test_print_backend=no])
 AM_CONDITIONAL(TEST_PRINT_BACKEND, test "x$enable_test_print_backend" != "xno")
 
+################################################################
+# CMS system checks
+################################################################
+
+AC_ARG_ENABLE(lcms,
+              [AC_HELP_STRING([--disable-lcms]
+                              [disable lcms print backend])],,
+              [enable_lcms=auto])
+
+if test "x$enable_lcms" = "xno"; then
+  AM_CONDITIONAL(HAVE_LCMS, false)
+else
+  PKG_CHECK_MODULES(LCMS, lcms, have_lcms=yes, have_lcms=no)
+  if test "x$have_lcms" = "xno"; then
+    if test "x$enable_lcms" = "xauto"; then
+      AM_CONDITIONAL(HAVE_LCMS, false)
+    else
+      AC_MSG_ERROR([
+*** lcms not found.
+])
+    fi
+  else
+    AC_SUBST(LCMS_CFLAGS)
+    AC_SUBST(LCMS_LIBS)
+    AM_CONDITIONAL(HAVE_LCMS, true)
+  fi
+fi
 
 ################################################################
 # Strip -export-dynamic from the link lines of various libraries
@@ -2148,6 +2175,8 @@ gtk/theme-bits/Makefile
 gtk/tests/Makefile
 modules/Makefile
 modules/other/Makefile
+modules/giomodules/Makefile
+modules/giomodules/lcms/Makefile
 modules/other/gail/Makefile
 modules/other/gail/libgail-util/Makefile
 modules/other/gail/tests/Makefile
diff --git a/demos/icc-profile-fish.png b/demos/icc-profile-fish.png
new file mode 100644
index 0000000..7f8b64b
Binary files /dev/null and b/demos/icc-profile-fish.png differ
diff --git a/demos/testpixbuf-color.c b/demos/testpixbuf-color.c
index 78fa939..af8999c 100644
--- a/demos/testpixbuf-color.c
+++ b/demos/testpixbuf-color.c
@@ -100,6 +100,77 @@ out:
 	return ret;
 }
 
+static gboolean
+transform_image (const gchar *filename, GError **error)
+{
+	GtkWidget *image_test;
+	GtkWidget *dialog;
+	GtkWidget *vbox;
+	gint response;
+	GdkPixbuf *pixbuf;
+	GtkColorEngine *engine = NULL;
+	GtkColorProfile *profile = NULL;
+	GtkColorTransform *transform = NULL;
+	gchar *icc_profile = NULL;
+	gsize len = 0;
+	gboolean ret;
+	const gchar *option;
+
+	image_test = gtk_image_new_from_file (filename);
+	pixbuf = gtk_image_get_pixbuf (GTK_IMAGE(image_test));
+
+	/* check values */
+	option = gdk_pixbuf_get_option (pixbuf, "icc-profile");
+	if (option == NULL) {
+		*error = g_error_new (1, 0, "no profile set");
+		goto out;
+	}
+
+	/* decode base64 */
+	icc_profile = (gchar *) g_base64_decode (option, &len);
+	if (len == 0) {
+		*error = g_error_new (1, 0, "no embedded profile");
+		goto out;
+	}
+
+        /* transform this image with the embedded profile */
+        engine = gtk_color_engine_get_default ();
+        profile = gtk_color_engine_create_profile (engine, (const guint8 *)icc_profile, len, error);
+        if (profile == NULL) {
+                ret = FALSE;
+                goto out;
+        }
+        transform = gtk_color_engine_create_transform_from_profiles (engine, profile, NULL);
+        ret = gtk_color_transform_apply_in_place (transform, pixbuf, error);
+        if (!ret)
+                goto out;
+
+	/* show in a dialog as an example */
+	dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "Are the fish yellow?");
+	vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+	gtk_box_pack_end (GTK_BOX(vbox), image_test, TRUE, TRUE, 12);
+	gtk_widget_set_size_request (GTK_WIDGET(image_test), 300, 300);
+	gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+	gtk_widget_show (image_test);
+
+        /* ask the user to ensure the image was converted */
+	response = gtk_dialog_run (GTK_DIALOG (dialog));
+	if (response != GTK_RESPONSE_YES) {
+		ret = FALSE;
+		*error = g_error_new (1, 0, "failed to convert fish");
+		goto out;
+	}
+out:
+        if (transform != NULL)
+                g_object_unref (transform);
+        if (profile != NULL)
+                g_object_unref (profile);
+        if (engine != NULL)
+                g_object_unref (engine);
+	g_free (icc_profile);
+	return ret;
+}
+
 int
 main (int argc, char **argv)
 {
@@ -118,6 +189,15 @@ main (int argc, char **argv)
 					       0, 0, 0, 0, 150, 160);
 
 	/* PASS */
+	g_debug ("try to render color corrected image");
+	ret = transform_image ("icc-profile-fish.png", &error);
+	if (!ret) {
+		g_warning ("FAILED: did not load image: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* PASS */
 	g_debug ("try to save PNG with a profile");
 	ret = save_image_png ("icc-profile.png", pixbuf, &error);
 	if (!ret) {
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index c3d950f..ecc410e 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -196,8 +196,11 @@ gtk_public_h_sources =          \
 	gtkcheckmenuitem.h	\
 	gtkclipboard.h		\
 	gtkcolorbutton.h	\
-	gtkcolorsel.h		\
+	gtkcolorengine.h	\
+	gtkcolorprofile.h	\
 	gtkcolorseldialog.h	\
+	gtkcolorsel.h		\
+	gtkcolortransform.h	\
 	gtkcombobox.h		\
 	gtkcomboboxentry.h	\
 	gtkcontainer.h		\
@@ -380,6 +383,9 @@ gtk_private_h_sources =		\
 	gtkfilesystem.h		\
 	gtkfilesystemmodel.h	\
 	gtkiconcache.h		\
+	gtkcolorenginefallback.h	\
+	gtkcolorprofilefallback.h	\
+	gtkcolortransformfallback.h	\
 	gtkintl.h		\
 	gtkkeyhash.h		\
 	gtkmnemonichash.h	\
@@ -455,6 +461,12 @@ gtk_base_c_sources =            \
 	gtkcolorbutton.c	\
 	gtkcolorsel.c		\
 	gtkcolorseldialog.c	\
+	gtkcolorengine.c	\
+	gtkcolorprofile.c	\
+	gtkcolortransform.c	\
+	gtkcolorenginefallback.c	\
+	gtkcolorprofilefallback.c	\
+	gtkcolortransformfallback.c	\
 	gtkcombobox.c		\
 	gtkcomboboxentry.c	\
 	gtkcontainer.c		\
diff --git a/gtk/gtk.h b/gtk/gtk.h
index bbeabae..d8b8015 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -67,8 +67,11 @@
 #include <gtk/gtkcheckmenuitem.h>
 #include <gtk/gtkclipboard.h>
 #include <gtk/gtkcolorbutton.h>
-#include <gtk/gtkcolorsel.h>
+#include <gtk/gtkcolorengine.h>
+#include <gtk/gtkcolorprofile.h>
 #include <gtk/gtkcolorseldialog.h>
+#include <gtk/gtkcolorsel.h>
+#include <gtk/gtkcolortransform.h>
 #include <gtk/gtkcombobox.h>
 #include <gtk/gtkcomboboxentry.h>
 #include <gtk/gtkcontainer.h>
diff --git a/gtk/gtkcolorengine.c b/gtk/gtkcolorengine.c
new file mode 100644
index 0000000..8ff4c84
--- /dev/null
+++ b/gtk/gtkcolorengine.c
@@ -0,0 +1,214 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gtk-color-engine
+ * @short_description: Creates %GtkColorProfile and %GtkColorTransform objects
+ * @Title: GtkColorEngine
+ * @See_also:#GtkColorProfile
+ *
+ * Loads the default color engine, and allows the user to create
+ * %GtkColorProfile and %GtkColorTransform objects to use in color transforms.
+ */
+
+#include "config.h"
+
+#include "gtkprivate.h"
+#include "gtkcolorengine.h"
+#include "gtkcolorenginefallback.h"
+
+static void gtk_color_engine_finalize (GObject * object);
+
+G_DEFINE_TYPE (GtkColorEngine, gtk_color_engine, G_TYPE_OBJECT)
+
+/**
+ * gtk_color_engine_create_transform:
+ * @color_engine: a %GtkColorEngine
+ *
+ * Gets a new transform from the engine.
+ *
+ * Return value: a new %GtkColorTransform instance, free with g_object_unref()
+ **/
+GtkColorTransform *
+gtk_color_engine_create_transform (GtkColorEngine *color_engine)
+{
+  GtkColorEngineClass *klass = GTK_COLOR_ENGINE_GET_CLASS (color_engine);
+
+  g_return_val_if_fail (GTK_IS_COLOR_ENGINE (color_engine), NULL);
+  g_return_val_if_fail (klass->create_transform != NULL, NULL);
+
+  /* proxy */
+  return klass->create_transform ();
+}
+
+/**
+ * gtk_color_engine_create_transform_from_profiles:
+ * @color_engine: a %GtkColorEngine
+ * @input_profile: a %GtkColorProfile, or %NULL
+ * @output_profile: a %GtkColorProfile, or %NULL
+ * @error: a %GError, or %NULL
+ *
+ * Gets a new transform from the engine which is preset with two profiles.
+ *
+ * Return value: a new %GtkColorTransform instance, free with g_object_unref(), or %NULL
+ **/
+GtkColorTransform *
+gtk_color_engine_create_transform_from_profiles (GtkColorEngine  *color_engine,
+                                                 GtkColorProfile *input_profile,
+                                                 GtkColorProfile *output_profile)
+{
+  GtkColorTransform *color_transform;
+
+  g_return_val_if_fail (GTK_IS_COLOR_ENGINE (color_engine), NULL);
+  g_return_val_if_fail (GTK_IS_COLOR_PROFILE (input_profile) || input_profile == NULL, NULL);
+  g_return_val_if_fail (GTK_IS_COLOR_PROFILE (output_profile) || output_profile == NULL, NULL);
+
+  color_transform = gtk_color_engine_create_transform (color_engine);
+  gtk_color_transform_set_input_profile (color_transform, input_profile);
+  gtk_color_transform_set_output_profile (color_transform, output_profile);
+  return color_transform;
+}
+
+/**
+ * gtk_color_engine_create_profile:
+ * @color_engine: a %GtkColorEngine
+ * @data: the COLOR engine data
+ * @length: the COLOR engine data
+ * @error: a %GError, or %NULL
+ *
+ * Loads an ICC file as an input engine.
+ *
+ * Return value: %TRUE if the engine was opened, otherwise %FALSE and @error is set.
+ **/
+GtkColorProfile *
+gtk_color_engine_create_profile (GtkColorEngine *color_engine,
+                                 const guint8  *data,
+                                 gsize          length,
+                                 GError       **error)
+{
+  gboolean ret;
+  GtkColorProfile *color_profile;
+  GtkColorEngineClass *klass = GTK_COLOR_ENGINE_GET_CLASS (color_engine);
+
+  g_return_val_if_fail (GTK_IS_COLOR_ENGINE (color_engine), FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (klass->create_profile != NULL, NULL);
+
+  /* create and set */
+  color_profile = klass->create_profile ();
+  ret = gtk_color_profile_set_from_data (color_profile, data, length, error);
+  if (!ret)
+    {
+      g_object_unref (color_profile);
+      color_profile = NULL;
+      goto out;
+    }
+out:
+  return color_profile;
+}
+
+/**
+ * gtk_color_engine_class_init:
+ **/
+static void
+gtk_color_engine_class_init (GtkColorEngineClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  object_class->finalize = gtk_color_engine_finalize;
+}
+
+/**
+ * gtk_color_engine_init:
+ **/
+static void
+gtk_color_engine_init (GtkColorEngine *color_engine)
+{
+}
+
+/**
+ * gtk_color_engine_finalize:
+ **/
+static void
+gtk_color_engine_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gtk_color_engine_parent_class)->finalize (object);
+}
+
+/**
+ * gtk_color_engine_get_default_cb:
+ **/
+static gpointer
+gtk_color_engine_get_default_cb (gpointer data)
+{
+  GIOExtensionPoint *ep;
+  GList *extensions;
+
+  /* find our extension point */
+  ep = g_io_extension_point_lookup (GTK_COLOR_ENGINE_EXTENSION_POINT_NAME);
+  if (ep == NULL)
+    goto out;
+
+  /* try what we've got */
+  extensions = g_io_extension_point_get_extensions (ep);
+  if (extensions != NULL)
+    return (gpointer) g_io_extension_get_type (extensions->data);
+out:
+  return (gpointer) G_TYPE_INVALID;
+}
+
+static gpointer gtk_color_engine_singleton = NULL;
+
+/**
+ * gtk_color_engine_get_default:
+ * @error: a %GError, or %NULL
+ *
+ * Gets the default color engine. If no engines are installed then a fallback
+ * engine is used which just copies the pixbuf data without modification.
+ *
+ * Return value: a new %GtkColorEngine object. Use g_object_unref() when done.
+ **/
+GtkColorEngine *
+gtk_color_engine_get_default (void)
+{
+  static GOnce once_init = G_ONCE_INIT;
+  GType type;
+
+  _gtk_io_modules_ensure_loaded ();
+
+  /* get the type */
+  g_once (&once_init, gtk_color_engine_get_default_cb, NULL);
+  type = (GType) once_init.retval;
+  if (type == G_TYPE_INVALID)
+    type = GTK_TYPE_COLOR_ENGINE_FALLBACK;
+
+  /* return a reference to a singleton object */
+  if (gtk_color_engine_singleton != NULL) {
+    g_object_ref (gtk_color_engine_singleton);
+  } else {
+    gtk_color_engine_singleton = g_object_new (type, NULL);
+    g_object_add_weak_pointer (gtk_color_engine_singleton, &gtk_color_engine_singleton);
+  }
+  return GTK_COLOR_ENGINE (gtk_color_engine_singleton);
+}
+
+#define __GTK_COLOR_ENGINE_C__
+#include "gtkaliasdef.c"
diff --git a/gtk/gtkcolorengine.h b/gtk/gtkcolorengine.h
new file mode 100644
index 0000000..8df7259
--- /dev/null
+++ b/gtk/gtkcolorengine.h
@@ -0,0 +1,86 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_COLOR_ENGINE_H
+#define __GTK_COLOR_ENGINE_H
+
+#include <glib-object.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "gtkcolorprofile.h"
+#include "gtkcolortransform.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLOR_ENGINE               (gtk_color_engine_get_type ())
+#define GTK_COLOR_ENGINE(o)                 (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLOR_ENGINE, GtkColorEngine))
+#define GTK_COLOR_ENGINE_CLASS(k)           (G_TYPE_CHECK_CLASS_CAST((k), GTK_TYPE_COLOR_ENGINE, GtkColorEngineClass))
+#define GTK_IS_COLOR_ENGINE(o)              (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLOR_ENGINE))
+#define GTK_IS_COLOR_ENGINE_CLASS(k)        (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLOR_ENGINE))
+#define GTK_COLOR_ENGINE_GET_CLASS(o)       (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLOR_ENGINE, GtkColorEngineClass))
+
+typedef struct _GtkColorEnginePrivate       GtkColorEnginePrivate;
+typedef struct _GtkColorEngine              GtkColorEngine;
+typedef struct _GtkColorEngineClass         GtkColorEngineClass;
+
+struct _GtkColorEngine
+{
+  GObject parent;
+  GtkColorEnginePrivate *priv;
+};
+
+#define GTK_COLOR_ENGINE_EXTENSION_POINT_NAME "gtk-color-engine"
+
+struct _GtkColorEngineClass
+{
+        GObjectClass parent_class;
+        GtkColorProfile     *(*create_profile)    (void);
+        GtkColorTransform   *(*create_transform)  (void);
+        /* padding for future expansion */
+        void (*_gtk_reserved1) (void);
+        void (*_gtk_reserved2) (void);
+        void (*_gtk_reserved3) (void);
+        void (*_gtk_reserved4) (void);
+        void (*_gtk_reserved5) (void);
+};
+
+GType                   gtk_color_engine_get_type           (void);
+GtkColorEngine         *gtk_color_engine_get_default        (void);
+
+/* new profile */
+GtkColorProfile        *gtk_color_engine_create_profile (GtkColorEngine    *color_engine,
+                                                         const guint8      *data,
+                                                         gsize              length,
+                                                         GError           **error);
+
+/* new transform */
+GtkColorTransform      *gtk_color_engine_create_transform                (GtkColorEngine    *color_engine);
+GtkColorTransform      *gtk_color_engine_create_transform_from_profiles  (GtkColorEngine    *color_engine,
+                                                                          GtkColorProfile   *input_profile,
+                                                                          GtkColorProfile   *output_profile);
+
+G_END_DECLS
+
+#endif /* __GTK_COLOR_ENGINE_H */
+
diff --git a/gtk/gtkcolorenginefallback.c b/gtk/gtkcolorenginefallback.c
new file mode 100644
index 0000000..27736fe
--- /dev/null
+++ b/gtk/gtkcolorenginefallback.c
@@ -0,0 +1,64 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gtkcolorenginefallback.h"
+#include "gtkcolorprofilefallback.h"
+#include "gtkcolortransformfallback.h"
+
+static void     gtk_color_engine_fallback_finalize  (GObject     *object);
+
+G_DEFINE_TYPE (GtkColorEngineFallback, gtk_color_engine_fallback, GTK_TYPE_COLOR_ENGINE)
+
+/**
+ * gtk_color_engine_fallback_class_init:
+ **/
+static void
+gtk_color_engine_fallback_class_init (GtkColorEngineFallbackClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkColorEngineClass *parent_class = GTK_COLOR_ENGINE_CLASS (klass);
+  object_class->finalize = gtk_color_engine_fallback_finalize;
+
+  parent_class->create_profile = _gtk_color_profile_fallback_new;
+  parent_class->create_transform = _gtk_color_transform_fallback_new;
+}
+
+/**
+ * gtk_color_engine_fallback_init:
+ **/
+static void
+gtk_color_engine_fallback_init (GtkColorEngineFallback *color_engine_fallback)
+{
+}
+
+/**
+ * gtk_color_engine_fallback_finalize:
+ **/
+static void
+gtk_color_engine_fallback_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gtk_color_engine_fallback_parent_class)->finalize (object);
+}
+
diff --git a/gtk/gtkcolorenginefallback.h b/gtk/gtkcolorenginefallback.h
new file mode 100644
index 0000000..a50d35b
--- /dev/null
+++ b/gtk/gtkcolorenginefallback.h
@@ -0,0 +1,61 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_COLOR_ENGINE_FALLBACK_H
+#define __GTK_COLOR_ENGINE_FALLBACK_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLOR_ENGINE_FALLBACK          (gtk_color_engine_fallback_get_type ())
+#define GTK_COLOR_ENGINE_FALLBACK(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLOR_ENGINE_FALLBACK, GtkColorEngineFallback))
+#define GTK_COLOR_ENGINE_FALLBACK_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), GTK_TYPE_COLOR_ENGINE_FALLBACK, GtkColorEngineFallbackClass))
+#define GTK_IS_COLOR_ENGINE_FALLBACK(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLOR_ENGINE_FALLBACK))
+#define GTK_IS_COLOR_ENGINE_FALLBACK_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLOR_ENGINE_FALLBACK))
+#define GTK_COLOR_ENGINE_FALLBACK_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLOR_ENGINE_FALLBACK, GtkColorEngineFallbackClass))
+
+typedef struct _GtkColorEngineFallback        GtkColorEngineFallback;
+typedef struct _GtkColorEngineFallbackClass   GtkColorEngineFallbackClass;
+
+struct _GtkColorEngineFallback
+{
+   GtkColorEngine parent;
+};
+
+struct _GtkColorEngineFallbackClass
+{
+  GtkColorEngineClass parent_class;
+  /* padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+  void (*_gtk_reserved5) (void);
+};
+
+GType      gtk_color_engine_fallback_get_type    (void);
+
+G_END_DECLS
+
+#endif /* __GTK_COLOR_ENGINE_FALLBACK_H */
+
diff --git a/gtk/gtkcolorprofile.c b/gtk/gtkcolorprofile.c
new file mode 100644
index 0000000..a53a1e5
--- /dev/null
+++ b/gtk/gtkcolorprofile.c
@@ -0,0 +1,99 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gtk-color-profile
+ * @Short_description: An object describing a color profile
+ * @Title: GtkColorProfile
+ * @See_also:#GtkColorTransform
+ *
+ * Describes a profile used for color transforms.
+ */
+
+#include "config.h"
+
+#include "gtkcolorprofile.h"
+
+static void gtk_color_profile_finalize (GObject * object);
+
+G_DEFINE_TYPE (GtkColorProfile, gtk_color_profile, G_TYPE_OBJECT)
+
+/**
+ * gtk_color_profile_set_from data:
+ * @color_profile: a %GtkColorProfile
+ * @data: the ICC profile data
+ * @length: the size of the data in bytes
+ * @error: a %GError, or %NULL
+ *
+ * Loads ICC data into the profile, overwriting the old data if it was set.
+ *
+ * Return value: %TRUE if the profile was set, otherwise %FALSE and @error is set.
+ **/
+gboolean
+gtk_color_profile_set_from_data (GtkColorProfile *color_profile,
+                                 const guint8    *data,
+                                 gsize            length,
+                                 GError         **error)
+{
+  gboolean ret;
+  GtkColorProfileClass *klass = GTK_COLOR_PROFILE_GET_CLASS (color_profile);
+
+  g_return_val_if_fail (GTK_IS_COLOR_PROFILE (color_profile), FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (klass->set_from_data != NULL, FALSE);
+
+  /* FIXME: check header bytes to ensure this is an ICC profile */
+
+  /* open new profile */
+  ret = klass->set_from_data (color_profile, data, length, error);
+  return ret;
+}
+
+/**
+ * gtk_color_profile_class_init:
+ **/
+static void
+gtk_color_profile_class_init (GtkColorProfileClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  object_class->finalize = gtk_color_profile_finalize;
+}
+
+/**
+ * gtk_color_profile_init:
+ **/
+static void
+gtk_color_profile_init (GtkColorProfile *color_profile)
+{
+}
+
+/**
+ * gtk_color_profile_finalize:
+ **/
+static void
+gtk_color_profile_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gtk_color_profile_parent_class)->finalize (object);
+}
+
+#define __GTK_COLOR_PROFILE_C__
+#include "gtkaliasdef.c"
diff --git a/gtk/gtkcolorprofile.h b/gtk/gtkcolorprofile.h
new file mode 100644
index 0000000..281e877
--- /dev/null
+++ b/gtk/gtkcolorprofile.h
@@ -0,0 +1,74 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_COLOR_PROFILE_H
+#define __GTK_COLOR_PROFILE_H
+
+#include <glib-object.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLOR_PROFILE               (gtk_color_profile_get_type ())
+#define GTK_COLOR_PROFILE(o)                 (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLOR_PROFILE, GtkColorProfile))
+#define GTK_COLOR_PROFILE_CLASS(k)           (G_TYPE_CHECK_CLASS_CAST((k), GTK_TYPE_COLOR_PROFILE, GtkColorProfileClass))
+#define GTK_IS_COLOR_PROFILE(o)              (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLOR_PROFILE))
+#define GTK_IS_COLOR_PROFILE_CLASS(k)        (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLOR_PROFILE))
+#define GTK_COLOR_PROFILE_GET_CLASS(o)       (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLOR_PROFILE, GtkColorProfileClass))
+
+typedef struct _GtkColorProfilePrivate       GtkColorProfilePrivate;
+typedef struct _GtkColorProfile              GtkColorProfile;
+typedef struct _GtkColorProfileClass         GtkColorProfileClass;
+
+struct _GtkColorProfile
+{
+  GObject parent;
+  GtkColorProfilePrivate *priv;
+};
+
+struct _GtkColorProfileClass
+{
+        GObjectClass parent_class;
+        gboolean    (*set_from_data)  (GtkColorProfile  *color_profile,
+                                       const guint8     *data,
+                                       gsize             length,
+                                       GError          **error);
+        /* padding for future expansion */
+        void (*_gtk_reserved1) (void);
+        void (*_gtk_reserved2) (void);
+        void (*_gtk_reserved3) (void);
+        void (*_gtk_reserved4) (void);
+        void (*_gtk_reserved5) (void);
+};
+
+GType                    gtk_color_profile_get_type       (void);
+gboolean                 gtk_color_profile_set_from_data  (GtkColorProfile   *color_profile,
+                                                           const guint8      *data,
+                                                           gsize              length,
+                                                           GError           **error);
+
+G_END_DECLS
+
+#endif /* __GTK_COLOR_PROFILE_H */
+
diff --git a/gtk/gtkcolorprofilefallback.c b/gtk/gtkcolorprofilefallback.c
new file mode 100644
index 0000000..06d968a
--- /dev/null
+++ b/gtk/gtkcolorprofilefallback.c
@@ -0,0 +1,84 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gtkcolorprofilefallback.h"
+
+static void     gtk_color_profile_fallback_finalize  (GObject     *object);
+
+G_DEFINE_TYPE (GtkColorProfileFallback, gtk_color_profile_fallback, GTK_TYPE_COLOR_PROFILE)
+
+/**
+ * gtk_color_profile_fallback_set_from_data:
+ **/
+static gboolean
+gtk_color_profile_fallback_set_from_data (GtkColorProfile *color_profile,
+                                          const guint8    *data,
+                                          gsize            length,
+                                          GError         **error)
+{
+	return TRUE;
+}
+
+/**
+ * gtk_color_profile_fallback_class_init:
+ **/
+static void
+gtk_color_profile_fallback_class_init (GtkColorProfileFallbackClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkColorProfileClass *parent_class = GTK_COLOR_PROFILE_CLASS (klass);
+  object_class->finalize = gtk_color_profile_fallback_finalize;
+
+  parent_class->set_from_data = gtk_color_profile_fallback_set_from_data;
+}
+
+/**
+ * gtk_color_profile_fallback_init:
+ **/
+static void
+gtk_color_profile_fallback_init (GtkColorProfileFallback *color_profile_fallback)
+{
+}
+
+/**
+ * gtk_color_profile_fallback_finalize:
+ **/
+static void
+gtk_color_profile_fallback_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gtk_color_profile_fallback_parent_class)->finalize (object);
+}
+
+/**
+ * _gtk_color_profile_fallback_new:
+ **/
+GtkColorProfile *
+_gtk_color_profile_fallback_new (void)
+{
+  GtkColorProfileFallback *color_profile;
+  color_profile = g_object_new (GTK_TYPE_COLOR_PROFILE_FALLBACK, NULL);
+  return GTK_COLOR_PROFILE (color_profile);
+}
+
diff --git a/gtk/gtkcolorprofilefallback.h b/gtk/gtkcolorprofilefallback.h
new file mode 100644
index 0000000..bcde2c6
--- /dev/null
+++ b/gtk/gtkcolorprofilefallback.h
@@ -0,0 +1,62 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_COLOR_PROFILE_FALLBACK_H
+#define __GTK_COLOR_PROFILE_FALLBACK_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLOR_PROFILE_FALLBACK          (gtk_color_profile_fallback_get_type ())
+#define GTK_COLOR_PROFILE_FALLBACK(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLOR_PROFILE_FALLBACK, GtkColorProfileFallback))
+#define GTK_COLOR_PROFILE_FALLBACK_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), GTK_TYPE_COLOR_PROFILE_FALLBACK, GtkColorProfileFallbackClass))
+#define GTK_IS_COLOR_PROFILE_FALLBACK(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLOR_PROFILE_FALLBACK))
+#define GTK_IS_COLOR_PROFILE_FALLBACK_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLOR_PROFILE_FALLBACK))
+#define GTK_COLOR_PROFILE_FALLBACK_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLOR_PROFILE_FALLBACK, GtkColorProfileFallbackClass))
+
+typedef struct _GtkColorProfileFallback        GtkColorProfileFallback;
+typedef struct _GtkColorProfileFallbackClass   GtkColorProfileFallbackClass;
+
+struct _GtkColorProfileFallback
+{
+   GtkColorProfile parent;
+};
+
+struct _GtkColorProfileFallbackClass
+{
+  GtkColorProfileClass parent_class;
+  /* padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+  void (*_gtk_reserved5) (void);
+};
+
+GType            gtk_color_profile_fallback_get_type    (void);
+GtkColorProfile *_gtk_color_profile_fallback_new        (void);
+
+G_END_DECLS
+
+#endif /* __GTK_COLOR_PROFILE_FALLBACK_H */
+
diff --git a/gtk/gtkcolortransform.c b/gtk/gtkcolortransform.c
new file mode 100644
index 0000000..e6b87d4
--- /dev/null
+++ b/gtk/gtkcolortransform.c
@@ -0,0 +1,403 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gtk-color-transform
+ * @short_description: Converts %GdkPixbuf's using %GtkColorProfile's
+ * @Title: GtkColorTransform
+ * @See_also:#GtkColorProfile
+ *
+ * Converts %GdkPixbuf's from one colorspace to another, and applies ICC input
+ * and output profiles if required. Extensions are automatically loaded at
+ * startup, but none are shipped by default.
+ */
+
+#include "config.h"
+#include <gdk/gdk.h>
+
+#include "gtktypeutils.h"
+#include "gtkcolortransform.h"
+
+static void gtk_color_transform_finalize (GObject * object);
+
+#define GTK_COLOR_TRANSFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_COLOR_TRANSFORM, GtkColorTransformPrivate))
+
+/**
+ * GtkColorTransformPrivate:
+ *
+ * Private #GtkColorTransform data
+ **/
+struct _GtkColorTransformPrivate
+{
+  GtkColorIntent     intent;
+  gboolean           black_point_compensation;
+  GtkColorProfile   *input_profile;
+  GtkColorProfile   *output_profile;
+};
+
+enum
+{
+  PROP_0,
+  PROP_INTENT,
+  PROP_BLACK_POINT_COMPENSATION,
+  PROP_INPUT_PROFILE,
+  PROP_OUTPUT_PROFILE,
+  PROP_LAST
+};
+
+G_DEFINE_TYPE (GtkColorTransform, gtk_color_transform, G_TYPE_OBJECT)
+
+/**
+ * gtk_color_transform_set_input_profile:
+ * @color_transform: a %GtkColorTransform
+ * @profile: a %GtkColorProfile, or %NULL
+ * @length: the size of the data in bytes
+ *
+ * Sets the profile for use as the input transform. If the @profile is %NULL,
+ * then the profile is cleared.
+ *
+ * Return value: %TRUE if the profile was set, otherwise %FALSE.
+ **/
+void
+gtk_color_transform_set_input_profile (GtkColorTransform *color_transform,
+                                       GtkColorProfile   *profile)
+{
+  GtkColorTransformPrivate *priv = color_transform->priv;
+
+  g_return_if_fail (GTK_IS_COLOR_TRANSFORM (color_transform));
+  g_return_if_fail (GTK_IS_COLOR_PROFILE (profile) || profile == NULL);
+
+  /* close old profile */
+  if (profile == NULL)
+    {
+      if (priv->input_profile != NULL)
+        {
+          g_object_unref (priv->input_profile);
+          priv->input_profile = NULL;
+          g_object_notify (G_OBJECT (color_transform), "input-profile");
+        }
+      return;
+    }
+
+  /* set new profile */
+  g_object_set (color_transform, "input-profile", profile, NULL);
+}
+
+/**
+ * gtk_color_transform_set_output_profile:
+ * @color_transform: a %GtkColorTransform
+ * @data: the ICC profile data
+ * @length: the size of the data in bytes
+ *
+ * Loads an ICC file as an output profile.
+ *
+ * Return value: %TRUE if the profile was opened, otherwise %FALSE.
+ **/
+void
+gtk_color_transform_set_output_profile (GtkColorTransform *color_transform,
+                                        GtkColorProfile   *profile)
+{
+  GtkColorTransformPrivate *priv = color_transform->priv;
+
+  g_return_if_fail (GTK_IS_COLOR_TRANSFORM (color_transform));
+  g_return_if_fail (GTK_IS_COLOR_PROFILE (profile) || profile == NULL);
+
+  /* close old profile */
+  if (profile == NULL)
+    {
+      if (priv->output_profile != NULL)
+        {
+          g_object_unref (priv->output_profile);
+          priv->output_profile = NULL;
+          g_object_notify (G_OBJECT (color_transform), "output-profile");
+        }
+      return;
+    }
+
+  /* set new profile */
+  g_object_set (color_transform, "output-profile", profile, NULL);
+}
+
+/**
+ * gtk_color_transform_apply_in_place:
+ * @color_transform: a %GtkColorTransform
+ * @pixbuf: a %GdkPixbuf
+ * @error: a %GError, or %NULL
+ *
+ * Transform the pixmap in-place, destroying the old content.
+ *
+ * This function will be faster than gtk_color_transform_apply(), as a new
+ * pixmap does not have to be allocated, and the conversion can be done
+ * one row at a time.
+ *
+ * If the input profile or output profile have not been set then these are
+ * assumed to be sRGB.
+ *
+ * Return value: %TRUE if the pixbuf was transformed, otherwise %FALSE and @error is set.
+ **/
+gboolean
+gtk_color_transform_apply_in_place (GtkColorTransform *color_transform,
+                                    GdkPixbuf         *pixbuf,
+                                    GError           **error)
+{
+  gboolean ret;
+  GtkColorTransformClass *klass = GTK_COLOR_TRANSFORM_GET_CLASS (color_transform);
+
+  g_return_val_if_fail (pixbuf != NULL, FALSE);
+  g_return_val_if_fail (klass->apply_in_place != NULL, FALSE);
+
+  /* proxy */
+  ret = klass->apply_in_place (color_transform,
+                               pixbuf,
+                               error);
+  return ret;
+}
+
+/**
+ * gtk_color_transform_apply:
+ * @color_transform: a %GtkColorTransform
+ * @pixbuf_in: the source %GdkPixbuf
+ * @pixbuf_out: the destination %GdkPixbuf
+ * @error: a %GError, or %NULL
+ *
+ * Transform from one pixmap to another.
+ *
+ * This function will be slower than gtk_color_transform_apply_in_place(), as a new
+ * pixmap will have to be allocated by your application.
+ *
+ * If the input profile or output profile have not been set then these are
+ * assumed to be sRGB.
+ *
+ * Return value: %TRUE if the pixbuf was transformed, otherwise %FALSE and @error is set.
+ **/
+gboolean
+gtk_color_transform_apply (GtkColorTransform *color_transform,
+                           GdkPixbuf         *pixbuf_in,
+                           GdkPixbuf         *pixbuf_out,
+                           GError           **error)
+{
+  gboolean ret = FALSE;
+  GtkColorTransformClass *klass = GTK_COLOR_TRANSFORM_GET_CLASS (color_transform);
+
+  g_return_val_if_fail (pixbuf_in != NULL, FALSE);
+  g_return_val_if_fail (pixbuf_out != NULL, FALSE);
+  g_return_val_if_fail (klass->apply != NULL, FALSE);
+
+  /* check the pixbufs are compatible */
+  if (pixbuf_in != pixbuf_out)
+    {
+      if (gdk_pixbuf_get_colorspace (pixbuf_in) != gdk_pixbuf_get_colorspace (pixbuf_in))
+        {
+          if (error != NULL)
+            *error = g_error_new (1, 0, "cannot transform, colorspace is not the same");
+          goto out;
+        }
+      if (gdk_pixbuf_get_height (pixbuf_in) != gdk_pixbuf_get_height (pixbuf_in))
+        {
+          if (error != NULL)
+            *error = g_error_new (1, 0, "cannot transform, height is not the same");
+          goto out;
+        }
+      if (gdk_pixbuf_get_width (pixbuf_in) != gdk_pixbuf_get_width (pixbuf_in))
+        {
+          if (error != NULL)
+            *error = g_error_new (1, 0, "cannot transform, width is not the same");
+          goto out;
+        }
+      if (gdk_pixbuf_get_rowstride (pixbuf_in) != gdk_pixbuf_get_rowstride (pixbuf_in))
+        {
+          if (error != NULL)
+            *error = g_error_new (1, 0, "cannot transform, rowstride is not the same");
+          goto out;
+        }
+      if (gdk_pixbuf_get_bits_per_sample (pixbuf_in) != gdk_pixbuf_get_bits_per_sample (pixbuf_in))
+        {
+          if (error != NULL)
+            *error = g_error_new (1, 0, "cannot transform, bits_per_sample is not the same");
+          goto out;
+        }
+      if (gdk_pixbuf_get_has_alpha (pixbuf_in) != gdk_pixbuf_get_has_alpha (pixbuf_in))
+        {
+          if (error != NULL)
+            *error = g_error_new (1, 0, "cannot transform, has_alpha is not the same");
+          goto out;
+        }
+    }
+
+  /* proxy */
+  ret = klass->apply (color_transform,
+                      pixbuf_in,
+                      pixbuf_out,
+                      error);
+out:
+  return ret;
+}
+
+/**
+ * gtk_color_transform_get_property:
+ **/
+static void
+gtk_color_transform_get_property (GObject *object, guint prop_id,
+                                  GValue *value, GParamSpec *pspec)
+{
+  GtkColorTransform *color_transform = GTK_COLOR_TRANSFORM (object);
+  GtkColorTransformPrivate *priv = color_transform->priv;
+
+  switch (prop_id)
+    {
+    case PROP_INTENT:
+      g_value_set_enum (value, priv->intent);
+      break;
+    case PROP_BLACK_POINT_COMPENSATION:
+      g_value_set_boolean (value, priv->black_point_compensation);
+      break;
+    case PROP_INPUT_PROFILE:
+      g_value_set_object (value, priv->input_profile);
+      break;
+    case PROP_OUTPUT_PROFILE:
+      g_value_set_object (value, priv->output_profile);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+/**
+ * gtk_color_transform_set_property:
+ **/
+static void
+gtk_color_transform_set_property (GObject *object, guint prop_id,
+                                  const GValue *value, GParamSpec *pspec)
+{
+  GtkColorTransform *color_transform = GTK_COLOR_TRANSFORM (object);
+  GtkColorTransformPrivate *priv = color_transform->priv;
+
+  switch (prop_id)
+    {
+    case PROP_INTENT:
+      priv->intent = g_value_get_enum (value);
+      g_object_notify (object, "intent");
+      break;
+    case PROP_BLACK_POINT_COMPENSATION:
+      priv->black_point_compensation = g_value_get_boolean (value);
+      g_object_notify (object, "black-point-compensation");
+      break;
+    case PROP_INPUT_PROFILE:
+      if (priv->input_profile)
+        g_object_unref (priv->input_profile);
+      priv->input_profile = g_value_dup_object (value);
+      g_object_notify (object, "input-profile");
+      break;
+    case PROP_OUTPUT_PROFILE:
+      if (priv->output_profile)
+        g_object_unref (priv->output_profile);
+      priv->output_profile = g_value_dup_object (value);
+      g_object_notify (object, "output-profile");
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+/**
+ * gtk_color_transform_class_init:
+ **/
+static void
+gtk_color_transform_class_init (GtkColorTransformClass *klass)
+{
+  GParamSpec *pspec;
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  object_class->finalize = gtk_color_transform_finalize;
+  object_class->get_property = gtk_color_transform_get_property;
+  object_class->set_property = gtk_color_transform_set_property;
+
+  /**
+    * GtkColorTransform:intent:
+    */
+  pspec = g_param_spec_enum ("intent", "rendering intent", NULL,
+                             GTK_TYPE_COLOR_INTENT,
+                             GTK_COLOR_INTENT_PERCEPTUAL,
+                             G_PARAM_READWRITE);
+  g_object_class_install_property (object_class, PROP_INTENT, pspec);
+
+  /**
+   * GtkColorTransform:black-point-compensation:
+   */
+  pspec = g_param_spec_boolean ("black-point-compensation", "black point compensation", NULL,
+                                FALSE, G_PARAM_READWRITE);
+  g_object_class_install_property (object_class,
+                                   PROP_BLACK_POINT_COMPENSATION, pspec);
+
+  /**
+   * GtkColorTransform:input-profile:
+   */
+  pspec = g_param_spec_object ("input-profile", "input ICC profile", NULL,
+                               GTK_TYPE_COLOR_PROFILE, G_PARAM_READWRITE);
+  g_object_class_install_property (object_class,
+                                   PROP_INPUT_PROFILE, pspec);
+
+  /**
+   * GtkColorTransform:output-profile:
+   */
+  pspec = g_param_spec_object ("output-profile", "output ICC profile", NULL,
+                               GTK_TYPE_COLOR_PROFILE, G_PARAM_READWRITE);
+  g_object_class_install_property (object_class,
+                                   PROP_OUTPUT_PROFILE, pspec);
+
+  g_type_class_add_private (klass, sizeof (GtkColorTransformPrivate));
+}
+
+/**
+ * gtk_color_transform_init:
+ **/
+static void
+gtk_color_transform_init (GtkColorTransform *color_transform)
+{
+  color_transform->priv = GTK_COLOR_TRANSFORM_GET_PRIVATE (color_transform);
+  color_transform->priv->intent = GTK_COLOR_INTENT_PERCEPTUAL;
+  color_transform->priv->black_point_compensation = FALSE;
+  color_transform->priv->input_profile = NULL;
+  color_transform->priv->output_profile = NULL;
+}
+
+/**
+ * gtk_color_transform_finalize:
+ **/
+static void
+gtk_color_transform_finalize (GObject *object)
+{
+  GtkColorTransform *color_transform = GTK_COLOR_TRANSFORM (object);
+  GtkColorTransformPrivate *priv = color_transform->priv;
+
+  /* close profiles if they ever existed */
+  if (priv->input_profile != NULL)
+    g_object_unref (priv->input_profile);
+  if (priv->output_profile != NULL)
+    g_object_unref (priv->output_profile);
+
+  G_OBJECT_CLASS (gtk_color_transform_parent_class)->finalize (object);
+}
+
+#define __GTK_COLOR_TRANSFORM_C__
+#include "gtkaliasdef.c"
diff --git a/gtk/gtkcolortransform.h b/gtk/gtkcolortransform.h
new file mode 100644
index 0000000..1a6e1b8
--- /dev/null
+++ b/gtk/gtkcolortransform.h
@@ -0,0 +1,95 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_COLOR_TRANSFORM_H
+#define __GTK_COLOR_TRANSFORM_H
+
+#include <glib-object.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "gtkcolorprofile.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLOR_TRANSFORM             (gtk_color_transform_get_type ())
+#define GTK_COLOR_TRANSFORM(o)               (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLOR_TRANSFORM, GtkColorTransform))
+#define GTK_COLOR_TRANSFORM_CLASS(k)         (G_TYPE_CHECK_CLASS_CAST((k), GTK_TYPE_COLOR_TRANSFORM, GtkColorTransformClass))
+#define GTK_IS_COLOR_TRANSFORM(o)            (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLOR_TRANSFORM))
+#define GTK_IS_COLOR_TRANSFORM_CLASS(k)      (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLOR_TRANSFORM))
+#define GTK_COLOR_TRANSFORM_GET_CLASS(o)     (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLOR_TRANSFORM, GtkColorTransformClass))
+
+typedef struct _GtkColorTransformPrivate       GtkColorTransformPrivate;
+typedef struct _GtkColorTransform              GtkColorTransform;
+typedef struct _GtkColorTransformClass         GtkColorTransformClass;
+
+struct _GtkColorTransform
+{
+  GObject parent;
+  GtkColorTransformPrivate *priv;
+};
+
+typedef enum {
+  GTK_COLOR_INTENT_INVALID,
+  GTK_COLOR_INTENT_PERCEPTUAL,
+  GTK_COLOR_INTENT_RELATIVE_COLORMETRIC,
+  GTK_COLOR_INTENT_SATURATION,
+  GTK_COLOR_INTENT_ABSOLUTE_COLORMETRIC,
+  GTK_COLOR_INTENT_LAST
+} GtkColorIntent;
+
+struct _GtkColorTransformClass
+{
+        GObjectClass parent_class;
+        gboolean         (*apply_in_place)  (GtkColorTransform  *color_transform,
+                                             GdkPixbuf          *pixbuf,
+                                             GError            **error);
+        gboolean         (*apply)           (GtkColorTransform  *color_transform,
+                                             GdkPixbuf          *pixbuf_in,
+                                             GdkPixbuf          *pixbuf_out,
+                                             GError            **error);
+        /* padding for future expansion */
+        void (*_gtk_reserved1) (void);
+        void (*_gtk_reserved2) (void);
+        void (*_gtk_reserved3) (void);
+        void (*_gtk_reserved4) (void);
+        void (*_gtk_reserved5) (void);
+};
+
+GType                    gtk_color_transform_get_type             (void);
+void                     gtk_color_transform_set_input_profile    (GtkColorTransform    *color_transform,
+                                                                   GtkColorProfile      *profile);
+void                     gtk_color_transform_set_output_profile   (GtkColorTransform    *color_transform,
+                                                                   GtkColorProfile      *profile);
+gboolean                 gtk_color_transform_apply_in_place       (GtkColorTransform    *color_transform,
+                                                                   GdkPixbuf            *pixbuf,
+                                                                   GError              **error);
+gboolean                 gtk_color_transform_apply                (GtkColorTransform    *color_transform,
+                                                                   GdkPixbuf            *pixbuf_in,
+                                                                   GdkPixbuf            *pixbuf_out,
+                                                                   GError              **error);
+
+G_END_DECLS
+
+#endif /* __GTK_COLOR_TRANSFORM_H */
+
diff --git a/gtk/gtkcolortransformfallback.c b/gtk/gtkcolortransformfallback.c
new file mode 100644
index 0000000..d11feeb
--- /dev/null
+++ b/gtk/gtkcolortransformfallback.c
@@ -0,0 +1,115 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#include "gtkcolortransformfallback.h"
+
+static void     gtk_color_transform_fallback_finalize  (GObject     *object);
+
+G_DEFINE_TYPE (GtkColorTransformFallback, gtk_color_transform_fallback, GTK_TYPE_COLOR_TRANSFORM)
+
+/**
+ * gtk_color_transform_fallback_apply:
+ **/
+static gboolean
+gtk_color_transform_fallback_apply (GtkColorTransform *color_transform,
+                                    GdkPixbuf         *pixbuf_in,
+                                    GdkPixbuf         *pixbuf_out,
+                                    GError           **error)
+{
+  gint width, height, rowstride;
+  guchar *p_in;
+  guchar *p_out;
+  gint i;
+
+  /* just blit each row */
+  height = gdk_pixbuf_get_height (pixbuf_in);
+  width = gdk_pixbuf_get_width (pixbuf_in);
+  rowstride = gdk_pixbuf_get_rowstride (pixbuf_in);
+  p_in = gdk_pixbuf_get_pixels (pixbuf_in);
+  p_out = gdk_pixbuf_get_pixels (pixbuf_out);
+  for (i=0; i<height; ++i)
+    {
+      memcpy (p_out, p_in, width);
+      p_in += rowstride;
+      p_out += rowstride;
+    }
+  return TRUE;
+}
+
+/**
+ * gtk_color_transform_fallback_apply_in_place:
+ **/
+static gboolean
+gtk_color_transform_fallback_apply_in_place (GtkColorTransform *color_transform,
+                                             GdkPixbuf       *pixbuf,
+                                             GError         **error)
+{
+  /* this is a NOP */
+  return TRUE;
+}
+
+/**
+ * gtk_color_transform_fallback_class_init:
+ **/
+static void
+gtk_color_transform_fallback_class_init (GtkColorTransformFallbackClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkColorTransformClass *parent_class = GTK_COLOR_TRANSFORM_CLASS (klass);
+  object_class->finalize = gtk_color_transform_fallback_finalize;
+
+  parent_class->apply_in_place = gtk_color_transform_fallback_apply_in_place;
+  parent_class->apply = gtk_color_transform_fallback_apply;
+}
+
+/**
+ * gtk_color_transform_fallback_init:
+ **/
+static void
+gtk_color_transform_fallback_init (GtkColorTransformFallback *color_transform_fallback)
+{
+}
+
+/**
+ * gtk_color_transform_fallback_finalize:
+ **/
+static void
+gtk_color_transform_fallback_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gtk_color_transform_fallback_parent_class)->finalize (object);
+}
+
+/**
+ * _gtk_color_transform_fallback_new:
+ **/
+GtkColorTransform *
+_gtk_color_transform_fallback_new (void)
+{
+  GtkColorTransformFallback *color_transform;
+  color_transform = g_object_new (GTK_TYPE_COLOR_TRANSFORM_FALLBACK, NULL);
+  return GTK_COLOR_TRANSFORM (color_transform);
+}
+
diff --git a/gtk/gtkcolortransformfallback.h b/gtk/gtkcolortransformfallback.h
new file mode 100644
index 0000000..9ca1514
--- /dev/null
+++ b/gtk/gtkcolortransformfallback.h
@@ -0,0 +1,62 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_COLOR_TRANSFORM_FALLBACK_H
+#define __GTK_COLOR_TRANSFORM_FALLBACK_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLOR_TRANSFORM_FALLBACK          (gtk_color_transform_fallback_get_type ())
+#define GTK_COLOR_TRANSFORM_FALLBACK(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLOR_TRANSFORM_FALLBACK, GtkColorTransformFallback))
+#define GTK_COLOR_TRANSFORM_FALLBACK_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), GTK_TYPE_COLOR_TRANSFORM_FALLBACK, GtkColorTransformFallbackClass))
+#define GTK_IS_COLOR_TRANSFORM_FALLBACK(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLOR_TRANSFORM_FALLBACK))
+#define GTK_IS_COLOR_TRANSFORM_FALLBACK_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLOR_TRANSFORM_FALLBACK))
+#define GTK_COLOR_TRANSFORM_FALLBACK_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLOR_TRANSFORM_FALLBACK, GtkColorTransformFallbackClass))
+
+typedef struct _GtkColorTransformFallback        GtkColorTransformFallback;
+typedef struct _GtkColorTransformFallbackClass   GtkColorTransformFallbackClass;
+
+struct _GtkColorTransformFallback
+{
+   GtkColorTransform parent;
+};
+
+struct _GtkColorTransformFallbackClass
+{
+  GtkColorTransformClass parent_class;
+  /* padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+  void (*_gtk_reserved5) (void);
+};
+
+GType              gtk_color_transform_fallback_get_type    (void);
+GtkColorTransform *_gtk_color_transform_fallback_new        (void);
+
+G_END_DECLS
+
+#endif /* __GTK_COLOR_TRANSFORM_FALLBACK_H */
+
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index b150bf3..d4d3a7a 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -27,6 +27,7 @@
 #include "config.h"
 
 #include <glib.h>
+#include <gio/gio.h>
 #include "gdkconfig.h"
 
 #include <locale.h>
@@ -50,6 +51,7 @@
 #include "gtkaccelmap.h"
 #include "gtkbox.h"
 #include "gtkclipboard.h"
+#include "gtkcolorengine.h"
 #include "gtkdnd.h"
 #include "gtkversion.h"
 #include "gtkmain.h"
@@ -822,6 +824,52 @@ gtk_get_option_group (gboolean open_default_display)
   return group;
 }
 
+static void
+_gtk_io_modules_ensure_extension_points_registered (void)
+{
+  static gboolean registered_extensions = FALSE;
+  GIOExtensionPoint *ep;
+
+  if (!registered_extensions)
+    {
+      registered_extensions = TRUE;
+      ep = g_io_extension_point_register (GTK_COLOR_ENGINE_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, GTK_TYPE_COLOR_ENGINE);
+    }
+}
+
+void
+_gtk_io_modules_ensure_loaded (void)
+{
+  static gboolean loaded_dirs = FALSE;
+  const gchar *module_path;
+  gchar *path;
+
+  _gtk_io_modules_ensure_extension_points_registered ();
+
+  if (!loaded_dirs)
+    {
+      loaded_dirs = TRUE;
+      path = g_build_filename (GTK_LIBDIR, "gtk-2.0", GTK_BINARY_VERSION, "giomodules", NULL);
+      g_io_modules_scan_all_in_directory (path);
+      g_free (path);
+
+      module_path = g_getenv ("GTK_EXTRA_GIOMODULES");
+      if (module_path)
+        {
+          gint i = 0;
+          gchar **paths;
+          paths = g_strsplit (module_path, ":", 0);
+          while (paths[i] != NULL)
+            {
+              g_io_modules_scan_all_in_directory (paths[i]);
+              i++;
+            }
+          g_strfreev (paths);
+        }
+    }
+}
+
 /**
  * gtk_init_with_args:
  * @argc: a pointer to the number of command line arguments.
diff --git a/gtk/gtkprivate.h b/gtk/gtkprivate.h
index 7ba5a5d..479a0f1 100644
--- a/gtk/gtkprivate.h
+++ b/gtk/gtkprivate.h
@@ -112,6 +112,8 @@ gboolean _gtk_fnmatch (const char *pattern,
 #define GTK_DEFAULT_ACCEL_MOD_MASK GDK_META_MASK
 #endif
 
+void _gtk_io_modules_ensure_loaded (void);
+
 G_END_DECLS
 
 #endif /* __GTK_PRIVATE_H__ */
diff --git a/modules/Makefile.am b/modules/Makefile.am
index 40d5fa5..9eb28a7 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -1,6 +1,6 @@
 include $(top_srcdir)/Makefile.decl
 
-SUBDIRS = input engines other
+SUBDIRS = input engines other giomodules
 
 if OS_UNIX
 SUBDIRS += printbackends
diff --git a/modules/giomodules/Makefile.am b/modules/giomodules/Makefile.am
new file mode 100644
index 0000000..29fc894
--- /dev/null
+++ b/modules/giomodules/Makefile.am
@@ -0,0 +1,11 @@
+include $(top_srcdir)/Makefile.decl
+
+SUBDIRS =
+
+if HAVE_LCMS
+SUBDIRS += lcms
+endif
+
+DIST_SUBDIRS = lcms
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/giomodules/lcms/Makefile.am b/modules/giomodules/lcms/Makefile.am
new file mode 100644
index 0000000..aeb4d51
--- /dev/null
+++ b/modules/giomodules/lcms/Makefile.am
@@ -0,0 +1,36 @@
+include $(top_srcdir)/Makefile.decl
+
+INCLUDES = \
+	-I$(top_srcdir) 				\
+	-I$(top_srcdir)/gdk				\
+	-I$(top_builddir)/gdk				\
+	-I$(top_srcdir)/gtk				\
+	-I$(top_builddir)/gtk				\
+	$(LCMS_CFLAGS)					\
+	$(GTK_DEP_CFLAGS)				\
+	$(GTK_DEBUG_FLAGS)
+
+LDADDS = \
+	$(top_builddir)/gtk/$(gtktargetlib)		\
+	$(GTK_DEP_LIBS)
+
+backenddir = $(libdir)/gtk-2.0/$(GTK_BINARY_VERSION)/giomodules
+
+backend_LTLIBRARIES = libcolorenginelcms.la
+
+libcolorenginelcms_la_SOURCES =				\
+	lcms-helper.c					\
+	gtkcolorenginelcms.c				\
+	gtkcolorprofilelcms.c				\
+	gtkcolortransformlcms.c
+
+noinst_HEADERS =					\
+	lcms-helper.h					\
+	gtkcolorenginelcms.h				\
+	gtkcolortransformlcms.h				\
+	gtkcolorprofilelcms.h
+
+libcolorenginelcms_la_LDFLAGS =  -avoid-version -module $(no_undefined)
+libcolorenginelcms_la_LIBADD = $(LDADDS) $(LCMS_LIBS)
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/giomodules/lcms/gtkcolorenginelcms.c b/modules/giomodules/lcms/gtkcolorenginelcms.c
new file mode 100644
index 0000000..3c32b8b
--- /dev/null
+++ b/modules/giomodules/lcms/gtkcolorenginelcms.c
@@ -0,0 +1,102 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gtkcolorenginelcms.h"
+#include "gtkcolorprofilelcms.h"
+#include "gtkcolortransformlcms.h"
+
+static void     gtk_color_engine_lcms_finalize  (GObject     *object);
+
+G_DEFINE_DYNAMIC_TYPE (GtkColorEngineLcms, gtk_color_engine_lcms, GTK_TYPE_COLOR_ENGINE)
+
+/**
+ * gtk_color_engine_lcms_class_init:
+ **/
+static void
+gtk_color_engine_lcms_class_init (GtkColorEngineLcmsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkColorEngineClass *parent_class = GTK_COLOR_ENGINE_CLASS (klass);
+  object_class->finalize = gtk_color_engine_lcms_finalize;
+
+  parent_class->create_profile = _gtk_color_profile_lcms_new;
+  parent_class->create_transform = _gtk_color_transform_lcms_new;
+}
+
+/**
+ * gtk_color_engine_lcms_init:
+ **/
+static void
+gtk_color_engine_lcms_init (GtkColorEngineLcms *color_engine_lcms)
+{
+}
+
+/**
+ * gtk_color_engine_lcms_finalize:
+ **/
+static void
+gtk_color_engine_lcms_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gtk_color_engine_lcms_parent_class)->finalize (object);
+}
+
+/**
+ * gtk_color_engine_lcms_class_finalize:
+ **/
+static void
+gtk_color_engine_lcms_class_finalize (GtkColorEngineLcmsClass *klass)
+{
+}
+
+/**
+ * gtk_color_engine_lcms_register:
+ **/
+void
+gtk_color_engine_lcms_register (GIOModule *module)
+{
+  gtk_color_engine_lcms_register_type (G_TYPE_MODULE (module));
+  g_io_extension_point_implement (GTK_COLOR_ENGINE_EXTENSION_POINT_NAME,
+                                  GTK_TYPE_COLOR_ENGINE_LCMS,
+                                  "lcms",
+                                  10);
+}
+
+/**
+ * g_io_module_load:
+ **/
+void
+g_io_module_load (GIOModule *module)
+{
+  gtk_color_engine_lcms_register (module);
+}
+
+/**
+ * g_io_module_unload:
+ **/
+void
+g_io_module_unload (GIOModule *module)
+{
+}
+
diff --git a/modules/giomodules/lcms/gtkcolorenginelcms.h b/modules/giomodules/lcms/gtkcolorenginelcms.h
new file mode 100644
index 0000000..716ede8
--- /dev/null
+++ b/modules/giomodules/lcms/gtkcolorenginelcms.h
@@ -0,0 +1,64 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_COLOR_ENGINE_LCMS_H
+#define __GTK_COLOR_ENGINE_LCMS_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLOR_ENGINE_LCMS          (gtk_color_engine_lcms_get_type ())
+#define GTK_COLOR_ENGINE_LCMS(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLOR_ENGINE_LCMS, GtkColorEngineLcms))
+#define GTK_COLOR_ENGINE_LCMS_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), GTK_TYPE_COLOR_ENGINE_LCMS, GtkColorEngineLcmsClass))
+#define GTK_IS_COLOR_ENGINE_LCMS(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLOR_ENGINE_LCMS))
+#define GTK_IS_COLOR_ENGINE_LCMS_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLOR_ENGINE_LCMS))
+#define GTK_COLOR_ENGINE_LCMS_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLOR_ENGINE_LCMS, GtkColorEngineLcmsClass))
+
+typedef struct _GtkColorEngineLcmsPrivate GtkColorEngineLcmsPrivate;
+typedef struct _GtkColorEngineLcms        GtkColorEngineLcms;
+typedef struct _GtkColorEngineLcmsClass   GtkColorEngineLcmsClass;
+
+struct _GtkColorEngineLcms
+{
+   GtkColorEngine parent;
+   GtkColorEngineLcmsPrivate *priv;
+};
+
+struct _GtkColorEngineLcmsClass
+{
+  GtkColorEngineClass parent_class;
+  /* padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+  void (*_gtk_reserved5) (void);
+};
+
+GType      gtk_color_engine_lcms_get_type    (void);
+void       gtk_color_engine_lcms_register    (GIOModule *module);
+
+G_END_DECLS
+
+#endif /* __GTK_COLOR_ENGINE_LCMS_H */
+
diff --git a/modules/giomodules/lcms/gtkcolorprofilelcms.c b/modules/giomodules/lcms/gtkcolorprofilelcms.c
new file mode 100644
index 0000000..083326f
--- /dev/null
+++ b/modules/giomodules/lcms/gtkcolorprofilelcms.c
@@ -0,0 +1,128 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <lcms.h>
+#include <gtk/gtk.h>
+
+#include "lcms-helper.h"
+#include "gtkcolorprofilelcms.h"
+
+static void     gtk_color_profile_lcms_finalize  (GObject     *object);
+
+#define GTK_COLOR_PROFILE_LCMS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_COLOR_PROFILE_LCMS, GtkColorProfileLcmsPrivate))
+
+/**
+ * GtkColorProfileLcmsPrivate:
+ *
+ * Private #GtkColorProfileLcms data
+ **/
+struct _GtkColorProfileLcmsPrivate
+{
+  cmsHPROFILE   handle;
+};
+
+G_DEFINE_TYPE (GtkColorProfileLcms, gtk_color_profile_lcms, GTK_TYPE_COLOR_PROFILE)
+
+/**
+ * _gtk_color_profile_lcms_get_handle:
+ **/
+gpointer
+_gtk_color_profile_lcms_get_handle (GtkColorProfile *color_profile)
+{
+  GtkColorProfileLcms *color_profile_lcms = GTK_COLOR_PROFILE_LCMS (color_profile);
+  GtkColorProfileLcmsPrivate *priv = color_profile_lcms->priv;
+  return priv->handle;
+}
+
+/**
+ * gtk_color_profile_lcms_set_from_data:
+ **/
+static gboolean
+gtk_color_profile_lcms_set_from_data (GtkColorProfile *color_profile,
+                                      const guint8    *data,
+                                      gsize            length,
+                                      GError         **error)
+{
+  GtkColorProfileLcms *color_profile_lcms = GTK_COLOR_PROFILE_LCMS (color_profile);
+  GtkColorProfileLcmsPrivate *priv = color_profile_lcms->priv;
+
+  if (priv->handle != NULL)
+    cmsCloseProfile (priv->handle);
+  priv->handle = cmsOpenProfileFromMem ((LPVOID)data, length);
+  return TRUE;
+}
+
+/**
+ * gtk_color_profile_lcms_class_init:
+ **/
+static void
+gtk_color_profile_lcms_class_init (GtkColorProfileLcmsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkColorProfileClass *parent_class = GTK_COLOR_PROFILE_CLASS (klass);
+  object_class->finalize = gtk_color_profile_lcms_finalize;
+
+  parent_class->set_from_data = gtk_color_profile_lcms_set_from_data;
+
+  g_type_class_add_private (klass, sizeof (GtkColorProfileLcmsPrivate));
+}
+
+/**
+ * gtk_color_profile_lcms_init:
+ **/
+static void
+gtk_color_profile_lcms_init (GtkColorProfileLcms *color_profile_lcms)
+{
+  color_profile_lcms->priv = GTK_COLOR_PROFILE_LCMS_GET_PRIVATE (color_profile_lcms);
+
+  lcms_helper_init ();
+
+  color_profile_lcms->priv->handle = NULL;
+}
+
+/**
+ * gtk_color_profile_lcms_finalize:
+ **/
+static void
+gtk_color_profile_lcms_finalize (GObject *object)
+{
+  GtkColorProfileLcms *color_profile_lcms = GTK_COLOR_PROFILE_LCMS (object);
+  GtkColorProfileLcmsPrivate *priv = color_profile_lcms->priv;
+
+  if (priv->handle != NULL)
+    cmsCloseProfile (priv->handle);
+
+  G_OBJECT_CLASS (gtk_color_profile_lcms_parent_class)->finalize (object);
+}
+
+/**
+ * _gtk_color_profile_lcms_new:
+ **/
+GtkColorProfile *
+_gtk_color_profile_lcms_new (void)
+{
+  GtkColorProfileLcms *color_profile;
+  color_profile = g_object_new (GTK_TYPE_COLOR_PROFILE_LCMS, NULL);
+  return GTK_COLOR_PROFILE (color_profile);
+}
+
diff --git a/modules/giomodules/lcms/gtkcolorprofilelcms.h b/modules/giomodules/lcms/gtkcolorprofilelcms.h
new file mode 100644
index 0000000..32fce77
--- /dev/null
+++ b/modules/giomodules/lcms/gtkcolorprofilelcms.h
@@ -0,0 +1,65 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_COLOR_PROFILE_LCMS_H
+#define __GTK_COLOR_PROFILE_LCMS_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLOR_PROFILE_LCMS          (gtk_color_profile_lcms_get_type ())
+#define GTK_COLOR_PROFILE_LCMS(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLOR_PROFILE_LCMS, GtkColorProfileLcms))
+#define GTK_COLOR_PROFILE_LCMS_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), GTK_TYPE_COLOR_PROFILE_LCMS, GtkColorProfileLcmsClass))
+#define GTK_IS_COLOR_PROFILE_LCMS(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLOR_PROFILE_LCMS))
+#define GTK_IS_COLOR_PROFILE_LCMS_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLOR_PROFILE_LCMS))
+#define GTK_COLOR_PROFILE_LCMS_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLOR_PROFILE_LCMS, GtkColorProfileLcmsClass))
+
+typedef struct _GtkColorProfileLcmsPrivate GtkColorProfileLcmsPrivate;
+typedef struct _GtkColorProfileLcms        GtkColorProfileLcms;
+typedef struct _GtkColorProfileLcmsClass   GtkColorProfileLcmsClass;
+
+struct _GtkColorProfileLcms
+{
+   GtkColorProfile parent;
+   GtkColorProfileLcmsPrivate *priv;
+};
+
+struct _GtkColorProfileLcmsClass
+{
+  GtkColorProfileClass parent_class;
+  /* padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+  void (*_gtk_reserved5) (void);
+};
+
+GType            gtk_color_profile_lcms_get_type    (void);
+gpointer        _gtk_color_profile_lcms_get_handle  (GtkColorProfile *color_profile);
+GtkColorProfile *_gtk_color_profile_lcms_new        (void);
+
+G_END_DECLS
+
+#endif /* __GTK_COLOR_PROFILE_LCMS_H */
+
diff --git a/modules/giomodules/lcms/gtkcolortransformlcms.c b/modules/giomodules/lcms/gtkcolortransformlcms.c
new file mode 100644
index 0000000..2712bd0
--- /dev/null
+++ b/modules/giomodules/lcms/gtkcolortransformlcms.c
@@ -0,0 +1,280 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <lcms.h>
+#include <gtk/gtk.h>
+
+#include "lcms-helper.h"
+#include "gtkcolortransformlcms.h"
+#include "gtkcolorprofilelcms.h"
+
+static void     gtk_color_transform_lcms_finalize  (GObject     *object);
+
+#define GTK_COLOR_TRANSFORM_LCMS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_COLOR_TRANSFORM_LCMS, GtkColorTransformLcmsPrivate))
+
+/**
+ * GtkColorTransformLcmsPrivate:
+ *
+ * Private #GtkColorTransformLcms data
+ **/
+struct _GtkColorTransformLcmsPrivate
+{
+  cmsHPROFILE   srgb_profile;
+};
+
+G_DEFINE_TYPE (GtkColorTransformLcms, gtk_color_transform_lcms, GTK_TYPE_COLOR_TRANSFORM)
+
+/**
+ * gtk_color_transform_lcms_get_format:
+ **/
+static DWORD
+gtk_color_transform_lcms_get_format (GdkPixbuf *pixbuf)
+{
+  guint bits;
+  guint has_alpha;
+
+  /* get data */
+  has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
+  bits = gdk_pixbuf_get_bits_per_sample (pixbuf);
+
+  /* no alpha channel */
+  if (!has_alpha)
+    {
+      if (bits == 8)
+        return TYPE_RGB_8;
+      if (bits == 16)
+        return TYPE_RGB_16;
+      return 0;
+    }
+
+  /* alpha channel */
+  if (bits == 8)
+    return TYPE_RGBA_8;
+  if (bits == 16)
+    return TYPE_RGBA_16;
+  return 0;
+}
+
+/**
+ * gtk_color_transform_lcms_get_flags:
+ **/
+static DWORD
+gtk_color_transform_lcms_get_flags (GtkColorTransform *color_transform)
+{
+  DWORD flags = 0;
+  gboolean black_point_compensation;
+
+  g_object_get (color_transform,
+                "black-point-compensation", &black_point_compensation,
+                NULL);
+  if (black_point_compensation)
+    flags &= cmsFLAGS_BLACKPOINTCOMPENSATION;
+  return flags;
+}
+
+/**
+ * gtk_color_transform_lcms_get_intent:
+ **/
+static gint
+gtk_color_transform_lcms_get_intent (GtkColorTransform *color_transform)
+{
+  GtkColorIntent intent;
+
+  g_object_get (color_transform,
+                "intent", &intent,
+                NULL);
+  if (intent == GTK_COLOR_INTENT_PERCEPTUAL)
+    return INTENT_PERCEPTUAL;
+  if (intent == GTK_COLOR_INTENT_RELATIVE_COLORMETRIC)
+    return INTENT_RELATIVE_COLORIMETRIC;
+  if (intent == GTK_COLOR_INTENT_SATURATION)
+    return INTENT_SATURATION;
+  if (intent == GTK_COLOR_INTENT_ABSOLUTE_COLORMETRIC)
+    return INTENT_ABSOLUTE_COLORIMETRIC;
+
+  /* choose a good default */
+  return INTENT_PERCEPTUAL;
+}
+
+/**
+ * gtk_color_transform_lcms_apply:
+ **/
+static gboolean
+gtk_color_transform_lcms_apply (GtkColorTransform *color_transform,
+                                GdkPixbuf       *pixbuf_in,
+                                GdkPixbuf       *pixbuf_out,
+                                GError         **error)
+{
+  DWORD format;
+  DWORD flags;
+  gint intent;
+  gboolean ret = FALSE;
+  cmsHTRANSFORM transform;
+  gint width, height, rowstride;
+  guchar *p_in;
+  guchar *p_out;
+  gint i;
+  GtkColorProfile *input_profile = NULL;
+  GtkColorProfile *output_profile = NULL;
+  gpointer input_profile_handle;
+  gpointer output_profile_handle;
+  GtkColorTransformLcms *color_transform_lcms = GTK_COLOR_TRANSFORM_LCMS(color_transform);
+  GtkColorTransformLcmsPrivate *priv = color_transform_lcms->priv;
+
+  /* CMYK not supported */
+  if (gdk_pixbuf_get_colorspace (pixbuf_in) != GDK_COLORSPACE_RGB)
+    {
+      if (error != NULL)
+        *error = g_error_new (1, 0, "non-RGB not supported");
+      goto out;
+    }
+
+  /* work out the LCMS format flags */
+  flags = gtk_color_transform_lcms_get_flags (color_transform);
+  intent = gtk_color_transform_lcms_get_intent (color_transform);
+  format = gtk_color_transform_lcms_get_format (pixbuf_in);
+  if (format == 0)
+    {
+      if (error != NULL)
+        *error = g_error_new (1, 0, "format not supported");
+      goto out;
+    }
+
+  g_object_get (color_transform,
+                "input-profile", &input_profile,
+                "output-profile", &output_profile,
+                NULL);
+
+  /* no profiles */
+  if (input_profile == NULL && output_profile == NULL && pixbuf_in == pixbuf_out)
+    {
+      /* no need to blit */
+      goto out;
+    }
+
+  /* fall back to sRGB */
+  if (input_profile == NULL)
+    input_profile_handle = priv->srgb_profile;
+  else
+    input_profile_handle = _gtk_color_profile_lcms_get_handle (input_profile);
+
+  /* fall back to sRGB */
+  if (output_profile == NULL)
+    output_profile_handle = priv->srgb_profile;
+  else
+    output_profile_handle = _gtk_color_profile_lcms_get_handle (output_profile);
+
+  /* create transform */
+  transform = cmsCreateTransform (input_profile_handle, format, output_profile_handle, format, intent, flags);
+
+  /* process each row */
+  height = gdk_pixbuf_get_height (pixbuf_in);
+  width = gdk_pixbuf_get_width (pixbuf_in);
+  rowstride = gdk_pixbuf_get_rowstride (pixbuf_in);
+  p_in = gdk_pixbuf_get_pixels (pixbuf_in);
+  p_out = gdk_pixbuf_get_pixels (pixbuf_out);
+  for (i=0; i<height; ++i)
+    {
+      cmsDoTransform (transform, p_in, p_out, width);
+      p_in += rowstride;
+      p_out += rowstride;
+    }
+
+  /* success */
+  ret = TRUE;
+
+  /* destroy lcms state */
+  cmsDeleteTransform (transform);
+out:
+  if (input_profile != NULL)
+    g_object_unref (input_profile);
+  if (output_profile != NULL)
+    g_object_unref (output_profile);
+  return ret;
+}
+
+/**
+ * gtk_color_transform_lcms_apply_in_place:
+ **/
+static gboolean
+gtk_color_transform_lcms_apply_in_place (GtkColorTransform *color_transform,
+                                  GdkPixbuf       *pixbuf,
+                                  GError         **error)
+{
+  return gtk_color_transform_lcms_apply (color_transform, pixbuf, pixbuf, error);
+}
+
+/**
+ * gtk_color_transform_lcms_class_init:
+ **/
+static void
+gtk_color_transform_lcms_class_init (GtkColorTransformLcmsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkColorTransformClass *parent_class = GTK_COLOR_TRANSFORM_CLASS (klass);
+  object_class->finalize = gtk_color_transform_lcms_finalize;
+
+  parent_class->apply_in_place = gtk_color_transform_lcms_apply_in_place;
+  parent_class->apply = gtk_color_transform_lcms_apply;
+
+  g_type_class_add_private (klass, sizeof (GtkColorTransformLcmsPrivate));
+}
+
+/**
+ * gtk_color_transform_lcms_init:
+ **/
+static void
+gtk_color_transform_lcms_init (GtkColorTransformLcms *color_transform_lcms)
+{
+  color_transform_lcms->priv = GTK_COLOR_TRANSFORM_LCMS_GET_PRIVATE (color_transform_lcms);
+
+  lcms_helper_init ();
+
+  color_transform_lcms->priv->srgb_profile = cmsCreate_sRGBProfile ();
+}
+
+/**
+ * gtk_color_transform_lcms_finalize:
+ **/
+static void
+gtk_color_transform_lcms_finalize (GObject *object)
+{
+  GtkColorTransformLcms *color_transform_lcms = GTK_COLOR_TRANSFORM_LCMS (object);
+  GtkColorTransformLcmsPrivate *priv = color_transform_lcms->priv;
+
+  cmsCloseProfile (priv->srgb_profile);
+
+  G_OBJECT_CLASS (gtk_color_transform_lcms_parent_class)->finalize (object);
+}
+
+/**
+ * _gtk_color_transform_lcms_new:
+ **/
+GtkColorTransform *
+_gtk_color_transform_lcms_new (void)
+{
+  GtkColorTransformLcms *color_transform;
+  color_transform = g_object_new (GTK_TYPE_COLOR_TRANSFORM_LCMS, NULL);
+  return GTK_COLOR_TRANSFORM (color_transform);
+}
+
diff --git a/modules/giomodules/lcms/gtkcolortransformlcms.h b/modules/giomodules/lcms/gtkcolortransformlcms.h
new file mode 100644
index 0000000..91a2b55
--- /dev/null
+++ b/modules/giomodules/lcms/gtkcolortransformlcms.h
@@ -0,0 +1,64 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_COLOR_TRANSFORM_LCMS_H
+#define __GTK_COLOR_TRANSFORM_LCMS_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLOR_TRANSFORM_LCMS          (gtk_color_transform_lcms_get_type ())
+#define GTK_COLOR_TRANSFORM_LCMS(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLOR_TRANSFORM_LCMS, GtkColorTransformLcms))
+#define GTK_COLOR_TRANSFORM_LCMS_CLASS(k)      (G_TYPE_CHECK_CLASS_CAST((k), GTK_TYPE_COLOR_TRANSFORM_LCMS, GtkColorTransformLcmsClass))
+#define GTK_IS_COLOR_TRANSFORM_LCMS(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLOR_TRANSFORM_LCMS))
+#define GTK_IS_COLOR_TRANSFORM_LCMS_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLOR_TRANSFORM_LCMS))
+#define GTK_COLOR_TRANSFORM_LCMS_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLOR_TRANSFORM_LCMS, GtkColorTransformLcmsClass))
+
+typedef struct _GtkColorTransformLcmsPrivate GtkColorTransformLcmsPrivate;
+typedef struct _GtkColorTransformLcms        GtkColorTransformLcms;
+typedef struct _GtkColorTransformLcmsClass   GtkColorTransformLcmsClass;
+
+struct _GtkColorTransformLcms
+{
+   GtkColorTransform parent;
+   GtkColorTransformLcmsPrivate *priv;
+};
+
+struct _GtkColorTransformLcmsClass
+{
+  GtkColorTransformClass parent_class;
+  /* padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+  void (*_gtk_reserved5) (void);
+};
+
+GType              gtk_color_transform_lcms_get_type    (void);
+GtkColorTransform *_gtk_color_transform_lcms_new        (void);
+
+G_END_DECLS
+
+#endif /* __GTK_COLOR_TRANSFORM_LCMS_H */
+
diff --git a/modules/giomodules/lcms/lcms-helper.c b/modules/giomodules/lcms/lcms-helper.c
new file mode 100644
index 0000000..5e2b4e8
--- /dev/null
+++ b/modules/giomodules/lcms/lcms-helper.c
@@ -0,0 +1,55 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <lcms.h>
+
+#include "lcms-helper.h"
+
+/**
+ * lcms_helper_error_cb:
+ **/
+static int
+lcms_helper_error_cb (gint         error_code,
+                      const gchar *error_text)
+{
+  g_warning ("LCMS error %i: %s", error_code, error_text);
+  return LCMS_ERRC_WARNING;
+}
+
+/**
+ * lcms_helper_init:
+ **/
+void
+lcms_helper_init (void)
+{
+  static gboolean inited = FALSE;
+  if (inited)
+    return;
+
+  cmsSetErrorHandler (lcms_helper_error_cb);
+  cmsErrorAction (LCMS_ERROR_SHOW);
+  cmsSetLanguage ("en", "US");
+
+  inited = TRUE;
+}
+
diff --git a/modules/giomodules/lcms/lcms-helper.h b/modules/giomodules/lcms/lcms-helper.h
new file mode 100644
index 0000000..f030af7
--- /dev/null
+++ b/modules/giomodules/lcms/lcms-helper.h
@@ -0,0 +1,29 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright (C) 2010 Richard Hughes <richard@hughsie.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 2 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
+ * Lesser 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LCMS_HELPER_H
+#define __LCMS_HELPER_H
+
+#include <glib.h>
+
+void lcms_helper_init (void);
+
+#endif /* __LCMS_HELPER_H */
+
