[gthumb] Use exiv2 to extract thumbnails



commit 7cf9e991ae0273173c8e265da71a5276b0bbe0b4
Author: Michael J. Chudobiak <mjc avtechpulse com>
Date:   Fri Jun 26 12:32:16 2009 -0400

    Use exiv2 to extract thumbnails

 libgthumb/file-utils.c        |   58 +++++++++++++++++++++++++++++++++++++++++
 libgthumb/file-utils.h        |    4 ++-
 libgthumb/gth-exiv2-utils.cpp |   24 +++++++++++++++++
 libgthumb/gth-exiv2-utils.hpp |    4 +++
 src/dlg-photo-importer.c      |   35 +++++++++++++++----------
 5 files changed, 110 insertions(+), 15 deletions(-)
---
diff --git a/add-include-prefix b/add-include-prefix
old mode 100755
new mode 100644
diff --git a/autogen.sh b/autogen.sh
old mode 100755
new mode 100644
diff --git a/libgthumb/file-utils.c b/libgthumb/file-utils.c
index 7112a27..0a085b3 100644
--- a/libgthumb/file-utils.c
+++ b/libgthumb/file-utils.c
@@ -2174,6 +2174,59 @@ free_cache (void)
 }
 
 
+const char * get_embedded_thumb (const char  *local_path, const char  *tmp_thumb);
+
+GdkPixbuf*
+gth_extract_embedded_thumbnail (GFile *gfile, int size)
+{
+	GdkPixbuf *pixbuf = NULL;
+	char *local_path = g_file_get_path (gfile);
+
+	if (local_path) {
+		char *tmp_dir = get_temp_dir_name ();
+		char *filename = g_strconcat (tmp_dir, "/thumb", NULL);
+
+		const char *ext = get_embedded_thumb (local_path, filename);
+
+		if (ext && ext[0] != 0) {
+			char *full_filename = g_strconcat (filename, ext, NULL);
+			if (path_is_file (full_filename)) {
+				if (size > 0)
+					pixbuf = gdk_pixbuf_new_from_file_at_scale (full_filename, size, size, TRUE, NULL);
+				else
+					pixbuf = gdk_pixbuf_new_from_file (full_filename, NULL);
+			}
+		dir_remove_recursive (tmp_dir);
+		}
+
+		/* size sanity check */
+		if (pixbuf) {
+			int real_w = 0;
+			int real_h = 0;
+			int w, h;
+
+			w = gdk_pixbuf_get_width (pixbuf);
+			h = gdk_pixbuf_get_height (pixbuf);
+
+			gdk_pixbuf_get_file_info (local_path, &real_w, &real_h);
+
+			if ((w>0) && (h>0) && (real_w>0) && (real_h>0)) {
+				if (((real_w > real_h) && (h > w)) ||
+				    ((real_w < real_h) && (w > h))) {
+					/* reject thumbnails where the orientation is 
+					   obviously wrong */
+					g_object_unref (pixbuf);
+					pixbuf = NULL;
+				}
+			}
+		}
+	}
+
+	g_free (local_path);
+	return pixbuf;
+}
+
+
 static GdkPixbuf*
 get_pixbuf_using_external_converter (FileData   *file,
 				     int         requested_width,
@@ -2391,6 +2444,11 @@ gth_pixbuf_new_from_file (FileData               *file,
 		return NULL;
 	}
 
+	/* use exiv2 to extract embedded thumbnails, if possible */
+	if ((pixbuf == NULL)
+	    && (requested_width > 0))
+		pixbuf = gth_extract_embedded_thumbnail (file->gfile, requested_width);
+
 #ifdef HAVE_LIBOPENRAW
 	/* Raw thumbnails - using libopenraw is much faster than using dcraw for
 	   thumbnails. Use libopenraw for full raw images too, once it matures. */
diff --git a/libgthumb/file-utils.h b/libgthumb/file-utils.h
index d5cc44a..89c642d 100644
--- a/libgthumb/file-utils.h
+++ b/libgthumb/file-utils.h
@@ -218,8 +218,10 @@ gboolean	    is_local_file                 (const char       *filename);
 void                free_cache                    (void);
 GHashTable *        read_dot_hidden_file          (const char       *uri);
 
-/* Pixbuf + VFS */
+/* Pixbuf */
 
+GdkPixbuf*          gth_extract_embedded_thumbnail     (GFile                  *gfile,
+							int                     size);
 GdkPixbuf*	    gth_pixbuf_new_from_file	       (FileData               *file,
 			  				GError                **error,
 			  				int                     requested_width,
diff --git a/libgthumb/gth-exiv2-utils.cpp b/libgthumb/gth-exiv2-utils.cpp
index a0909ce..03b4e5e 100644
--- a/libgthumb/gth-exiv2-utils.cpp
+++ b/libgthumb/gth-exiv2-utils.cpp
@@ -573,6 +573,30 @@ mandatory_string (Exiv2::ExifData &checkdata,
                 checkdata[tag] = value;
 }
 
+
+extern "C"
+const char *
+get_embedded_thumb (const char *local_file, const char *tmp_thumb)
+{
+	try {
+                Exiv2::Image::AutoPtr image1 = Exiv2::ImageFactory::open (local_file);
+                g_assert (image1.get() != 0);
+
+		image1->readMetadata();
+		Exiv2::ExifData &ed = image1->exifData();
+		Exiv2::ExifThumbC et(ed);
+
+		et.writeFile(tmp_thumb);
+		return et.extension();
+	}
+        catch (const Exiv2::AnyError& error) {
+                std::cerr << error << "\n";
+		return NULL;
+        }
+
+}
+
+
 extern "C"
 void
 write_metadata (const char *from_file,
diff --git a/libgthumb/gth-exiv2-utils.hpp b/libgthumb/gth-exiv2-utils.hpp
index 6dd9374..9d961db 100644
--- a/libgthumb/gth-exiv2-utils.hpp
+++ b/libgthumb/gth-exiv2-utils.hpp
@@ -33,6 +33,10 @@ extern "C" GList *
 read_exiv2_sidecar	(const char  *uri,
 			 GList       *metadata);
 
+extern "C" const char *
+get_embedded_thumb      (const char  *local_file,
+			 const char  *tmp_thumb);
+
 extern "C" void
 write_metadata 		(const char  *from_file,
 			 const char  *to_file,
diff --git a/src/dlg-photo-importer.c b/src/dlg-photo-importer.c
index c40c3bc..7c0245c 100644
--- a/src/dlg-photo-importer.c
+++ b/src/dlg-photo-importer.c
@@ -50,6 +50,7 @@
 #include "rotation-utils.h"
 #include "main.h"
 
+
 #define GNOME_DESKTOP_USE_UNSTABLE_API
 #include <libgnomeui/gnome-desktop-thumbnail.h>
 
@@ -779,7 +780,6 @@ gfile_get_preview (DialogData *data,
         GIcon        *gicon;
         GtkIconTheme *theme;
 	GFileInfo    *info;
-	char         *uri;
 	const char   *mime_type;
 
 	mime_type = gfile_get_mime_type (gfile, FALSE);
@@ -795,11 +795,18 @@ gfile_get_preview (DialogData *data,
                 return NULL;
 
 	if (data->generate_previews && is_relevant_mime_type (gfile, TRUE, FALSE)) {
-		uri = g_file_get_uri (gfile);
+
+		pixbuf = gth_extract_embedded_thumbnail (gfile, size);
+		if (pixbuf) {
+			gfile_debug (DEBUG_INFO, "using embedded thumbnail for", gfile);
+			return pixbuf;
+		} 
+
+		char *uri = g_file_get_uri (gfile);
 		pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (data->factory, uri, mime_type);
 		g_free (uri);
-
 		if (pixbuf) {
+			gfile_debug (DEBUG_INFO, "using generated thumbnail for", gfile);
 			int w = gdk_pixbuf_get_width (pixbuf);
 			int h = gdk_pixbuf_get_height (pixbuf);
 			if (scale_keeping_ratio (&w, &h, size, size, FALSE)) {
@@ -807,20 +814,20 @@ gfile_get_preview (DialogData *data,
 				pixbuf = gdk_pixbuf_scale_simple (tmp, w, h, GDK_INTERP_BILINEAR);
 				g_object_unref (tmp);
 			}
+			return pixbuf;
 		}
 
-		if (pixbuf) {
-			gfile_debug (DEBUG_INFO, "using thumbnail for", gfile);
-		} else {
-			char *local_path = g_file_get_path (gfile);
+		char *local_path = g_file_get_path (gfile);
+		if (local_path)
 			pixbuf = gdk_pixbuf_new_from_file_at_scale (local_path, size, size, TRUE, NULL);
-			g_free (local_path);
-			if (pixbuf) {
-				gfile_debug (DEBUG_INFO, "using gdk pixbuf loader for", gfile);
-				GdkPixbuf *tmp = pixbuf;
-				pixbuf = gdk_pixbuf_apply_embedded_orientation (tmp);
-				g_object_unref (tmp);
-			}
+		g_free (local_path);
+
+		if (pixbuf) {
+			gfile_debug (DEBUG_INFO, "using gdk pixbuf loader for", gfile);
+			GdkPixbuf *tmp = pixbuf;
+			pixbuf = gdk_pixbuf_apply_embedded_orientation (tmp);
+			g_object_unref (tmp);
+			return pixbuf;
 		}
 	}
 



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