[gthumb] image loading optiomization



commit fd8d8b3a07a168e50560d4a336046adceab0e1a0
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon Sep 13 00:34:27 2010 +0200

    image loading optiomization
    
    do use gdk_pixbuf_get_file_info to read the file size, use
    the pixbuf loader directly.

 gthumb/pixbuf-io.c |  221 +++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 183 insertions(+), 38 deletions(-)
---
diff --git a/gthumb/pixbuf-io.c b/gthumb/pixbuf-io.c
index b65a0c0..7f94f5f 100644
--- a/gthumb/pixbuf-io.c
+++ b/gthumb/pixbuf-io.c
@@ -220,6 +220,101 @@ _gdk_pixbuf_save_async (GdkPixbuf        *pixbuf,
 }
 
 
+#define LOAD_BUFFER_SIZE (64*1024)
+
+
+typedef struct {
+	int requested_size;
+	int original_width;
+	int original_height;
+	int loader_width;
+	int loader_height;
+} ScaleData;
+
+
+static GdkPixbuf *
+load_from_stream (GdkPixbufLoader  *loader,
+                  GInputStream     *stream,
+                  GCancellable     *cancellable,
+                  GError          **error)
+{
+        GdkPixbuf *pixbuf;
+        gssize n_read;
+        guchar buffer[LOAD_BUFFER_SIZE];
+        gboolean res;
+
+        res = TRUE;
+        while (1) {
+                n_read = g_input_stream_read (stream,
+                                              buffer,
+                                              sizeof (buffer),
+                                              cancellable,
+                                              error);
+
+                if (n_read < 0) {
+                        res = FALSE;
+                        error = NULL; /* Ignore further errors */
+                        break;
+                }
+
+                if (n_read == 0)
+                        break;
+
+                if (!gdk_pixbuf_loader_write (loader,
+                                              buffer,
+                                              n_read,
+                                              error)) {
+                        res = FALSE;
+                        error = NULL;
+                        break;
+                }
+        }
+
+        if (!gdk_pixbuf_loader_close (loader, error)) {
+                res = FALSE;
+                error = NULL;
+        }
+
+        pixbuf = NULL;
+        if (res) {
+                pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+                if (pixbuf)
+                        g_object_ref (pixbuf);
+        }
+
+        return pixbuf;
+}
+
+
+static void
+pixbuf_loader_size_prepared_cb (GdkPixbufLoader *loader,
+				int              width,
+				int              height,
+				gpointer         user_data)
+{
+	ScaleData *scale_data = user_data;
+
+	scale_data->original_width = width;
+	scale_data->original_height = height;
+	scale_data->loader_width = width;
+	scale_data->loader_height = height;
+
+	if (scale_data->requested_size == -1)
+		return;
+
+	if (scale_keeping_ratio (&scale_data->loader_width,
+				 &scale_data->loader_height,
+				 scale_data->requested_size,
+				 scale_data->requested_size,
+				 FALSE))
+	{
+		gdk_pixbuf_loader_set_size (loader,
+					    scale_data->loader_width,
+					    scale_data->loader_height);
+	}
+}
+
+
 GdkPixbuf *
 gth_pixbuf_new_from_file (GthFileData   *file_data,
 			  int            requested_size,
@@ -229,11 +324,12 @@ gth_pixbuf_new_from_file (GthFileData   *file_data,
 			  GCancellable  *cancellable,
 			  GError       **error)
 {
-	GdkPixbuf    *pixbuf = NULL;
-	gboolean      scale_pixbuf;
-	int           original_w;
-	int           original_h;
-	GInputStream *stream;
+#if 0
+	GdkPixbuf *pixbuf = NULL;
+	char      *path;
+	gboolean   scale_pixbuf;
+	int        original_w;
+	int        original_h;
 
 	if (original_width != NULL)
 		*original_width = -1;
@@ -244,65 +340,113 @@ gth_pixbuf_new_from_file (GthFileData   *file_data,
 	if (file_data == NULL)
 		return NULL;
 
+	path = g_file_get_path (file_data->file);
+
 	scale_pixbuf = FALSE;
 	original_w = -1;
 	original_h = -1;
 
 	if (requested_size > 0) {
-		char *path;
-
-		path = g_file_get_path (file_data->file);
-		if (path != NULL) {
-			if (gdk_pixbuf_get_file_info (path, &original_w, &original_h) == NULL) {
-				original_w = -1;
-				original_h = -1;
-			}
-			if ((original_w > requested_size) || (original_h > requested_size))
-				scale_pixbuf = TRUE;
+		if (gdk_pixbuf_get_file_info (path, &original_w, &original_h) == NULL) {
+			original_w = -1;
+			original_h = -1;
 		}
+		if ((original_w > requested_size) || (original_h > requested_size))
+			scale_pixbuf = TRUE;
+	}
 
-		g_free (path);
+	if (scale_pixbuf)
+		pixbuf = gdk_pixbuf_new_from_file_at_scale (path,
+							    requested_size,
+							    requested_size,
+							    TRUE,
+							    error);
+	else
+		pixbuf = gdk_pixbuf_new_from_file (path, error);
+
+	if (pixbuf != NULL) {
+		GdkPixbuf *rotated;
+
+		rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf);
+		if (rotated != NULL) {
+			g_object_unref (pixbuf);
+			pixbuf = rotated;
+		}
 	}
 
+	if (original_width != NULL)
+		*original_width = original_w;
+	if (original_height != NULL)
+		*original_height = original_h;
+
+	g_free (path);
+
+	return pixbuf;
+#endif
+
+	GdkPixbuf       *pixbuf = NULL;
+	ScaleData        scale_data;
+	GInputStream    *stream;
+	GdkPixbufLoader *pixbuf_loader;
+
+	if (original_width != NULL)
+		*original_width = -1;
+	if (original_height != NULL)
+		*original_height = -1;
+
+	if (file_data == NULL)
+		return NULL;
+
 	stream = (GInputStream *) g_file_read (file_data->file, cancellable, error);
 	if (stream == NULL)
 		return NULL;
 
-	if (scale_pixbuf) {
-		pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream,
-							      requested_size,
-							      requested_size,
-							      TRUE,
-							      cancellable,
-							      error);
-		if ((pixbuf != NULL) && scale_to_original) {
-			GdkPixbuf *tmp;
-
-			tmp = _gdk_pixbuf_scale_simple_safe (pixbuf, original_w, original_h, GDK_INTERP_NEAREST);
-			g_object_unref (pixbuf);
-			pixbuf = tmp;
-		}
+	scale_data.requested_size = requested_size;
+	scale_data.original_width = -1;
+	scale_data.original_height = -1;
+	scale_data.loader_width = -1;
+	scale_data.loader_height = -1;
+
+	pixbuf_loader = gdk_pixbuf_loader_new ();
+	g_signal_connect (pixbuf_loader,
+			  "size-prepared",
+			  G_CALLBACK (pixbuf_loader_size_prepared_cb),
+			  &scale_data);
+
+	pixbuf = load_from_stream (pixbuf_loader, stream, cancellable, error);
+
+	g_object_unref (pixbuf_loader);
+	g_object_unref (stream);
+
+	if ((pixbuf != NULL) && scale_to_original) {
+		GdkPixbuf *tmp;
+
+		tmp = gdk_pixbuf_scale_simple (pixbuf, scale_data.original_width, scale_data.original_height, GDK_INTERP_NEAREST);
+		g_object_unref (pixbuf);
+		pixbuf = tmp;
 	}
-	else
-		pixbuf = gdk_pixbuf_new_from_stream (stream, cancellable, error);
 
 	if (pixbuf != NULL) {
 		GdkPixbuf *rotated;
 
 		rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf);
 		if (rotated != NULL) {
+			if (rotated != pixbuf) {
+				int tmp;
+
+				tmp = scale_data.original_width;
+				scale_data.original_width = scale_data.original_height;
+				scale_data.original_height = tmp;
+			}
 			g_object_unref (pixbuf);
 			pixbuf = rotated;
 		}
 	}
 
 	if (original_width != NULL)
-		*original_width = original_w;
-
+		*original_width = scale_data.original_width;
 	if (original_height != NULL)
-		*original_height = original_h;
-
-	g_object_unref (stream);
+		*original_height = scale_data.original_height;
 
 	return pixbuf;
 }
@@ -328,7 +472,8 @@ gth_pixbuf_animation_new_from_file (GthFileData   *file_data,
 		char *path;
 
 		path = g_file_get_path (file_data->file);
-		animation = gdk_pixbuf_animation_new_from_file (path, error);
+		if (path != NULL)
+			animation = gdk_pixbuf_animation_new_from_file (path, error);
 
 		g_free (path);
 



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