[gthumb] color profile: use an object to store the transformation



commit 2c47261ea45ed9f7500deca85ee741f569772156
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon Jun 26 17:51:45 2017 +0200

    color profile: use an object to store the transformation

 extensions/cairo_io/cairo-image-surface-jpeg.c  |    2 +-
 extensions/image_viewer/gth-image-viewer-page.c |    2 +-
 gthumb/gth-browser.c                            |   16 +-
 gthumb/gth-browser.h                            |    2 +-
 gthumb/gth-color-manager.c                      |  159 +++++++---------
 gthumb/gth-color-manager.h                      |   16 +--
 gthumb/gth-icc-profile.c                        |  238 +++++++++++++++++------
 gthumb/gth-icc-profile.h                        |   78 ++++++---
 gthumb/gth-image-loader.c                       |    4 +-
 gthumb/gth-image-loader.h                       |    2 +-
 gthumb/gth-image-preloader.c                    |    4 +-
 gthumb/gth-image-preloader.h                    |    2 +-
 gthumb/gth-image.c                              |   36 ++--
 gthumb/gth-image.h                              |    8 +-
 14 files changed, 341 insertions(+), 228 deletions(-)
---
diff --git a/extensions/cairo_io/cairo-image-surface-jpeg.c b/extensions/cairo_io/cairo-image-surface-jpeg.c
index d54ff89..a500adb 100644
--- a/extensions/cairo_io/cairo-image-surface-jpeg.c
+++ b/extensions/cairo_io/cairo-image-surface-jpeg.c
@@ -209,7 +209,7 @@ _cairo_image_surface_create_from_jpeg (GInputStream  *istream,
                orientation = GTH_TRANSFORM_NONE;
 #if HAVE_LCMS2
        if (jpeg_info.valid & _JPEG_INFO_ICC_PROFILE) {
-               GthICCData *profile = gth_icc_data_new (NULL, cmsOpenProfileFromMem (jpeg_info.icc_data, 
jpeg_info.icc_data_size));
+               GthICCProfile *profile = gth_icc_profile_new (GTH_ICC_PROFILE_ID_UNKNOWN, 
cmsOpenProfileFromMem (jpeg_info.icc_data, jpeg_info.icc_data_size));
                gth_image_set_icc_profile (image, profile);
                g_object_unref (profile);
        }
diff --git a/extensions/image_viewer/gth-image-viewer-page.c b/extensions/image_viewer/gth-image-viewer-page.c
index 83ec2e9..4afe487 100644
--- a/extensions/image_viewer/gth-image-viewer-page.c
+++ b/extensions/image_viewer/gth-image-viewer-page.c
@@ -257,7 +257,7 @@ profile_ready_cb (GObject      *source_object,
 {
        ProfileData        *profile_data = user_data;
        GthImageViewerPage *self = profile_data->self;
-       GthICCData         *profile;
+       GthICCProfile      *profile;
 
        profile = gth_color_manager_get_profile_finish (GTH_COLOR_MANAGER (source_object), res, NULL);
        if (profile == NULL)
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index ee343a1..c223a2c 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -180,7 +180,7 @@ struct _GthBrowserPrivate {
        gboolean           file_properties_on_the_right;
        GthSidebarState    viewer_sidebar;
        BrowserState       state;
-       GthICCProfile      screen_profile;
+       GthICCProfile     *screen_profile;
        GtkTreePath       *folder_tree_last_dest_row; /* used to open a folder during D&D */
        guint              folder_tree_open_folder_id;
        GtkWidget         *apply_editor_changes_button;
@@ -6951,7 +6951,7 @@ gth_browser_apply_editor_changes (GthBrowser *browser)
 }
 
 
-GthICCData *
+GthICCProfile *
 gth_browser_get_monitor_profile (GthBrowser *browser)
 {
 #if HAVE_LCMS2
@@ -6976,13 +6976,13 @@ gth_browser_get_monitor_profile (GthBrowser *browser)
                                              0, 64 * 1024 * 1024, FALSE,
                                              &type, &format, &nitems, &data) && nitems > 0)
                        {
-                               GthICCProfile profile;
+                               GthCMSProfile cms_profile;
 
-                               profile = cmsOpenProfileFromMem (data, nitems);
-                               if (profile != NULL) {
-                                       char *filename = g_strdup_printf ("icc-profile://%d", monitor_num);
-                                       browser->priv->screen_profile = gth_icc_data_new (filename, profile);
-                                       g_free (filename);
+                               cms_profile = (GthCMSProfile) cmsOpenProfileFromMem (data, nitems);
+                               if (cms_profile != NULL) {
+                                       char *id = g_strdup_printf ("%s%d", GTH_ICC_PROFILE_FROM_PROPERTY, 
monitor_num);
+                                       browser->priv->screen_profile = gth_icc_profile_new (id, cms_profile);
+                                       g_free (id);
                                }
 
                                g_free (data);
diff --git a/gthumb/gth-browser.h b/gthumb/gth-browser.h
index 68d60cd..a0bae0a 100644
--- a/gthumb/gth-browser.h
+++ b/gthumb/gth-browser.h
@@ -272,7 +272,7 @@ void             gth_browser_ask_whether_to_save    (GthBrowser       *browser,
 void             gth_browser_save_state             (GthBrowser       *browser);
 gboolean         gth_browser_restore_state          (GthBrowser       *browser);
 void            gth_browser_apply_editor_changes   (GthBrowser       *browser);
-GthICCData *     gth_browser_get_monitor_profile    (GthBrowser              *browser);
+GthICCProfile *  gth_browser_get_monitor_profile    (GthBrowser              *browser);
 GtkWidget *      gth_browser_get_fullscreen_headerbar
                                                    (GthBrowser       *browser);
 void             gth_browser_keep_mouse_visible     (GthBrowser              *browser,
diff --git a/gthumb/gth-color-manager.c b/gthumb/gth-color-manager.c
index 078aa77..eeee7b1 100644
--- a/gthumb/gth-color-manager.c
+++ b/gthumb/gth-color-manager.c
@@ -33,9 +33,9 @@
 
 
 typedef struct {
-       GthICCData      *in_profile;
-       GthICCData      *out_profile;
-       GthICCTransform  transform;
+       GthICCProfile   *in_profile;
+       GthICCProfile   *out_profile;
+       GthICCTransform *transform;
 } TransformData;
 
 
@@ -58,7 +58,7 @@ transform_data_free (TransformData *data)
 {
        _g_object_unref (data->in_profile);
        _g_object_unref (data->out_profile);
-       gth_icc_transform_free (data->transform);
+       _g_object_unref (data->transform);
        g_free (data);
 }
 
@@ -143,6 +143,19 @@ gth_color_manager_new (void)
 }
 
 
+static void
+_gth_color_manager_add_profile (GthColorManager         *self,
+                               const char       *id,
+                               GthICCProfile    *profile)
+{
+       g_return_if_fail (self != NULL);
+       g_return_if_fail (id != NULL);
+       g_return_if_fail (profile != NULL);
+
+       g_hash_table_insert (self->priv->profile_cache, g_strdup (id), g_object_ref (profile));
+}
+
+
 #if HAVE_LCMS2 && HAVE_COLORD
 
 
@@ -177,17 +190,17 @@ profile_buffer_ready_cb (void     **buffer,
                g_task_return_error (task, g_error_copy (error));
        }
        else {
-               ProfilesData *data = g_task_get_task_data (task);
-               char         *filename;
-               GthICCData   *icc_data;
+               ProfilesData  *data = g_task_get_task_data (task);
+               char          *uri;
+               GthICCProfile *profile;
 
-               filename = g_file_get_path (data->icc_file);
-               icc_data = gth_icc_data_new (filename, (GthICCProfile) cmsOpenProfileFromMem (*buffer, 
count));
-               gth_color_manager_add_profile (data->color_manager, data->cache_id, icc_data);
-               g_task_return_pointer (task, g_object_ref (icc_data), g_object_unref);
+               uri = g_file_get_uri (data->icc_file);
+               profile = gth_icc_profile_new (uri, (GthCMSProfile) cmsOpenProfileFromMem (*buffer, count));
+               _gth_color_manager_add_profile (data->color_manager, data->cache_id, profile);
+               g_task_return_pointer (task, g_object_ref (profile), g_object_unref);
 
-               g_object_unref (icc_data);
-               g_free (filename);
+               g_object_unref (profile);
+               g_free (uri);
        }
 
        g_object_unref (task);
@@ -308,6 +321,20 @@ cd_client_connected_cb (GObject      *source_object,
 #endif /* HAVE_LCMS2 && HAVE_COLORD */
 
 
+static GthICCProfile *
+_gth_color_manager_get_profile (GthColorManager         *self,
+                               const char       *id)
+{
+       GthICCProfile *profile;
+
+       g_return_val_if_fail (self != NULL, NULL);
+       g_return_val_if_fail (id != NULL, NULL);
+
+       profile = g_hash_table_lookup (self->priv->profile_cache, id);
+       return _g_object_ref (profile);
+}
+
+
 void
 gth_color_manager_get_profile_async (GthColorManager    *self,
                                     char                *monitor_name,
@@ -322,12 +349,12 @@ gth_color_manager_get_profile_async (GthColorManager       *self,
 #if HAVE_LCMS2
 
        {
-               char         *id;
-               GthICCData   *profile;
-               ProfilesData *data;
+               char          *id;
+               GthICCProfile *profile;
+               ProfilesData  *data;
 
                id = g_strdup_printf ("monitor://%s", monitor_name);
-               profile = gth_color_manager_get_profile (self, id);
+               profile = _gth_color_manager_get_profile (self, id);
                if (profile != NULL) {
                        g_task_return_pointer (task, g_object_ref (profile), g_object_unref);
                        g_object_unref (task);
@@ -373,7 +400,7 @@ gth_color_manager_get_profile_async (GthColorManager         *self,
 }
 
 
-GthICCData *
+GthICCProfile *
 gth_color_manager_get_profile_finish (GthColorManager   *self,
                                      GAsyncResult       *result,
                                      GError            **error)
@@ -383,99 +410,43 @@ gth_color_manager_get_profile_finish (GthColorManager      *self,
 }
 
 
-void
-gth_color_manager_add_profile (GthColorManager  *self,
-                              const char        *id,
-                              GthICCData        *profile)
-{
-       g_return_if_fail (self != NULL);
-       g_return_if_fail (id != NULL);
-       g_return_if_fail (profile != NULL);
-
-       g_hash_table_insert (self->priv->profile_cache, g_strdup (id), g_object_ref (profile));
-}
-
-
-GthICCData *
-gth_color_manager_get_profile (GthColorManager  *self,
-                              const char        *id)
-{
-       GthICCData *profile;
-
-       g_return_val_if_fail (self != NULL, NULL);
-       g_return_val_if_fail (id != NULL, NULL);
-
-       profile = g_hash_table_lookup (self->priv->profile_cache, id);
-       return _g_object_ref (profile);
-}
-
-
-#if HAVE_LCMS2
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN /* BGRA */
-#define _LCMS2_CAIRO_FORMAT TYPE_BGRA_8
-#elif G_BYTE_ORDER == G_BIG_ENDIAN /* ARGB */
-#define _LCMS2_CAIRO_FORMAT TYPE_ARGB_8
-#else
-#define _LCMS2_CAIRO_FORMAT TYPE_ABGR_8
-#endif
-#endif
-
-
 static char *
-create_transform_id (GthICCData *from_profile,
-                    GthICCData *to_profile)
+create_transform_id_for_cache (GthICCProfile *from_profile,
+                              GthICCProfile *to_profile)
 {
-       const char *from_filename = gth_icc_data_get_filename (from_profile);
-       const char *to_filename = gth_icc_data_get_filename (to_profile);
+       const char *from_id = gth_icc_profile_get_id (from_profile);
+       const char *to_id = gth_icc_profile_get_id (to_profile);
 
-       if ((g_strcmp0 (from_filename, "") != 0) && (g_strcmp0 (to_filename, "") != 0))
-               return g_strdup_printf ("%s -> %s", from_filename, to_filename);
-       else
-               return NULL;
-}
+       g_print ("  -> gth_color_manager_get_transform: %s -> %s\n", from_id, to_id);
 
+       if (gth_icc_profile_id_is_unknown (from_id) || gth_icc_profile_id_is_unknown (to_id))
+               return NULL;
 
-GthICCTransform
-gth_color_manager_create_transform (GthColorManager *self,
-                                   GthICCData      *from_profile,
-                                   GthICCData      *to_profile)
-{
-#if HAVE_LCMS2
-       g_print ("gth_color_manager_create_transform (%p, %p)\n", gth_icc_data_get_profile (from_profile), 
gth_icc_data_get_profile (to_profile));
-
-       return (GthICCTransform) cmsCreateTransform ((cmsHPROFILE) gth_icc_data_get_profile (from_profile),
-                                                    _LCMS2_CAIRO_FORMAT,
-                                                    (cmsHPROFILE) gth_icc_data_get_profile (to_profile),
-                                                    _LCMS2_CAIRO_FORMAT,
-                                                    INTENT_PERCEPTUAL,
-                                                    0);
-#else
-       return NULL;
-#endif
+       return g_strdup_printf ("%s -> %s", from_id, to_id);
 }
 
 
-GthICCTransform
+GthICCTransform *
 gth_color_manager_get_transform (GthColorManager *self,
-                                GthICCData      *from_profile,
-                                GthICCData      *to_profile)
+                                GthICCProfile   *in_profile,
+                                GthICCProfile   *out_profile)
 {
 #if HAVE_LCMS2
 
-       GthICCTransform  transform = NULL;
+       GthICCTransform *transform = NULL;
        char            *transform_id;
 
        g_return_val_if_fail (self != NULL, NULL);
 
-       transform_id = create_transform_id (from_profile, to_profile);
+       transform_id = create_transform_id_for_cache (in_profile, out_profile);
        if (transform_id != NULL) {
                TransformData *transform_data = g_hash_table_lookup (self->priv->transform_cache, 
transform_id);
 
                if (transform_data == NULL) {
                        transform_data = transform_data_new ();
-                       transform_data->in_profile = g_object_ref (from_profile);
-                       transform_data->out_profile = g_object_ref (to_profile);
-                       transform_data->transform = gth_color_manager_create_transform (self, 
transform_data->in_profile, transform_data->out_profile);
+                       transform_data->in_profile = g_object_ref (in_profile);
+                       transform_data->out_profile = g_object_ref (out_profile);
+                       transform_data->transform = gth_icc_transform_new_from_profiles 
(transform_data->in_profile, transform_data->out_profile);
 
                        if (transform_data->transform != NULL) {
                                g_hash_table_insert (self->priv->transform_cache, g_strdup (transform_id), 
transform_data);
@@ -487,14 +458,18 @@ gth_color_manager_get_transform (GthColorManager *self,
                }
 
                if (transform_data != NULL)
-                       transform = transform_data->transform;
+                       transform = g_object_ref (transform_data->transform);
 
                g_free (transform_id);
        }
+       else
+               transform = gth_icc_transform_new_from_profiles (in_profile, out_profile);
 
        return transform;
 
-#endif
+#else
 
        return NULL;
+
+#endif
 }
diff --git a/gthumb/gth-color-manager.h b/gthumb/gth-color-manager.h
index 71a7770..9687e68 100644
--- a/gthumb/gth-color-manager.h
+++ b/gthumb/gth-color-manager.h
@@ -59,20 +59,12 @@ void                        gth_color_manager_get_profile_async     (GthColorManager      
   *color_manager,
                                                                 GCancellable            *cancellable,
                                                                 GAsyncReadyCallback      callback,
                                                                 gpointer                 user_data);
-GthICCData *           gth_color_manager_get_profile_finish    (GthColorManager         *color_manager,
+GthICCProfile *                gth_color_manager_get_profile_finish    (GthColorManager         
*color_manager,
                                                                 GAsyncResult            *result,
                                                                 GError                 **error);
-void                   gth_color_manager_add_profile           (GthColorManager         *color_manager,
-                                                                const char              *id,
-                                                                GthICCData              *profile);
-GthICCData *           gth_color_manager_get_profile           (GthColorManager         *color_manager,
-                                                                const char              *id);
-GthICCTransform                gth_color_manager_create_transform      (GthColorManager         *self,
-                                                                GthICCData              *from_profile,
-                                                                GthICCData              *to_profile);
-GthICCTransform         gth_color_manager_get_transform         (GthColorManager        *color_manager,
-                                                                GthICCData              *from_profile,
-                                                                GthICCData              *to_profile);
+GthICCTransform *       gth_color_manager_get_transform         (GthColorManager        *color_manager,
+                                                                GthICCProfile           *from_profile,
+                                                                GthICCProfile           *to_profile);
 
 G_END_DECLS
 
diff --git a/gthumb/gth-icc-profile.c b/gthumb/gth-icc-profile.c
index 35af682..637e041 100644
--- a/gthumb/gth-icc-profile.c
+++ b/gthumb/gth-icc-profile.c
@@ -28,67 +28,87 @@
 #include "gth-icc-profile.h"
 
 
-struct _GthICCDataPrivate {
-       GthICCProfile icc_profile;
-       char *filename;
+struct _GthICCProfilePrivate {
+       GthCMSProfile cms_profile;
+       char *id;
 };
 
 
-G_DEFINE_TYPE (GthICCData, gth_icc_data, G_TYPE_OBJECT)
+struct _GthICCTransformPrivate {
+       GthCMSTransform cms_transform;
+};
+
+
+G_DEFINE_TYPE (GthICCProfile, gth_icc_profile, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GthICCTransform, gth_icc_transform, G_TYPE_OBJECT)
+
+
+void
+gth_cms_profile_free (GthCMSProfile profile)
+{
+#ifdef HAVE_LCMS2
+       if (profile != NULL)
+               cmsCloseProfile ((cmsHPROFILE) profile);
+#endif
+}
+
+
+void
+gth_cms_transform_free (GthCMSTransform transform)
+{
+#ifdef HAVE_LCMS2
+       if (transform != NULL)
+               cmsDeleteTransform ((cmsHTRANSFORM) transform);
+#endif
+}
+
+
+/* -- GthICCProfile -- */
 
 
 static void
-gth_icc_data_finalize (GObject *object)
+gth_icc_profile_finalize (GObject *object)
 {
-       GthICCData *icc_data;
+       GthICCProfile *icc_profile;
 
        g_return_if_fail (object != NULL);
-       g_return_if_fail (GTH_IS_ICC_DATA (object));
+       g_return_if_fail (GTH_IS_ICC_PROFILE (object));
 
-       icc_data = GTH_ICC_DATA (object);
-       gth_icc_profile_free (icc_data->priv->icc_profile);
-       g_free (icc_data->priv->filename);
+       icc_profile = GTH_ICC_PROFILE (object);
+       gth_cms_profile_free (icc_profile->priv->cms_profile);
+       g_free (icc_profile->priv->id);
 
        /* Chain up */
-       G_OBJECT_CLASS (gth_icc_data_parent_class)->finalize (object);
+       G_OBJECT_CLASS (gth_icc_profile_parent_class)->finalize (object);
 }
 
 
 static void
-gth_icc_data_class_init (GthICCDataClass *klass)
+gth_icc_profile_class_init (GthICCProfileClass *klass)
 {
        GObjectClass *gobject_class;
 
-       g_type_class_add_private (klass, sizeof (GthICCDataPrivate));
+       g_type_class_add_private (klass, sizeof (GthICCProfilePrivate));
 
        gobject_class = (GObjectClass*) klass;
-       gobject_class->finalize = gth_icc_data_finalize;
+       gobject_class->finalize = gth_icc_profile_finalize;
 }
 
 
 static void
-gth_icc_data_init (GthICCData *self)
+gth_icc_profile_init (GthICCProfile *self)
 {
-       self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_ICC_DATA, GthICCDataPrivate);
-       self->priv->icc_profile = NULL;
-       self->priv->filename = NULL;
-}
-
-
-void
-gth_icc_profile_free (GthICCProfile icc_profile)
-{
-#ifdef HAVE_LCMS2
-       if (icc_profile != NULL)
-               cmsCloseProfile ((cmsHPROFILE) icc_profile);
-#endif
+       self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_ICC_PROFILE, GthICCProfilePrivate);
+       self->priv->cms_profile = NULL;
+       self->priv->id = NULL;
 }
 
 
 static char *
-gth_icc_profile_get_id (GthICCProfile icc_profile)
+_gth_cms_profile_create_id (GthCMSProfile cms_profile)
 {
-       GString *str;
+       GString  *str;
+       gboolean  id_set = FALSE;
 
        str = g_string_new ("");
 
@@ -103,7 +123,7 @@ gth_icc_profile_get_id (GthICCProfile icc_profile)
                gchar          *md5 = NULL;
                guint           i;
 
-               cmsGetHeaderProfileID ((cmsHPROFILE) icc_profile, icc_id);
+               cmsGetHeaderProfileID ((cmsHPROFILE) cms_profile, icc_id);
                for (i = 0; i < 16; i++) {
                        if (icc_id[i] != 0) {
                                md5_precooked = TRUE;
@@ -118,62 +138,162 @@ gth_icc_profile_get_id (GthICCProfile icc_profile)
                }
 
                if (md5 != NULL) {
-                       g_string_append (str, "md5://");
+                       g_string_append (str, GTH_ICC_PROFILE_WITH_MD5);
                        g_string_append (str, md5);
+                       id_set = TRUE;
                }
        }
 #endif
 
-       return g_string_free (str, FALSE);
-}
+       if (! id_set)
+               g_string_append (str, GTH_ICC_PROFILE_ID_UNKNOWN);
 
-void
-gth_icc_transform_free (GthICCTransform transform)
-{
-#ifdef HAVE_LCMS2
-       if (transform != NULL)
-               cmsDeleteTransform ((cmsHTRANSFORM) transform);
-#endif
+       return g_string_free (str, FALSE);
 }
 
 
-GthICCData *
-gth_icc_data_new (const char    *filename,
-                 GthICCProfile  profile)
+GthICCProfile *
+gth_icc_profile_new (const char    *id,
+                    GthCMSProfile  profile)
 {
-       GthICCData *icc_data;
+       GthICCProfile *icc_profile;
 
-       icc_data = g_object_new (GTH_TYPE_ICC_DATA, NULL);
-       if (filename != NULL)
-               icc_data->priv->filename = g_strdup (filename);
+       icc_profile = g_object_new (GTH_TYPE_ICC_PROFILE, NULL);
+       if (! gth_icc_profile_id_is_unknown (id))
+               icc_profile->priv->id = g_strdup (id);
        else
-               icc_data->priv->filename = gth_icc_profile_get_id (profile);
-       icc_data->priv->icc_profile = profile;
+               icc_profile->priv->id = _gth_cms_profile_create_id (profile);
+       icc_profile->priv->cms_profile = profile;
 
-       return icc_data;
+       return icc_profile;
 }
 
 
 const char *
-gth_icc_data_get_filename (GthICCData *self)
+gth_icc_profile_get_id (GthICCProfile *self)
 {
        g_return_val_if_fail (self != NULL, NULL);
-       return self->priv->filename;
+       return self->priv->id;
 }
 
 
-GthICCProfile
-gth_icc_data_get_profile (GthICCData *self)
+gboolean
+gth_icc_profile_id_is_unknown (const char *id)
+{
+       return (id == NULL) || (g_strcmp0 (id, GTH_ICC_PROFILE_ID_UNKNOWN) == 0);
+}
+
+
+GthCMSProfile
+gth_icc_profile_get_profile (GthICCProfile *self)
 {
        g_return_val_if_fail (self != NULL, NULL);
-       return self->priv->icc_profile;
+       return self->priv->cms_profile;
 }
 
 
 gboolean
-gth_icc_data_equal (GthICCData *a,
-                   GthICCData *b)
+gth_icc_profile_equal (GthICCProfile *a,
+                      GthICCProfile *b)
 {
        g_return_val_if_fail ((a == NULL) || (b == NULL), NULL);
-       return g_strcmp0 (a->priv->filename, b->priv->filename) == 0;
+
+       if (gth_icc_profile_id_is_unknown (a->priv->id) || gth_icc_profile_id_is_unknown (b->priv->id))
+               return FALSE;
+       else
+               return g_strcmp0 (a->priv->id, b->priv->id) == 0;
+}
+
+
+/* -- GthICCTransform -- */
+
+
+static void
+gth_icc_transform_finalize (GObject *object)
+{
+       GthICCTransform *icc_transform;
+
+       g_return_if_fail (object != NULL);
+       g_return_if_fail (GTH_IS_ICC_TRANSFORM (object));
+
+       icc_transform = GTH_ICC_TRANSFORM (object);
+       gth_cms_transform_free (icc_transform->priv->cms_transform);
+
+       /* Chain up */
+       G_OBJECT_CLASS (gth_icc_transform_parent_class)->finalize (object);
+}
+
+
+static void
+gth_icc_transform_class_init (GthICCTransformClass *klass)
+{
+       GObjectClass *gobject_class;
+
+       g_type_class_add_private (klass, sizeof (GthICCTransformPrivate));
+
+       gobject_class = (GObjectClass*) klass;
+       gobject_class->finalize = gth_icc_transform_finalize;
+}
+
+
+static void
+gth_icc_transform_init (GthICCTransform *self)
+{
+       self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_ICC_TRANSFORM, GthICCTransformPrivate);
+       self->priv->cms_transform = NULL;
+}
+
+
+GthICCTransform *
+gth_icc_transform_new (GthCMSTransform transform)
+{
+       GthICCTransform *icc_transform;
+
+       icc_transform = g_object_new (GTH_TYPE_ICC_TRANSFORM, NULL);
+       icc_transform->priv->cms_transform = transform;
+
+       return icc_transform;
+}
+
+
+#if HAVE_LCMS2
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN /* BGRA */
+#define _LCMS2_CAIRO_FORMAT TYPE_BGRA_8
+#elif G_BYTE_ORDER == G_BIG_ENDIAN /* ARGB */
+#define _LCMS2_CAIRO_FORMAT TYPE_ARGB_8
+#else
+#define _LCMS2_CAIRO_FORMAT TYPE_ABGR_8
+#endif
+#endif
+
+
+GthICCTransform *
+gth_icc_transform_new_from_profiles (GthICCProfile *from_profile,
+                                    GthICCProfile *to_profile)
+{
+#if HAVE_LCMS2
+       GthICCTransform *transform = NULL;
+       GthCMSTransform  cms_transform;
+
+       cms_transform = (GthCMSTransform) cmsCreateTransform ((cmsHPROFILE) gth_icc_profile_get_profile 
(from_profile),
+                                                             _LCMS2_CAIRO_FORMAT,
+                                                             (cmsHPROFILE) gth_icc_profile_get_profile 
(to_profile),
+                                                             _LCMS2_CAIRO_FORMAT,
+                                                             INTENT_PERCEPTUAL,
+                                                             0);
+       if (cms_transform != NULL)
+               transform = gth_icc_transform_new (cms_transform);
+
+       return transform;
+#else
+       return NULL;
+#endif
+}
+
+
+GthCMSTransform
+gth_icc_transform_get_transform (GthICCTransform *transform)
+{
+       g_return_val_if_fail (transform != NULL, NULL);
+       return transform->priv->cms_transform;
 }
diff --git a/gthumb/gth-icc-profile.h b/gthumb/gth-icc-profile.h
index 9562423..d7e759f 100644
--- a/gthumb/gth-icc-profile.h
+++ b/gthumb/gth-icc-profile.h
@@ -26,39 +26,71 @@
 
 G_BEGIN_DECLS
 
-typedef gpointer GthICCProfile;
-typedef gpointer GthICCTransform;
+typedef gpointer GthCMSProfile;
+typedef gpointer GthCMSTransform;
 
-#define GTH_TYPE_ICC_DATA            (gth_icc_data_get_type ())
-#define GTH_ICC_DATA(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_ICC_DATA, GthICCData))
-#define GTH_ICC_DATA_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_ICC_DATA, GthICCDataClass))
-#define GTH_IS_ICC_DATA(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_ICC_DATA))
-#define GTH_IS_ICC_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_ICC_DATA))
-#define GTH_ICC_DATA_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_ICC_DATA, GthICCDataClass))
+#define GTH_ICC_PROFILE_ID_UNKNOWN "unknown://"
+#define GTH_ICC_PROFILE_WITH_MD5 "md5://"
+#define GTH_ICC_PROFILE_FROM_PROPERTY "property://"
 
-typedef struct _GthICCData         GthICCData;
-typedef struct _GthICCDataPrivate  GthICCDataPrivate;
-typedef struct _GthICCDataClass    GthICCDataClass;
+#define GTH_TYPE_ICC_PROFILE            (gth_icc_profile_get_type ())
+#define GTH_ICC_PROFILE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_ICC_PROFILE, 
GthICCProfile))
+#define GTH_ICC_PROFILE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_ICC_PROFILE, 
GthICCProfileClass))
+#define GTH_IS_ICC_PROFILE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_ICC_PROFILE))
+#define GTH_IS_ICC_PROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_ICC_PROFILE))
+#define GTH_ICC_PROFILE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_ICC_PROFILE, 
GthICCProfileClass))
 
-struct _GthICCData {
+#define GTH_TYPE_ICC_TRANSFORM            (gth_icc_transform_get_type ())
+#define GTH_ICC_TRANSFORM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_ICC_TRANSFORM, 
GthICCTransform))
+#define GTH_ICC_TRANSFORM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_ICC_TRANSFORM, 
GthICCTransformClass))
+#define GTH_IS_ICC_TRANSFORM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_ICC_TRANSFORM))
+#define GTH_IS_ICC_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_ICC_TRANSFORM))
+#define GTH_ICC_TRANSFORM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_ICC_TRANSFORM, 
GthICCTransformClass))
+
+typedef struct _GthICCProfile         GthICCProfile;
+typedef struct _GthICCProfilePrivate  GthICCProfilePrivate;
+typedef struct _GthICCProfileClass    GthICCProfileClass;
+
+typedef struct _GthICCTransform         GthICCTransform;
+typedef struct _GthICCTransformPrivate  GthICCTransformPrivate;
+typedef struct _GthICCTransformClass    GthICCTransformClass;
+
+struct _GthICCProfile {
+       GObject __parent;
+       GthICCProfilePrivate *priv;
+};
+
+struct _GthICCProfileClass {
+       GObjectClass __parent_class;
+};
+
+struct _GthICCTransform {
        GObject __parent;
-       GthICCDataPrivate *priv;
+       GthICCTransformPrivate *priv;
 };
 
