added option to use exif thumbnails
authorVladimir Nadvornik <nadvornik@suse.cz>
Sat, 11 Oct 2008 20:19:48 +0000 (20:19 +0000)
committerVladimir Nadvornik <nadvornik@suse.cz>
Sat, 11 Oct 2008 20:19:48 +0000 (20:19 +0000)
- it requires exiv2 0.18 or the current svn
- it is disabled by default because the exif thumbnails
  may be outdated if the image was edited

src/exif.c
src/exif.h
src/exiv2.cc
src/image-load.c
src/options.c
src/options.h
src/preferences.c
src/rcfile.c
src/thumb.c

index f54c996..7a7e3d3 100644 (file)
@@ -1605,7 +1605,7 @@ struct _UnmapData
 
 static GList *exif_unmap_list = 0;
 
-guchar *exif_get_preview(ExifData *exif, guint *data_len)
+guchar *exif_get_preview(ExifData *exif, guint *data_len, gint requested_width, gint requested_height)
 {
        int success;
        guint offset;
index 6fc98c6..114658f 100644 (file)
@@ -158,7 +158,7 @@ gint exif_jpeg_segment_find(guchar *data, guint size,
 gint exif_jpeg_parse_color(ExifData *exif, guchar *data, guint size);
 
 /*raw support */
-guchar *exif_get_preview(ExifData *exif, guint *data_len);
+guchar *exif_get_preview(ExifData *exif, guint *data_len, gint requested_width, gint requested_height);
 void exif_free_preview(guchar *buf);
 
 
index 145be41..f9ba214 100644 (file)
@@ -608,13 +608,15 @@ guchar *exif_get_color_profile(ExifData *exif, guint *data_len)
 
 #if EXIV2_TEST_VERSION(0,17,90)
 
-guchar *exif_get_preview(ExifData *exif, guint *data_len)
+guchar *exif_get_preview(ExifData *exif, guint *data_len, gint requested_width, gint requested_height)
 {
        if (!exif) return NULL;
 
        const char* path = exif->image->io().path().c_str();
        /* given image pathname, first do simple (and fast) file extension test */
-       if (!filter_file_class(path, FORMAT_CLASS_RAWIMAGE)) return NULL;
+       gboolean is_raw = filter_file_class(path, FORMAT_CLASS_RAWIMAGE);
+       
+       if (!is_raw && requested_width == 0) return NULL;
 
        try {
 
@@ -624,7 +626,29 @@ guchar *exif_get_preview(ExifData *exif, guint *data_len)
 
                if (!list.empty())
                        {
-                       Exiv2::PreviewPropertiesList::iterator pos = --list.end();
+                       Exiv2::PreviewPropertiesList::iterator pos;
+                       Exiv2::PreviewPropertiesList::iterator last = --list.end();
+                       
+                       if (requested_width == 0)
+                               {
+                               pos = last; // the largest
+                               }
+                       else
+                               {
+                               pos = list.begin();
+                               while (pos != last)
+                                       {
+                                       if (pos->width_ >= (uint32_t)requested_width &&
+                                           pos->height_ >= (uint32_t)requested_height) break;
+                                       ++pos;
+                                       }
+                               
+                               // we are not interested in smaller thumbnails in normal image formats - we can use full image instead
+                               if (!is_raw) 
+                                       {
+                                       if (pos->width_ < (uint32_t)requested_width || pos->height_ < (uint32_t)requested_height) return NULL; 
+                                       }
+                               }
 
                        Exiv2::PreviewImage image = loader.getPreviewImage(*pos);
 
@@ -683,7 +707,7 @@ struct _UnmapData
 
 static GList *exif_unmap_list = 0;
 
-extern "C" guchar *exif_get_preview(ExifData *exif, guint *data_len)
+extern "C" guchar *exif_get_preview(ExifData *exif, guint *data_len, gint requested_width, gint requested_height)
 {
        unsigned long offset;
 
index 3790427..2cc9350 100644 (file)
@@ -607,12 +607,15 @@ static gint image_loader_setup_source(ImageLoader *il)
                {
                ExifData *exif = exif_read_fd(il->fd);
 
-               il->mapped_file = exif_get_preview(exif, &il->bytes_total);
-               
+               if (options->thumbnails.use_exif)
+                       il->mapped_file = exif_get_preview(exif, &il->bytes_total, il->requested_width, il->requested_height);
+               else
+                       il->mapped_file = exif_get_preview(exif, &il->bytes_total, 0, 0); /* get the largest available preview image or NULL for normal images*/
+
                if (il->mapped_file)
                        {
                        il->preview = TRUE;
-                       DEBUG_1("Raw file %s contains embedded image", il->fd->path);
+                       DEBUG_1("Usable reduced size (preview) image loaded from file %s", il->fd->path);
                        }
                exif_free_fd(il->fd, exif);
                }
index 5cdc985..b5a7fc3 100644 (file)
@@ -158,6 +158,7 @@ ConfOptions *init_options(ConfOptions *options)
        options->thumbnails.quality = GDK_INTERP_TILES;
        options->thumbnails.spec_standard = TRUE;
        options->thumbnails.use_xvpics = TRUE;
+       options->thumbnails.use_exif = FALSE;
 
        options->tree_descend_subdirs = FALSE;
        options->update_on_time_change = TRUE;
index 26f551f..bfe372b 100644 (file)
@@ -94,6 +94,7 @@ struct _ConfOptions
                gboolean use_xvpics;
                gboolean spec_standard;
                guint quality;
+               gboolean use_exif;
        } thumbnails;
 
        /* file filtering */
index aad2ac7..c85339b 100644 (file)
@@ -255,6 +255,7 @@ static void config_window_apply(void)
        options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
        options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
        options->thumbnails.fast = c_options->thumbnails.fast;
+       options->thumbnails.use_exif = c_options->thumbnails.use_exif;
 #if 0
        options->thumbnails.use_xvpics = c_options->thumbnails.use_xvpics;
 #endif
@@ -978,6 +979,9 @@ static void config_tab_general(GtkWidget *notebook)
        pref_checkbox_new_int(group, _("Faster jpeg thumbnailing (may reduce quality)"),
                              options->thumbnails.fast, &c_options->thumbnails.fast);
 
+       pref_checkbox_new_int(group, _("Use EXIF thumbnails when available"),
+                             options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
+
        group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
 
        c_options->slideshow.delay = options->slideshow.delay;
index b13e5ea..b26f758 100644 (file)
@@ -403,6 +403,7 @@ gboolean save_options_to(const gchar *utf8_path, ConfOptions *options)
        WRITE_BOOL(thumbnails.use_xvpics);
        WRITE_BOOL(thumbnails.spec_standard);
        WRITE_UINT(thumbnails.quality);
+       WRITE_BOOL(thumbnails.use_exif);
 
 
        WRITE_SUBTITLE("File sorting Options");
@@ -776,6 +777,7 @@ gboolean load_options_from(const gchar *utf8_path, ConfOptions *options)
                READ_BOOL(thumbnails.use_xvpics);
                READ_BOOL(thumbnails.spec_standard);
                READ_UINT_CLAMP(thumbnails.quality, GDK_INTERP_NEAREST, GDK_INTERP_HYPER);
+               READ_BOOL(thumbnails.use_exif);
 
                /* file sorting options */
                READ_UINT(file_sort.method);
index 3a7580e..5a2f33f 100644 (file)
@@ -471,7 +471,11 @@ ThumbLoader *thumb_loader_new(gint width, gint height)
 {
        ThumbLoader *tl;
 
-       if (options->thumbnails.spec_standard)
+       /* non-std thumb loader is more effective for configurations with disabled caching
+          because it loads the thumbnails at the required size. loader_std loads
+          the thumbnails at the sizes appropriate for standard cache (typically 256x256 pixels)
+          and then performs one additional scaling */
+       if (options->thumbnails.spec_standard && options->thumbnails.enable_caching)
                {
                return (ThumbLoader *)thumb_loader_std_new(width, height);
                }