[gthumb] image history: save a GthImage to preserve the icc profile



commit fa3eb2ea4b5b13410d34981169a86a435bae96e7
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Thu Feb 5 18:16:26 2015 +0100

    image history: save a GthImage to preserve the icc profile

 extensions/file_tools/gth-file-tool-resize.c    |    8 +-
 extensions/image_viewer/gth-image-viewer-page.c |   57 ++++++---
 gthumb/gth-image-history.c                      |   34 ++++--
 gthumb/gth-image-history.h                      |   53 +++++----
 gthumb/gth-image-preloader.c                    |    4 +-
 gthumb/gth-image-preloader.h                    |    2 +-
 gthumb/gth-image.c                              |  153 +++++++++++++++++++++--
 gthumb/gth-image.h                              |    3 +
 8 files changed, 248 insertions(+), 66 deletions(-)
---
diff --git a/extensions/file_tools/gth-file-tool-resize.c b/extensions/file_tools/gth-file-tool-resize.c
index 5136840..7319f94 100644
--- a/extensions/file_tools/gth-file-tool-resize.c
+++ b/extensions/file_tools/gth-file-tool-resize.c
@@ -117,10 +117,10 @@ resize_task_completed_cb (GthTask  *task,
        gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->new_image, FALSE);
 
        if (self->priv->apply_to_original) {
-               gth_image_history_add_image (gth_image_viewer_page_get_history (GTH_IMAGE_VIEWER_PAGE 
(viewer_page)),
-                                            self->priv->new_image,
-                                            -1,
-                                            TRUE);
+               gth_image_history_add_surface (gth_image_viewer_page_get_history (GTH_IMAGE_VIEWER_PAGE 
(viewer_page)),
+                                              self->priv->new_image,
+                                              -1,
+                                              TRUE);
                gth_viewer_page_focus (GTH_VIEWER_PAGE (viewer_page));
                gth_file_tool_hide_options (GTH_FILE_TOOL (self));
        }
diff --git a/extensions/image_viewer/gth-image-viewer-page.c b/extensions/image_viewer/gth-image-viewer-page.c
index 7ad6a5c..baf2ab1 100644
--- a/extensions/image_viewer/gth-image-viewer-page.c
+++ b/extensions/image_viewer/gth-image-viewer-page.c
@@ -1063,7 +1063,7 @@ preloader_load_ready_cb (GObject  *source_object,
 
        gth_image_history_clear (self->priv->history);
        gth_image_history_add_image (self->priv->history,
-                                    gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER 
(self->priv->viewer)),
+                                    image,
                                     requested_size,
                                     FALSE);
 
