[gthumb: 27/40] check the thumbnail validity without loading the pixbuf
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb: 27/40] check the thumbnail validity without loading the pixbuf
- Date: Fri, 10 Sep 2010 16:58:28 +0000 (UTC)
commit dc71ddb3cb4e0d325d980f7f7c256c6ce8d1272e
Author: Paolo Bacchilega <paobac src gnome org>
Date: Thu Sep 9 16:14:26 2010 +0200
check the thumbnail validity without loading the pixbuf
configure.ac | 1 +
gthumb/gnome-desktop-thumbnail.c | 261 ++++++++++++++++++++++++--------------
gthumb/gnome-desktop-thumbnail.h | 2 +-
gthumb/gth-thumb-loader.c | 75 +++++++++--
gthumb/gth-thumb-loader.h | 4 +
5 files changed, 236 insertions(+), 107 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 609ad1c..a5a1b1f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -135,6 +135,7 @@ PKG_CHECK_MODULES(GTHUMB, [
gtk+-2.0 >= $GTK_REQUIRED
gconf-2.0 >= $GCONF_REQUIRED
unique-1.0 >= $UNIQUE_REQUIRED
+ libpng
])
AC_SUBST(GTHUMB_LIBS)
AC_SUBST(GTHUMB_CFLAGS)
diff --git a/gthumb/gnome-desktop-thumbnail.c b/gthumb/gnome-desktop-thumbnail.c
index 83ab309..50d2e18 100644
--- a/gthumb/gnome-desktop-thumbnail.c
+++ b/gthumb/gnome-desktop-thumbnail.c
@@ -55,6 +55,7 @@
#include <string.h>
#include <glib.h>
#include <stdio.h>
+#include <png.h>
#define GDK_PIXBUF_ENABLE_BACKEND
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gconf/gconf.h>
@@ -524,50 +525,38 @@ gnome_desktop_thumbnail_factory_new (GnomeDesktopThumbnailSize size)
**/
char *
gnome_desktop_thumbnail_factory_lookup (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- time_t mtime)
+ const char *uri,
+ time_t mtime)
{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
- char *path, *file;
- GChecksum *checksum;
- guint8 digest[16];
- gsize digest_len = sizeof (digest);
- GdkPixbuf *pixbuf;
- gboolean res;
-
- g_return_val_if_fail (uri != NULL, NULL);
-
- res = FALSE;
-
- checksum = g_checksum_new (G_CHECKSUM_MD5);
- g_checksum_update (checksum, (const guchar *) uri, strlen (uri));
+ GChecksum *checksum;
+ guint8 digest[16];
+ gsize digest_len = sizeof (digest);
+ char *file;
+ char *path;
- g_checksum_get_digest (checksum, digest, &digest_len);
- g_assert (digest_len == 16);
+ g_return_val_if_fail (uri != NULL, NULL);
- file = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
+ checksum = g_checksum_new (G_CHECKSUM_MD5);
+ g_checksum_update (checksum, (const guchar *) uri, strlen (uri));
+ g_checksum_get_digest (checksum, digest, &digest_len);
+ g_assert (digest_len == 16);
- path = g_build_filename (g_get_home_dir (),
- ".thumbnails",
- (priv->size == GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL)?"normal":"large",
- file,
- NULL);
- g_free (file);
-
- pixbuf = gdk_pixbuf_new_from_file (path, NULL);
- if (pixbuf != NULL)
- {
- res = gnome_desktop_thumbnail_is_valid (pixbuf, uri, mtime);
- g_object_unref (pixbuf);
- }
+ file = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
+ path = g_build_filename (g_get_home_dir (),
+ ".thumbnails",
+ (factory->priv->size == GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL)?"normal":"large",
+ file,
+ NULL);
- g_checksum_free (checksum);
+ if (! gnome_desktop_thumbnail_is_valid (path, uri, mtime)) {
+ g_free (path);
+ path = NULL;
+ }
- if (res)
- return path;
+ g_free (file);
+ g_checksum_free (checksum);
- g_free (path);
- return FALSE;
+ return path;
}
/**
@@ -588,45 +577,34 @@ gnome_desktop_thumbnail_factory_lookup (GnomeDesktopThumbnailFactory *factory,
**/
gboolean
gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- time_t mtime)
+ const char *uri,
+ time_t mtime)
{
- char *path, *file;
- GdkPixbuf *pixbuf;
- gboolean res;
- GChecksum *checksum;
- guint8 digest[16];
- gsize digest_len = sizeof (digest);
-
- checksum = g_checksum_new (G_CHECKSUM_MD5);
- g_checksum_update (checksum, (const guchar *) uri, strlen (uri));
-
- g_checksum_get_digest (checksum, digest, &digest_len);
- g_assert (digest_len == 16);
-
- res = FALSE;
-
- file = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
-
- path = g_build_filename (g_get_home_dir (),
- ".thumbnails/fail",
- appname,
- file,
- NULL);
- g_free (file);
-
- pixbuf = gdk_pixbuf_new_from_file (path, NULL);
- g_free (path);
-
- if (pixbuf)
- {
- res = gnome_desktop_thumbnail_is_valid (pixbuf, uri, mtime);
- g_object_unref (pixbuf);
- }
+ GChecksum *checksum;
+ guint8 digest[16];
+ gsize digest_len = sizeof (digest);
+ char *path;
+ char *file;
+ gboolean res;
+
+ checksum = g_checksum_new (G_CHECKSUM_MD5);
+ g_checksum_update (checksum, (const guchar *) uri, strlen (uri));
+ g_checksum_get_digest (checksum, digest, &digest_len);
+ g_assert (digest_len == 16);
+
+ file = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
+ path = g_build_filename (g_get_home_dir (),
+ ".thumbnails/fail",
+ appname,
+ file,
+ NULL);
+ res = gnome_desktop_thumbnail_is_valid (path, uri, mtime);
- g_checksum_free (checksum);
+ g_free (path);
+ g_free (file);
+ g_checksum_free (checksum);
- return res;
+ return res;
}
static char *
@@ -1200,9 +1178,104 @@ gnome_desktop_thumbnail_path_for_uri (const char *uri,
}
+/* This function taken from gdk-pixbuf:
+ *
+ * Copyright (C) 1999 Mark Crichton
+ * Copyright (C) 1999 The Free Software Foundation
+ *
+ * Authors: Mark Crichton <crichton gimp org>
+ * Federico Mena-Quintero <federico gimp org>
+ *
+ * Released under the LGPL version 2 of the License,
+ * or (at your option) any later version.
+ *
+ **/
+static gboolean
+png_text_to_pixbuf_option (png_text text_ptr,
+ gchar **key,
+ gchar **value)
+{
+ gboolean is_ascii = TRUE;
+ int i;
+
+ /* Avoid loading iconv if the text is plain ASCII */
+ for (i = 0; i < text_ptr.text_length; i++)
+ if (text_ptr.text[i] & 0x80) {
+ is_ascii = FALSE;
+ break;
+ }
+
+ if (is_ascii) {
+ *value = g_strdup (text_ptr.text);
+ } else {
+ *value = g_convert (text_ptr.text, -1,
+ "UTF-8", "ISO-8859-1",
+ NULL, NULL, NULL);
+ }
+
+ if (*value) {
+ *key = g_strconcat ("tEXt::", text_ptr.key, NULL);
+ return TRUE;
+ } else {
+ g_warning ("Couldn't convert text chunk value to UTF-8.");
+ *key = NULL;
+ return FALSE;
+ }
+}
+
+
+static GHashTable *
+read_png_options (const char *thumbnail_filename)
+{
+ GHashTable *options;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ FILE *f;
+ png_textp text_ptr;
+ int num_texts;
+
+ options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (png_ptr == NULL)
+ return options;
+
+ info_ptr = png_create_info_struct (png_ptr);
+ if (info_ptr == NULL) {
+ png_destroy_read_struct (&png_ptr, NULL, NULL);
+ return options;
+ }
+
+ f = fopen (thumbnail_filename, "r");
+ if (f == NULL) {
+ png_destroy_read_struct (&png_ptr, NULL, NULL);
+ return options;
+ }
+
+ png_init_io (png_ptr, f);
+ png_read_info (png_ptr, info_ptr);
+
+ if (png_get_text (png_ptr, info_ptr, &text_ptr, &num_texts)) {
+ int i;
+ for (i = 0; i < num_texts; i++) {
+ char *key;
+ char *value;
+
+ if (png_text_to_pixbuf_option (text_ptr[i], &key, &value))
+ g_hash_table_insert (options, key, value);
+ }
+ }
+
+ png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+ fclose (f);
+
+ return options;
+}
+
+
/**
* gnome_desktop_thumbnail_is_valid:
- * @pixbuf: an loaded thumbnail #GdkPixbuf
+ * @thumbnail_filename: the png file that contains the thumbnail
* @uri: a uri
* @mtime: the mtime
*
@@ -1214,25 +1287,25 @@ gnome_desktop_thumbnail_path_for_uri (const char *uri,
* Since: 2.2
**/
gboolean
-gnome_desktop_thumbnail_is_valid (GdkPixbuf *pixbuf,
- const char *uri,
- time_t mtime)
+gnome_desktop_thumbnail_is_valid (const char *thumbnail_filename,
+ const char *uri,
+ time_t mtime)
{
- const char *thumb_uri, *thumb_mtime_str;
- time_t thumb_mtime;
-
- thumb_uri = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::URI");
- if (!thumb_uri)
- return FALSE;
- if (strcmp (uri, thumb_uri) != 0)
- return FALSE;
-
- thumb_mtime_str = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::MTime");
- if (!thumb_mtime_str)
- return FALSE;
- thumb_mtime = atol (thumb_mtime_str);
- if (mtime != thumb_mtime)
- return FALSE;
-
- return TRUE;
+ gboolean is_valid = FALSE;
+ GHashTable *png_options;
+ const char *thumb_uri;
+
+ png_options = read_png_options (thumbnail_filename);
+ thumb_uri = g_hash_table_lookup (png_options, "tEXt::Thumb::URI");
+ if (g_strcmp0 (uri, thumb_uri) == 0) {
+ const char *thumb_mtime_str;
+
+ thumb_mtime_str = g_hash_table_lookup (png_options, "tEXt::Thumb::MTime");
+ if ((thumb_mtime_str != NULL) && (mtime == atol (thumb_mtime_str)))
+ is_valid = TRUE;
+ }
+
+ g_hash_table_unref (png_options);
+
+ return is_valid;
}
diff --git a/gthumb/gnome-desktop-thumbnail.h b/gthumb/gnome-desktop-thumbnail.h
index b1b096b..c86f187 100644
--- a/gthumb/gnome-desktop-thumbnail.h
+++ b/gthumb/gnome-desktop-thumbnail.h
@@ -108,7 +108,7 @@ void gnome_desktop_thumbnail_factory_create_failed_thumbnail (
time_t mtime);
/* Thumbnailing utils: */
-gboolean gnome_desktop_thumbnail_is_valid (GdkPixbuf *pixbuf,
+gboolean gnome_desktop_thumbnail_is_valid (const char *thumbnail_filename,
const char *uri,
time_t mtime);
char * gnome_desktop_thumbnail_md5 (const char *uri);
diff --git a/gthumb/gth-thumb-loader.c b/gthumb/gth-thumb-loader.c
index 5e36e39..a9ddb8c 100644
--- a/gthumb/gth-thumb-loader.c
+++ b/gthumb/gth-thumb-loader.c
@@ -428,6 +428,8 @@ cache_image_ready_cb (GObject *source_object,
load_result->pixbuf = pixbuf;
g_simple_async_result_set_op_res_gpointer (load_data->simple, load_result, (GDestroyNotify) load_result_unref);
g_simple_async_result_complete_in_idle (load_data->simple);
+
+ load_data_unref (load_data);
}
@@ -691,8 +693,10 @@ original_image_ready_cb (GObject *source_object,
check_cancellable_cb,
load_data);
}
- else
+ else {
failed_to_load_original_image (self, load_data);
+ load_data_unref (load_data);
+ }
g_free (uri);
@@ -700,7 +704,9 @@ original_image_ready_cb (GObject *source_object,
}
original_image_loaded_correctly (self, load_data, pixbuf);
+
g_object_unref (pixbuf);
+ load_data_unref (load_data);
}
@@ -746,6 +752,21 @@ gth_thumb_loader_load (GthThumbLoader *self,
g_free (uri);
}
+ if ((cache_path == NULL)
+ && (self->priv->max_file_size > 0)
+ && (g_file_info_get_size (file_data->info) > self->priv->max_file_size))
+ {
+ GError *error;
+
+ error = g_error_new_literal (GTH_ERROR, 0, "file too big to generate the thumbnail");
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_error_free (error);
+
+ return;
+ }
+
load_data = load_data_new (file_data, self->priv->requested_size);
load_data->thumb_loader = g_object_ref (self);
load_data->cancellable = _g_object_ref (cancellable);
@@ -769,17 +790,6 @@ gth_thumb_loader_load (GthThumbLoader *self,
g_object_unref (cache_file);
g_free (cache_path);
}
- else if ((self->priv->max_file_size > 0) && (g_file_info_get_size (file_data->info) > self->priv->max_file_size)) {
- GError *error;
-
- load_data_unref (load_data);
-
- error = g_error_new_literal (GTH_ERROR, 0, "file too big to generate the thumbnail");
- g_simple_async_result_set_from_error (simple, error);
- g_simple_async_result_complete_in_idle (simple);
-
- g_error_free (error);
- }
else
gth_image_loader_load (self->priv->tloader,
file_data,
@@ -812,3 +822,44 @@ gth_thumb_loader_load_finish (GthThumbLoader *self,
return TRUE;
}
+
+
+gboolean
+gth_thumb_loader_has_valid_thumbnail (GthThumbLoader *self,
+ GthFileData *file_data)
+{
+ gboolean valid_thumbnail = FALSE;
+ char *uri;
+ time_t mtime;
+ char *thumbnail_path;
+
+ uri = g_file_get_uri (file_data->file);
+ mtime = gth_file_data_get_mtime (file_data);
+ thumbnail_path = gnome_desktop_thumbnail_factory_lookup (self->priv->thumb_factory, uri, mtime);
+ if (thumbnail_path != NULL) {
+ valid_thumbnail = TRUE;
+ g_free (thumbnail_path);
+ }
+
+ g_free (uri);
+
+ return valid_thumbnail;
+}
+
+
+gboolean
+gth_thumb_loader_has_failed_thumbnail (GthThumbLoader *self,
+ GthFileData *file_data)
+{
+ char *uri;
+ time_t mtime;
+ gboolean valid_thumbnail;
+
+ uri = g_file_get_uri (file_data->file);
+ mtime = gth_file_data_get_mtime (file_data);
+ valid_thumbnail = gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (self->priv->thumb_factory, uri, mtime);
+
+ g_free (uri);
+
+ return valid_thumbnail;
+}
diff --git a/gthumb/gth-thumb-loader.h b/gthumb/gth-thumb-loader.h
index a441130..ef40bc7 100644
--- a/gthumb/gth-thumb-loader.h
+++ b/gthumb/gth-thumb-loader.h
@@ -74,6 +74,10 @@ gboolean gth_thumb_loader_load_finish (GthThumbLoader *s
GAsyncResult *res,
GdkPixbuf **pixbuf,
GError **error);
+gboolean gth_thumb_loader_has_valid_thumbnail (GthThumbLoader *self,
+ GthFileData *file_data);
+gboolean gth_thumb_loader_has_failed_thumbnail (GthThumbLoader *self,
+ GthFileData *file_data);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]