Bug fix #934: Request to add image bookmarking/tagging within a folder
[geeqie.git] / src / thumb_standard.c
index 43ab9fe..6e89260 100644 (file)
@@ -30,6 +30,7 @@
 #include "filedata.h"
 #include "exif.h"
 #include "metadata.h"
+#include "color-man.h"
 
 
 /**
@@ -38,8 +39,7 @@
  * This thumbnail caching implementation attempts to conform
  * to the Thumbnail Managing Standard proposed on freedesktop.org
  * The standard is documented here: \n
- *   http://triq.net/~jens/thumbnail-spec/index.html \n
- *  (why isn't it actually hosted on freedesktop.org?)
+ *   https://www.freedesktop.org/wiki/Specifications/thumbnails/ \n
  *
  * This code attempts to conform to version 0.7.0 of the standard.
  *
@@ -386,6 +386,104 @@ static void thumb_loader_std_set_fallback(ThumbLoaderStd *tl)
        tl->fd->thumb_pixbuf = pixbuf_fallback(tl->fd, tl->requested_width, tl->requested_height);
 }
 
+
+void thumb_loader_std_calibrate_pixbuf(FileData *fd, GdkPixbuf *pixbuf) {
+       ColorMan *cm = NULL;
+       ExifData *exif = NULL;
+       gint color_profile_from_image = COLOR_PROFILE_NONE;
+       ColorManProfileType input_type = COLOR_PROFILE_MEM;
+       ColorManProfileType screen_type;
+       const gchar *input_file = NULL;
+       guchar *profile = NULL;
+       guint profile_len;
+       gint sw, sh;
+
+       if (!options->thumbnails.use_color_management)
+               {
+               return;
+               }
+
+       sw = gdk_pixbuf_get_width(pixbuf);
+       sh = gdk_pixbuf_get_height(pixbuf);
+
+       exif = exif_read_fd(fd);
+
+       if (exif)
+               {
+               profile = exif_get_color_profile(exif, &profile_len);
+               if (profile)
+                       {
+                       DEBUG_1("Found embedded color profile");
+                       color_profile_from_image = COLOR_PROFILE_MEM;
+                       }
+               else
+                       {
+                       gchar *interop_index = exif_get_data_as_text(exif, "Exif.Iop.InteroperabilityIndex");
+
+                       if (interop_index)
+                               {
+                               /* Exif 2.21 specification */
+                               if (!strcmp(interop_index, "R98"))
+                                       {
+                                       color_profile_from_image = COLOR_PROFILE_SRGB;
+                                       DEBUG_1("Found EXIF 2.21 ColorSpace of sRGB");
+                                       }
+                               else if (!strcmp(interop_index, "R03"))
+                                       {
+                                       color_profile_from_image = COLOR_PROFILE_ADOBERGB;
+                                       DEBUG_1("Found EXIF 2.21 ColorSpace of AdobeRGB");
+                                       }
+                               g_free(interop_index);
+                               }
+                       else
+                               {
+                               gint cs;
+
+                               /* ColorSpace == 1 specifies sRGB per EXIF 2.2 */
+                               if (!exif_get_integer(exif, "Exif.Photo.ColorSpace", &cs)) cs = 0;
+                               if (cs == 1)
+                                       {
+                                       color_profile_from_image = COLOR_PROFILE_SRGB;
+                                       DEBUG_1("Found EXIF 2.2 ColorSpace of sRGB");
+                                       }
+                               else if (cs == 2)
+                                       {
+                                       /* non-standard way of specifying AdobeRGB (used by some software) */
+                                       color_profile_from_image = COLOR_PROFILE_ADOBERGB;
+                                       DEBUG_1("Found EXIF 2.2 ColorSpace of AdobeRGB");
+                                       }
+                               }
+                       }
+
+               if(color_profile_from_image != COLOR_PROFILE_NONE)
+                       {
+                               // transform image, we always use sRGB as target for thumbnails
+                               screen_type = COLOR_PROFILE_SRGB;
+
+                               if (profile)
+                                       {
+                                       cm = color_man_new_embedded(NULL, pixbuf,
+                                                                       profile, profile_len,
+                                                                       screen_type, NULL, NULL, 0);
+                                       g_free(profile);
+                                       }
+                               else
+                                       {
+                                       cm = color_man_new(NULL, pixbuf,
+                                                       input_type, input_file,
+                                                       screen_type, NULL, NULL, 0);
+                                       }
+
+                               if(cm) {
+                                       color_man_correct_region(cm, cm->pixbuf, 0, 0, sw, sh);
+                                       g_free(cm);
+                               }
+
+                       }
+               exif_free_fd(fd, exif);
+               }
+}
+
 static GdkPixbuf *thumb_loader_std_finish(ThumbLoaderStd *tl, GdkPixbuf *pixbuf, gboolean shrunk)
 {
        GdkPixbuf *pixbuf_thumb = NULL;
@@ -398,7 +496,14 @@ static GdkPixbuf *thumb_loader_std_finish(ThumbLoaderStd *tl, GdkPixbuf *pixbuf,
                {
                if (!tl->fd->exif_orientation)
                        {
-                       tl->fd->exif_orientation = metadata_read_int(tl->fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                       if (g_strcmp0(tl->fd->format_name, "heif") != 0)
+                               {
+                               tl->fd->exif_orientation = metadata_read_int(tl->fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                               }
+                       else
+                               {
+                               tl->fd->exif_orientation = EXIF_ORIENTATION_TOP_LEFT;
+                               }
                        }
 
                if (tl->fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT)
@@ -499,6 +604,9 @@ static GdkPixbuf *thumb_loader_std_finish(ThumbLoaderStd *tl, GdkPixbuf *pixbuf,
                        }
                }
 
+       // apply color correction, if required
+       thumb_loader_std_calibrate_pixbuf(tl->fd, result);
+
        if (pixbuf_thumb) g_object_unref(pixbuf_thumb);
        if (rotated) g_object_unref(rotated);
 
@@ -1083,8 +1191,8 @@ static gboolean thumb_std_maint_move_idle(gpointer data)
  *
  * The thumbnails are processed when the app is idle. If the app
  * exits early well too bad - they can simply be regenerated from scratch.
- *
- * This does not manage local thumbnails (fixme ?)
+ */
+/** @FIXME This does not manage local thumbnails (fixme ?)
  */
 void thumb_std_maint_moved(const gchar *source, const gchar *dest)
 {