@@ -1504,21 +1504,20 @@ gth_image_viewer_page_real_save_as (GthViewerPage *base,
 
 static void
 _gth_image_viewer_page_set_image (GthImageViewerPage *self,
-                                 cairo_surface_t    *image,
+                                 GthImage           *image,
                                  int                 requested_size,
                                  gboolean            modified)
 {
        GthFileData *file_data;
        int          width;
        int          height;
-       char        *size;
 
        if (image == NULL)
                return;
 
        if (modified)
                gth_image_preloader_set_modified_image (self->priv->preloader, image);
-       gth_image_viewer_set_surface (GTH_IMAGE_VIEWER (self->priv->viewer), image, -1, -1);
+       gth_image_viewer_set_image (GTH_IMAGE_VIEWER (self->priv->viewer), image, -1, -1);
        gth_image_viewer_set_requested_size (GTH_IMAGE_VIEWER (self->priv->viewer), requested_size);
 
        file_data = gth_browser_get_current_file (GTH_BROWSER (self->priv->browser));
@@ -1526,16 +1525,16 @@ _gth_image_viewer_page_set_image (GthImageViewerPage *self,
        self->priv->image_changed = modified;
        g_file_info_set_attribute_boolean (file_data->info, "gth::file::is-modified", modified);
 
-       if (! _cairo_image_surface_get_original_size (image, &width, &height)) {
-               width = cairo_image_surface_get_width (image);
-               height = cairo_image_surface_get_height (image);
-       }
-       g_file_info_set_attribute_int32 (file_data->info, "image::width", width);
-       g_file_info_set_attribute_int32 (file_data->info, "image::height", height);
+       if (gth_image_get_original_size (image, &width, &height)) {
+               char *size;
+
+               g_file_info_set_attribute_int32 (file_data->info, "image::width", width);
+               g_file_info_set_attribute_int32 (file_data->info, "image::height", height);
 
-       size = g_strdup_printf (_("%d × %d"), width, height);
-       g_file_info_set_attribute_string (file_data->info, "general::dimensions", size);
-       g_free (size);
+               size = g_strdup_printf (_("%d × %d"), width, height);
+               g_file_info_set_attribute_string (file_data->info, "general::dimensions", size);
+               g_free (size);
+       }
 
        gth_monitor_metadata_changed (gth_main_get_default_monitor (), file_data);
 
@@ -1544,6 +1543,21 @@ _gth_image_viewer_page_set_image (GthImageViewerPage *self,
 
 
 static void
+_gth_image_viewer_page_set_surface (GthImageViewerPage *self,
+                                   cairo_surface_t    *surface,
+                                   int                 requested_size,
+                                   gboolean            modified)
+{
+       GthImage *image;
+
+       image = gth_image_new_for_surface (surface);
+       _gth_image_viewer_page_set_image (self, image, requested_size, modified);
+
+       g_object_unref (image);
+}
+
+
+static void
 gth_image_viewer_page_real_revert (GthViewerPage *base)
 {
        GthImageViewerPage *self = GTH_IMAGE_VIEWER_PAGE (base);
@@ -1729,9 +1743,9 @@ gth_image_viewer_page_set_image (GthImageViewerPage *self,
                return;
 
        if (add_to_history)
-               gth_image_history_add_image (self->priv->history, image, -1, TRUE);
+               gth_image_history_add_surface (self->priv->history, image, -1, TRUE);
 
-       _gth_image_viewer_page_set_image (self, image, -1, TRUE);
+       _gth_image_viewer_page_set_surface (self, image, -1, TRUE);
 
        if (add_to_history)
                gth_viewer_page_focus (GTH_VIEWER_PAGE (self));
@@ -2095,6 +2109,15 @@ gth_image_viewer_page_apply_icc_profile  (GthImageViewerPage *self,
        gth_image_preloader_clear_cache (self->priv->preloader);
 
        file_data = gth_browser_get_current_file (self->priv->browser);
-       if (file_data != NULL)
-               _gth_image_viewer_page_load (self, file_data);
+       if (file_data == NULL)
+               return;
+
+       /* force a complete reload */
+       _g_object_unref (self->priv->last_loaded);
+       self->priv->last_loaded = NULL;
+
+       g_object_ref (file_data);
+       _gth_image_viewer_page_load (self, file_data);
+
+       g_object_unref (file_data);
 }
diff --git a/gthumb/gth-image-history.c b/gthumb/gth-image-history.c
index d58c66d..35ed066 100644
--- a/gthumb/gth-image-history.c
+++ b/gthumb/gth-image-history.c
@@ -20,6 +20,7 @@
  */
 
 #include <config.h>
+#include "glib-utils.h"
 #include "gth-image-history.h"
 
 
@@ -33,9 +34,9 @@ G_DEFINE_TYPE (GthImageHistory, gth_image_history, G_TYPE_OBJECT)
 
 
 GthImageData *
-gth_image_data_new (cairo_surface_t *image,
-                   int              requested_size,
-                   gboolean         unsaved)
+gth_image_data_new (GthImage *image,
+                   int       requested_size,
+                   gboolean  unsaved)
 {
        GthImageData *idata;
 
@@ -44,7 +45,7 @@ gth_image_data_new (cairo_surface_t *image,
        idata = g_new0 (GthImageData, 1);
 
        idata->ref = 1;
-       idata->image = cairo_surface_reference (image);
+       idata->image = _g_object_ref (image);
        idata->requested_size = requested_size;
        idata->unsaved = unsaved;
 
@@ -68,7 +69,7 @@ gth_image_data_unref (GthImageData *idata)
 
        idata->ref--;
        if (idata->ref == 0) {
-               cairo_surface_destroy (idata->image);
+               _g_object_unref (idata->image);
                g_free (idata);
        }
 }
@@ -173,7 +174,7 @@ remove_first_image (GList **list)
 
 static GList*
 add_image_to_list (GList           *list,
-                  cairo_surface_t *image,
+                  GthImage        *image,
                   int              requested_size,
                   gboolean         unsaved)
 {
@@ -196,7 +197,7 @@ add_image_to_list (GList           *list,
 
 static void
 add_image_to_undo_history (GthImageHistory *history,
-                          cairo_surface_t *image,
+                          GthImage        *image,
                           int              requested_size,
                           gboolean         unsaved)
 {
@@ -209,7 +210,7 @@ add_image_to_undo_history (GthImageHistory *history,
 
 static void
 add_image_to_redo_history (GthImageHistory *history,
-                          cairo_surface_t *image,
+                          GthImage        *image,
                           int              requested_size,
                           gboolean         unsaved)
 {
@@ -222,7 +223,7 @@ add_image_to_redo_history (GthImageHistory *history,
 
 void
 gth_image_history_add_image (GthImageHistory *history,
-                            cairo_surface_t *image,
+                            GthImage        *image,
                             int              requested_size,
                             gboolean         unsaved)
 {
@@ -236,6 +237,21 @@ gth_image_history_add_image (GthImageHistory *history,
 }
 
 
+void
+gth_image_history_add_surface (GthImageHistory *history,
+                              cairo_surface_t *surface,
+                              int              requested_size,
+                              gboolean         unsaved)
+{
+       GthImage *image;
+
+       image = gth_image_new_for_surface (surface);
+       gth_image_history_add_image (history, image, requested_size, unsaved);
+
+       g_object_unref (image);
+}
+
+
 GthImageData *
 gth_image_history_undo (GthImageHistory *history)
 {
diff --git a/gthumb/gth-image-history.h b/gthumb/gth-image-history.h
index ffd686d..9b1d605 100644
--- a/gthumb/gth-image-history.h
+++ b/gthumb/gth-image-history.h
@@ -25,6 +25,7 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <cairo.h>
+#include "gth-image.h"
 
 G_BEGIN_DECLS
 
@@ -40,10 +41,10 @@ typedef struct _GthImageHistoryPrivate GthImageHistoryPrivate;
 typedef struct _GthImageHistoryClass   GthImageHistoryClass;
 
 typedef struct {
-       int              ref;
-       cairo_surface_t *image;
-       int              requested_size;
-       gboolean         unsaved;
+       int       ref;
+       GthImage *image;
+       int       requested_size;
+       gboolean  unsaved;
 } GthImageData;
 
 struct _GthImageHistory {
@@ -59,26 +60,30 @@ struct _GthImageHistoryClass {
        void (*changed) (GthImageHistory *image_history);
 };
 
-GthImageData *    gth_image_data_new           (cairo_surface_t *image,
-                                               int              requested_size,
-                                               gboolean         unsaved);
-GthImageData *    gth_image_data_ref           (GthImageData    *idata);
-void              gth_image_data_unref         (GthImageData    *idata);
-void              gth_image_data_list_free     (GList           *list);
-
-GType             gth_image_history_get_type   (void);
-GthImageHistory * gth_image_history_new        (void);
-void              gth_image_history_add_image  (GthImageHistory *history,
-                                               cairo_surface_t *image,
-                                               int              requested_size,
-                                               gboolean         unsaved);
-GthImageData *    gth_image_history_undo       (GthImageHistory *history);
-GthImageData *    gth_image_history_redo       (GthImageHistory *history);
-void              gth_image_history_clear      (GthImageHistory *history);
-gboolean          gth_image_history_can_undo   (GthImageHistory *history);
-gboolean          gth_image_history_can_redo   (GthImageHistory *history);
-GthImageData *    gth_image_history_revert     (GthImageHistory *history);
-GthImageData *    gth_image_history_get_last   (GthImageHistory *history);
+GthImageData *    gth_image_data_new           (GthImage        *image,
+                                                int              requested_size,
+                                                gboolean         unsaved);
+GthImageData *    gth_image_data_ref           (GthImageData    *idata);
+void              gth_image_data_unref         (GthImageData    *idata);
+void              gth_image_data_list_free     (GList           *list);
+
+GType             gth_image_history_get_type   (void);
+GthImageHistory * gth_image_history_new                (void);
+void              gth_image_history_add_image  (GthImageHistory *history,
+                                                GthImage        *image,
+                                                int              requested_size,
+                                                gboolean         unsaved);
+void              gth_image_history_add_surface        (GthImageHistory *history,
+                                                cairo_surface_t *image,
+                                                int              requested_size,
+                                                gboolean         unsaved);
+GthImageData *    gth_image_history_undo       (GthImageHistory *history);
+GthImageData *    gth_image_history_redo       (GthImageHistory *history);
+void              gth_image_history_clear      (GthImageHistory *history);
+gboolean          gth_image_history_can_undo   (GthImageHistory *history);
+gboolean          gth_image_history_can_redo   (GthImageHistory *history);
+GthImageData *    gth_image_history_revert     (GthImageHistory *history);
+GthImageData *    gth_image_history_get_last   (GthImageHistory *history);
 
 G_END_DECLS
 
diff --git a/gthumb/gth-image-preloader.c b/gthumb/gth-image-preloader.c
index 537d10f..8768e21 100644
--- a/gthumb/gth-image-preloader.c
+++ b/gthumb/gth-image-preloader.c
@@ -866,7 +866,7 @@ gth_image_preloader_load_finish (GthImagePreloader   *self,
 
 void
 gth_image_preloader_set_modified_image (GthImagePreloader *self,
-                                       cairo_surface_t   *image)
+                                       GthImage          *image)
 {
        GList     *scan;
        CacheData *cache_data;
@@ -889,7 +889,7 @@ gth_image_preloader_set_modified_image (GthImagePreloader *self,
 
        cache_data = cache_data_new ();
        cache_data->file_data = GTH_MODIFIED_IMAGE;
-       cache_data->image = gth_image_new_for_surface (image);
+       cache_data->image = g_object_ref (image);
        cache_data->original_width = -1;
        cache_data->original_height = -1;
        cache_data->requested_size = -1;
diff --git a/gthumb/gth-image-preloader.h b/gthumb/gth-image-preloader.h
index 94e9e1f..d5de045 100644
--- a/gthumb/gth-image-preloader.h
+++ b/gthumb/gth-image-preloader.h
@@ -70,7 +70,7 @@ gboolean            gth_image_preloader_load_finish                    (GthImagePreloader   
           *
                                                                  int                            
*original_height,
                                                                  GError                        **error);
 void                gth_image_preloader_set_modified_image      (GthImagePreloader              *self,
-                                                                 cairo_surface_t                *image);
+                                                                 GthImage                       *image);
 cairo_surface_t *   gth_image_preloader_get_modified_image      (GthImagePreloader              *self);
 void               gth_image_preloader_clear_cache              (GthImagePreloader              *self);
 
diff --git a/gthumb/gth-image.c b/gthumb/gth-image.c
index 1cee383..4b5fffb 100644
--- a/gthumb/gth-image.c
+++ b/gthumb/gth-image.c
@@ -33,6 +33,91 @@
 #include "pixbuf-utils.h"
 
 
+/* -- GthICCData -- */
+
+
+#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))
+
+typedef struct _GthICCData         GthICCData;
+typedef struct _GthICCDataClass    GthICCDataClass;
+
+struct _GthICCData {
+       GObject __parent;
+       GthICCProfile icc_profile;
+};
+
+struct _GthICCDataClass {
+       GObjectClass __parent_class;
+};
+
+
+static GType gth_icc_data_get_type (void);
+
+
+G_DEFINE_TYPE (GthICCData, gth_icc_data, G_TYPE_OBJECT)
+
+
+static void
+gth_icc_data_finalize (GObject *object)
+{
+       GthICCData *icc_data;
+
+       g_return_if_fail (object != NULL);
+       g_return_if_fail (GTH_IS_ICC_DATA (object));
+
+       icc_data = GTH_ICC_DATA (object);
+       gth_icc_profile_free (icc_data->icc_profile);
+
+       /* Chain up */
+       G_OBJECT_CLASS (gth_icc_data_parent_class)->finalize (object);
+}
+
+
+static void
+gth_icc_data_class_init (GthICCDataClass *klass)
+{
+       GObjectClass *gobject_class;
+
+       gobject_class = (GObjectClass*) klass;
+       gobject_class->finalize = gth_icc_data_finalize;
+}
+
+
+static void
+gth_icc_data_init (GthICCData *self)
+{
+       self->icc_profile = NULL;
+}
+
+
+static GthICCData *
+gth_icc_data_new (GthICCProfile profile)
+{
+       GthICCData *icc_data;
+
+       icc_data = g_object_new (GTH_TYPE_ICC_DATA, NULL);
+       icc_data->icc_profile = profile;
+
+       return icc_data;
+}
+
+
+static GthICCProfile
+gth_icc_data_get_profile (GthICCData *self)
+{
+       g_return_val_if_fail (self != NULL, NULL);
+       return self->icc_profile;
+}
+
+
+/* -- GthImage -- */
+
+
 struct _GthImagePrivate {
        GthImageFormat format;
        union {
@@ -40,7 +125,7 @@ struct _GthImagePrivate {
                GdkPixbuf          *pixbuf;
                GdkPixbufAnimation *pixbuf_animation;
        } data;
-       GthICCProfile icc_profile;
+       GthICCData *icc_data;
 };
 
 
@@ -75,8 +160,8 @@ _gth_image_free_data (GthImage *self)
 static void
 _gth_image_free_icc_profile (GthImage *self)
 {
-       gth_icc_profile_free (self->priv->icc_profile);
-       self->priv->icc_profile = NULL;
+       _g_object_unref (self->priv->icc_data);
+       self->priv->icc_data = NULL;
 }
 
 
@@ -132,7 +217,7 @@ gth_image_init (GthImage *self)
        self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_IMAGE, GthImagePrivate);
        self->priv->format = GTH_IMAGE_FORMAT_CAIRO_SURFACE;
        self->priv->data.surface = NULL;
-       self->priv->icc_profile = NULL;
+       self->priv->icc_data = NULL;
 }
 
 
@@ -173,6 +258,7 @@ gth_image_copy (GthImage *image)
        GthImage *new_image;
 
        new_image = gth_image_new ();
+       gth_image_set_icc_profile (new_image, gth_image_get_icc_profile (image));
 
        switch (image->priv->format) {
        case GTH_IMAGE_FORMAT_CAIRO_SURFACE:
@@ -243,6 +329,45 @@ gth_image_get_cairo_surface (GthImage *image)
 
 
 gboolean
+gth_image_get_original_size (GthImage *image,
+                            int      *width,
+                            int      *height)
+{
+       cairo_surface_t *surface;
+       int              local_width;
+       int              local_height;
+       gboolean         value_set = FALSE;
+
+       switch (image->priv->format) {
+       case GTH_IMAGE_FORMAT_CAIRO_SURFACE:
+               surface = gth_image_get_cairo_surface (image);
+               if (! _cairo_image_surface_get_original_size (surface, &local_width, &local_height)) {
+                       local_width = cairo_image_surface_get_width (surface);
+                       local_height = cairo_image_surface_get_height (surface);
+               }
+               value_set = TRUE;
+               break;
+
+       case GTH_IMAGE_FORMAT_GDK_PIXBUF:
+               local_width = gdk_pixbuf_get_width (image->priv->data.pixbuf);
+               local_height = gdk_pixbuf_get_height (image->priv->data.pixbuf);
+               value_set = TRUE;
+               break;
+
+       case GTH_IMAGE_FORMAT_GDK_PIXBUF_ANIMATION:
+               if (image->priv->data.pixbuf_animation != NULL) {
+                       local_width = gdk_pixbuf_animation_get_width (image->priv->data.pixbuf_animation);
+                       local_height = gdk_pixbuf_animation_get_width (image->priv->data.pixbuf_animation);
+                       value_set = TRUE;
+               }
+               break;
+       }
+
+       return value_set;
+}
+
+
+gboolean
 gth_image_get_is_zoomable (GthImage *self)
 {
        if (self == NULL)
@@ -373,7 +498,8 @@ gth_image_set_icc_profile (GthImage  *image,
                           GthICCProfile  profile)
 {
        _gth_image_free_icc_profile (image);
-       image->priv->icc_profile = profile;
+       if (profile != NULL)
+               image->priv->icc_data = gth_icc_data_new (profile);
 }
 
 
@@ -381,7 +507,7 @@ GthICCProfile
 gth_image_get_icc_profile (GthImage *image)
 {
        g_return_val_if_fail (image != NULL, NULL);
-       return image->priv->icc_profile;
+       return (image->priv->icc_data != NULL) ? gth_icc_data_get_profile (image->priv->icc_data) : NULL;
 }
 
 
@@ -406,6 +532,7 @@ gth_image_apply_icc_profile (GthImage      *image,
 {
 #if HAVE_LCMS2
 
+       GthICCProfile    image_profile;
        cmsHTRANSFORM    hTransform;
        cairo_surface_t *surface;
        unsigned char   *surface_row;
@@ -414,10 +541,19 @@ gth_image_apply_icc_profile (GthImage      *image,
        int              row_stride;
        int              row;
 
+       g_return_if_fail (image != NULL);
+
+       if (out_profile == NULL)
+               return;
+
+       image_profile = gth_image_get_icc_profile (image);
+       if (image_profile == NULL)
+               return;
+
        if (image->priv->format != GTH_IMAGE_FORMAT_CAIRO_SURFACE)
                return;
 
-       hTransform = cmsCreateTransform ((cmsHPROFILE) image->priv->icc_profile,
+       hTransform = cmsCreateTransform ((cmsHPROFILE) image_profile,
                                         _LCMS2_CAIRO_FORMAT,
                                         (cmsHPROFILE) out_profile,
                                         _LCMS2_CAIRO_FORMAT,
@@ -474,8 +610,7 @@ _gth_image_apply_icc_profile_thread (GSimpleAsyncResult *result,
        GError           *error = NULL;
 
        apd = g_simple_async_result_get_op_res_gpointer (result);
-       if ((apd->image->priv->icc_profile != NULL) && (apd->out_profile != NULL))
-               gth_image_apply_icc_profile (apd->image, apd->out_profile, cancellable);
+       gth_image_apply_icc_profile (apd->image, apd->out_profile, cancellable);
 
        if ((cancellable != NULL) && g_cancellable_is_cancelled (cancellable))
                error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, "");
diff --git a/gthumb/gth-image.h b/gthumb/gth-image.h
index 9528b13..c55f9d8 100644
--- a/gthumb/gth-image.h
+++ b/gthumb/gth-image.h
@@ -88,6 +88,9 @@ GthImage *            gth_image_copy                        (GthImage
 void                  gth_image_set_cairo_surface           (GthImage           *image,
                                                             cairo_surface_t    *value);
 cairo_surface_t *     gth_image_get_cairo_surface           (GthImage           *image);
+gboolean              gth_image_get_original_size          (GthImage           *image,
+                                                            int                *width,
+                                                            int                *height);
 gboolean              gth_image_get_is_zoomable             (GthImage           *image);
 gboolean              gth_image_set_zoom                    (GthImage           *image,
                                                             double              zoom,


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