-struct _GthICCDataClass {
+struct _GthICCTransformClass {
        GObjectClass __parent_class;
 };
 
-void           gth_icc_profile_free            (GthICCProfile   icc_profile);
-void           gth_icc_transform_free          (GthICCTransform transform);
+void                   gth_cms_profile_free            (GthCMSProfile    profile);
+void                   gth_cms_transform_free          (GthCMSTransform  transform);
+
+GType                  gth_icc_profile_get_type        (void);
+GthICCProfile *                gth_icc_profile_new             (const char      *id,
+                                                        GthCMSProfile    profile);
+const char *           gth_icc_profile_get_id          (GthICCProfile   *icc_profile);
+gboolean                gth_icc_profile_id_is_unknown   (const char      *id);
+GthCMSProfile          gth_icc_profile_get_profile     (GthICCProfile   *icc_profile);
+gboolean               gth_icc_profile_equal           (GthICCProfile   *a,
+                                                        GthICCProfile   *b);
 
-GType          gth_icc_data_get_type           (void);
-GthICCData *   gth_icc_data_new                (const char     *filename,
-                                                GthICCProfile   profile);
-const char *   gth_icc_data_get_filename       (GthICCData     *icc_data);
-GthICCProfile  gth_icc_data_get_profile        (GthICCData     *icc_data);
-gboolean       gth_icc_data_equal              (GthICCData     *a,
-                                                GthICCData     *b);
+GType                  gth_icc_transform_get_type      (void);
+GthICCTransform *      gth_icc_transform_new           (GthCMSTransform  transform);
+GthICCTransform *      gth_icc_transform_new_from_profiles
+                                                       (GthICCProfile   *from_profile,
+                                                        GthICCProfile   *to_profile);
+GthCMSTransform         gth_icc_transform_get_transform (GthICCTransform *transform);
 
 G_END_DECLS
 
diff --git a/gthumb/gth-image-loader.c b/gthumb/gth-image-loader.c
index 595dcfa..7c60bf4 100644
--- a/gthumb/gth-image-loader.c
+++ b/gthumb/gth-image-loader.c
@@ -33,7 +33,7 @@ struct _GthImageLoaderPrivate {
        gboolean           as_animation;  /* Whether to load the image in a
                                           * GdkPixbufAnimation structure. */
        GthImageFormat     preferred_format;
-       GthICCData        *out_profile;
+       GthICCProfile     *out_profile;
        GthImageLoaderFunc loader_func;
        gpointer           loader_data;
 };
@@ -114,7 +114,7 @@ gth_image_loader_set_preferred_format (GthImageLoader *self,
 
 void
 gth_image_loader_set_out_profile (GthImageLoader *self,
-                                 GthICCData     *out_profile)
+                                 GthICCProfile  *out_profile)
 {
        g_return_if_fail (self != NULL);
 
diff --git a/gthumb/gth-image-loader.h b/gthumb/gth-image-loader.h
index 2877501..96a367e 100644
--- a/gthumb/gth-image-loader.h
+++ b/gthumb/gth-image-loader.h
@@ -58,7 +58,7 @@ void              gth_image_loader_set_loader_func        (GthImageLoader
 void              gth_image_loader_set_preferred_format   (GthImageLoader       *loader,
                                                           GthImageFormat        preferred_format);
 void              gth_image_loader_set_out_profile        (GthImageLoader       *loader,
-                                                          GthICCData           *profile);
+                                                          GthICCProfile        *profile);
 void              gth_image_loader_load                   (GthImageLoader       *loader,
                                                           GthFileData          *file_data,
                                                           int                   requested_size,
diff --git a/gthumb/gth-image-preloader.c b/gthumb/gth-image-preloader.c
index 3079f33..c4d29ea 100644
--- a/gthumb/gth-image-preloader.c
+++ b/gthumb/gth-image-preloader.c
@@ -78,7 +78,7 @@ struct _GthImagePreloaderPrivate {
        GthImageLoader          *loader;
        GQueue                  *cache;
        guint                    load_next_id;
-       GthICCData              *out_profile;
+       GthICCProfile           *out_profile;
 };
 
 
@@ -293,7 +293,7 @@ gth_image_preloader_new (void)
 
 void
 gth_image_preloader_set_out_profile (GthImagePreloader *self,
-                                    GthICCData        *out_profile)
+                                    GthICCProfile     *out_profile)
 {
        g_return_if_fail (self != NULL);
 
diff --git a/gthumb/gth-image-preloader.h b/gthumb/gth-image-preloader.h
index aa59ba3..8fe1670 100644
--- a/gthumb/gth-image-preloader.h
+++ b/gthumb/gth-image-preloader.h
@@ -52,7 +52,7 @@ struct _GthImagePreloaderClass {
 GType               gth_image_preloader_get_type                (void) G_GNUC_CONST;
 GthImagePreloader * gth_image_preloader_new                     (void);
 void                gth_image_preloader_set_out_profile                 (GthImagePreloader              
*loader,
-                                                                 GthICCData                     *profile);
+                                                                 GthICCProfile                  *profile);
 void                gth_image_preloader_load                    (GthImagePreloader              *self,
                                                                  GthFileData                    *requested,
                                                                  int                             
requested_size,
diff --git a/gthumb/gth-image.c b/gthumb/gth-image.c
index 6f8dd82..f6cd00e 100644
--- a/gthumb/gth-image.c
+++ b/gthumb/gth-image.c
@@ -44,7 +44,7 @@ struct _GthImagePrivate {
                GdkPixbuf          *pixbuf;
                GdkPixbufAnimation *pixbuf_animation;
        } data;
-       GthICCData *icc_data;
+       GthICCProfile *icc_data;
 };
 
 
@@ -422,7 +422,7 @@ gth_image_get_is_animation (GthImage *image)
 
 void
 gth_image_set_icc_profile (GthImage   *image,
-                          GthICCData *profile)
+                          GthICCProfile *profile)
 {
        _g_object_ref (profile);
        _gth_image_free_icc_profile (image);
@@ -430,7 +430,7 @@ gth_image_set_icc_profile (GthImage   *image,
 }
 
 
-GthICCData *
+GthICCProfile *
 gth_image_get_icc_profile (GthImage *image)
 {
        g_return_val_if_fail (image != NULL, NULL);
@@ -443,14 +443,13 @@ gth_image_get_icc_profile (GthImage *image)
 
 void
 gth_image_apply_icc_profile (GthImage      *image,
-                            GthICCData    *out_profile,
+                            GthICCProfile *out_profile,
                             GCancellable  *cancellable)
 {
 #if HAVE_LCMS2
 
        cairo_surface_t *surface;
-       cmsHTRANSFORM    hTransform;
-       gboolean         delete_transform = FALSE;
+       GthICCTransform *transform;
 
        g_return_if_fail (image != NULL);
 
@@ -467,24 +466,19 @@ gth_image_apply_icc_profile (GthImage      *image,
        if (surface == NULL)
                return;
 
-       hTransform = (cmsHTRANSFORM) gth_color_manager_get_transform (gth_main_get_default_color_manager (),
-                                                                     image->priv->icc_data,
-                                                                     out_profile);
+       transform = gth_color_manager_get_transform (gth_main_get_default_color_manager (),
+                                                    image->priv->icc_data,
+                                                    out_profile);
 
-       if (hTransform == NULL) {
-               hTransform = (cmsHTRANSFORM) gth_color_manager_create_transform 
(gth_main_get_default_color_manager (),
-                                                                                image->priv->icc_data,
-                                                                                out_profile);
-               delete_transform = (hTransform != NULL);
-       }
-
-       if (hTransform != NULL) {
+       if (transform != NULL) {
+               cmsHTRANSFORM    hTransform;
                unsigned char   *surface_row;
                int              width;
                int              height;
                int              row_stride;
                int              row;
 
+               hTransform = (cmsHTRANSFORM) gth_icc_transform_get_transform (transform);
                surface_row = _cairo_image_surface_flush_and_get_data (surface);
                width = cairo_image_surface_get_width (surface);
                height = cairo_image_surface_get_height (surface);
@@ -501,8 +495,8 @@ gth_image_apply_icc_profile (GthImage      *image,
                cairo_surface_destroy (surface);
        }
 
-       if (delete_transform)
-               cmsDeleteTransform (hTransform);
+       _g_object_unref (transform);
+
 #endif
 }
 
@@ -512,7 +506,7 @@ gth_image_apply_icc_profile (GthImage      *image,
 
 typedef struct {
        GthImage   *image;
-       GthICCData *out_profile;
+       GthICCProfile *out_profile;
 } ApplyProfileData;
 
 
@@ -550,7 +544,7 @@ _gth_image_apply_icc_profile_thread (GSimpleAsyncResult *result,
 
 void
 gth_image_apply_icc_profile_async (GthImage            *image,
-                                  GthICCData           *out_profile,
+                                  GthICCProfile        *out_profile,
                                   GCancellable         *cancellable,
                                   GAsyncReadyCallback   callback,
                                   gpointer              user_data)
diff --git a/gthumb/gth-image.h b/gthumb/gth-image.h
index 566c123..7bae2ce 100644
--- a/gthumb/gth-image.h
+++ b/gthumb/gth-image.h
@@ -103,13 +103,13 @@ void                  gth_image_set_pixbuf_animation        (GthImage
 GdkPixbufAnimation *  gth_image_get_pixbuf_animation        (GthImage           *image);
 gboolean              gth_image_get_is_animation            (GthImage           *image);
 void                 gth_image_set_icc_profile             (GthImage           *image,
-                                                            GthICCData         *profile);
-GthICCData *         gth_image_get_icc_profile             (GthImage           *image);
+                                                            GthICCProfile      *profile);
+GthICCProfile *              gth_image_get_icc_profile             (GthImage           *image);
 void                 gth_image_apply_icc_profile           (GthImage           *image,
-                                                            GthICCData         *out_profile,
+                                                            GthICCProfile      *out_profile,
                                                             GCancellable       *cancellable);
 void                 gth_image_apply_icc_profile_async     (GthImage           *image,
-                                                            GthICCData         *out_profile,
+                                                            GthICCProfile      *out_profile,
                                                             GCancellable       *cancellable,
                                                             GAsyncReadyCallback callback,
                                                             gpointer            user_data);


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