/*
* Geeqie
* (C) 2006 John Ellis
- * Copyright (C) 2008 The Geeqie Team
+ * Copyright (C) 2008 - 2009 The Geeqie Team
*
* Author: John Ellis
*
#include "collect.h"
#include "color-man.h"
#include "exif.h"
+#include "metadata.h"
#include "histogram.h"
#include "image-load.h"
#include "image-overlay.h"
#include <math.h>
-
-/* size of the image loader buffer (512 bytes x defined number) */
-#define IMAGE_LOAD_BUFFER_COUNT 8
-
-/* define this so that more bytes are read per idle loop on larger images (> 1MB) */
-#define IMAGE_THROTTLE_LARGER_IMAGES 1
-
-/* throttle factor to increase read bytes by (2 is double, 3 is triple, etc.) */
-#define IMAGE_THROTTLE_FACTOR 32
-
-/* the file size at which throttling take place */
-#define IMAGE_THROTTLE_THRESHOLD 1048576
-
static GList *image_list = NULL;
-
static void image_update_title(ImageWindow *imd);
static void image_read_ahead_start(ImageWindow *imd);
static void image_cache_set(ImageWindow *imd, FileData *fd);
if (imd->collection && collection_to_number(imd->collection) >= 0)
{
- const gchar *name;
- name = imd->collection->name;
+ const gchar *name = imd->collection->name;
if (!name) name = _("Untitled");
- collection = g_strdup_printf(" (Collection %s)", name);
+ collection = g_strdup_printf(_(" (Collection %s)"), name);
}
if (imd->title_show_zoom)
ColorManProfileType screen_type;
const gchar *input_file;
const gchar *screen_file;
- unsigned char *profile = NULL;
+ guchar *profile = NULL;
guint profile_len;
if (imd->cm) return FALSE;
static const gint flip[] = {1, 4, 3, 2, 1, 8, 7, 6, 5};
- if (!imd || !imd->pr) return;
+ if (!imd || !imd->pr || !imd->image_fd) return;
if (imd->orientation < 1 || imd->orientation > 8) imd->orientation = 1;
g_object_ref(imd->read_ahead_fd->pixbuf);
image_cache_set(imd, imd->read_ahead_fd);
}
- else
- {
- imd->read_ahead_fd->pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN);
- }
}
image_loader_free(imd->read_ahead_il);
imd->read_ahead_il = NULL;
DEBUG_1("%s read ahead started for :%s", get_exec_time(), imd->read_ahead_fd->path);
imd->read_ahead_il = image_loader_new(imd->read_ahead_fd);
+
+ image_loader_delay_area_ready(imd->read_ahead_il, TRUE); /* we will need the area_ready signals later */
- image_loader_set_error_func(imd->read_ahead_il, image_read_ahead_error_cb, imd);
- if (!image_loader_start(imd->read_ahead_il, image_read_ahead_done_cb, imd))
+ g_signal_connect (G_OBJECT(imd->read_ahead_il), "error", (GCallback)image_read_ahead_error_cb, imd);
+ g_signal_connect (G_OBJECT(imd->read_ahead_il), "done", (GCallback)image_read_ahead_done_cb, imd);
+
+ if (!image_loader_start(imd->read_ahead_il))
{
image_read_ahead_cancel(imd);
image_complete_util(imd, TRUE);
fd->pixbuf = NULL;
}
-static FileCacheData *image_get_cache()
+static FileCacheData *image_get_cache(void)
{
static FileCacheData *cache = NULL;
if (!cache) cache = file_cache_new(image_cache_release_cb, 1);
if (success)
{
g_assert(imd->image_fd->pixbuf);
- image_change_pixbuf(imd, imd->image_fd->pixbuf, image_zoom_get(imd));
+ image_change_pixbuf(imd, imd->image_fd->pixbuf, image_zoom_get(imd), FALSE);
}
file_cache_dump(image_get_cache());
{
if (image_get_pixbuf(imd) || !imd->il) return;
- image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd));
+ image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd), FALSE);
}
static void image_load_area_cb(ImageLoader *il, guint x, guint y, guint w, guint h, gpointer data)
return;
}
- if (!pr->pixbuf) image_load_pixbuf_ready(imd);
+ if (!pr->pixbuf) image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd), TRUE);
pixbuf_renderer_area_changed(pr, x, y, w, h);
}
if (options->image.enable_read_ahead && imd->image_fd && !imd->image_fd->pixbuf && image_loader_get_pixbuf(imd->il))
{
- imd->image_fd->pixbuf = gdk_pixbuf_ref(image_loader_get_pixbuf(imd->il));
+ imd->image_fd->pixbuf = g_object_ref(image_loader_get_pixbuf(imd->il));
image_cache_set(imd, imd->image_fd);
}
- if (imd->delay_flip &&
+ if (!image_loader_get_pixbuf(imd->il))
+ {
+ GdkPixbuf *pixbuf;
+
+ pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN);
+ image_change_pixbuf(imd, pixbuf, image_zoom_get(imd), FALSE);
+ g_object_unref(pixbuf);
+
+ imd->unknown = TRUE;
+ }
+ else if (imd->delay_flip &&
image_get_pixbuf(imd) != image_loader_get_pixbuf(imd->il))
{
g_object_set(G_OBJECT(imd->pr), "complete", FALSE, NULL);
- image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd));
+ image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd), FALSE);
}
image_loader_free(imd->il);
image_load_done_cb(il, data);
}
-#ifdef IMAGE_THROTTLE_LARGER_IMAGES
-static void image_load_buffer_throttle(ImageLoader *il)
-{
- if (!il || il->bytes_total < IMAGE_THROTTLE_THRESHOLD) return;
-
- /* Larger image files usually have larger chunks of data per pixel...
- * So increase the buffer read size so that the rendering chunks called
- * are also larger.
- */
-
- image_loader_set_buffer_size(il, IMAGE_LOAD_BUFFER_COUNT * IMAGE_THROTTLE_FACTOR);
-}
-#endif
-
/* this read ahead is located here merely for the callbacks, above */
static gint image_read_ahead_check(ImageWindow *imd)
imd->read_ahead_il = NULL;
/* override the old signals */
- image_loader_set_area_ready_func(imd->il, image_load_area_cb, imd);
- image_loader_set_error_func(imd->il, image_load_error_cb, imd);
- image_loader_set_done_func(imd->il, image_load_done_cb, imd);
- image_loader_set_buffer_size(imd->il, IMAGE_LOAD_BUFFER_COUNT);
-
-#ifdef IMAGE_THROTTLE_LARGER_IMAGES
- image_load_buffer_throttle(imd->il);
-#endif
+ g_signal_handlers_disconnect_matched(G_OBJECT(imd->il), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, imd);
+ g_signal_connect (G_OBJECT(imd->il), "area_ready", (GCallback)image_load_area_cb, imd);
+ g_signal_connect (G_OBJECT(imd->il), "error", (GCallback)image_load_error_cb, imd);
+ g_signal_connect (G_OBJECT(imd->il), "done", (GCallback)image_load_done_cb, imd);
g_object_set(G_OBJECT(imd->pr), "loading", TRUE, NULL);
image_state_set(imd, IMAGE_STATE_LOADING);
if (!imd->delay_flip)
{
- image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd));
+ image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd), TRUE);
}
+ image_loader_delay_area_ready(imd->il, FALSE); /* send the delayed area_ready signals */
+
file_data_unref(imd->read_ahead_fd);
imd->read_ahead_fd = NULL;
return TRUE;
}
else if (imd->read_ahead_fd->pixbuf)
{
- image_change_pixbuf(imd, imd->read_ahead_fd->pixbuf, image_zoom_get(imd));
+ image_change_pixbuf(imd, imd->read_ahead_fd->pixbuf, image_zoom_get(imd), FALSE);
file_data_unref(imd->read_ahead_fd);
imd->read_ahead_fd = NULL;
imd->il = image_loader_new(fd);
- image_loader_set_area_ready_func(imd->il, image_load_area_cb, imd);
- image_loader_set_error_func(imd->il, image_load_error_cb, imd);
- image_loader_set_buffer_size(imd->il, IMAGE_LOAD_BUFFER_COUNT);
+ g_signal_connect (G_OBJECT(imd->il), "area_ready", (GCallback)image_load_area_cb, imd);
+ g_signal_connect (G_OBJECT(imd->il), "error", (GCallback)image_load_error_cb, imd);
+ g_signal_connect (G_OBJECT(imd->il), "done", (GCallback)image_load_done_cb, imd);
- if (!image_loader_start(imd->il, image_load_done_cb, imd))
+ if (!image_loader_start(imd->il))
{
DEBUG_1("image start error");
image_state_set(imd, IMAGE_STATE_LOADING);
-#ifdef IMAGE_THROTTLE_LARGER_IMAGES
- image_load_buffer_throttle(imd->il);
-#endif
-
- if (!imd->delay_flip && !image_get_pixbuf(imd)) image_load_pixbuf_ready(imd);
-
+/*
+ if (!imd->delay_flip && !image_get_pixbuf(imd) && image_loader_get_pixbuf(imd->il))
+ {
+ image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd), TRUE);
+ }
+*/
return TRUE;
}
GdkPixbuf *pixbuf;
pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN);
- image_change_pixbuf(imd, pixbuf, zoom);
+ image_change_pixbuf(imd, pixbuf, zoom, FALSE);
g_object_unref(pixbuf);
imd->unknown = TRUE;
GdkPixbuf *pixbuf;
pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN);
- image_change_pixbuf(imd, pixbuf, zoom);
+ image_change_pixbuf(imd, pixbuf, zoom, FALSE);
g_object_unref(pixbuf);
}
else
{
- image_change_pixbuf(imd, NULL, zoom);
+ image_change_pixbuf(imd, NULL, zoom, FALSE);
}
imd->unknown = TRUE;
}
return pixbuf_renderer_get_pixbuf((PixbufRenderer *)imd->pr);
}
-void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom)
+void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom, gint lazy)
{
- ExifData *exif = NULL;
- gint read_exif_for_color_profile = (imd->color_profile_enable && imd->color_profile_use_image);
- gint read_exif_for_orientation = FALSE;
- if (imd->image_fd && imd->image_fd->user_orientation)
- imd->orientation = imd->image_fd->user_orientation;
- else if (options->image.exif_rotate_enable)
- read_exif_for_orientation = TRUE;
-
- if (read_exif_for_color_profile || read_exif_for_orientation)
+ /* read_exif and similar functions can actually notice that the file has changed and triger a notification
+ that removes the pixbuf from cache and unref it. Therefore we must ref it here before it is taken over by the renderer. */
+ if (pixbuf) g_object_ref(pixbuf);
+
+ if (imd->image_fd)
{
- gint orientation;
-
- exif = exif_read_fd(imd->image_fd);
-
- if (exif && read_exif_for_orientation)
+ if (imd->image_fd->user_orientation)
{
- if (exif_get_integer(exif, "Exif.Image.Orientation", &orientation))
- imd->orientation = orientation;
- else
- imd->orientation = 1;
+ imd->orientation = imd->image_fd->user_orientation;
+ }
+ else if (options->image.exif_rotate_enable)
+ {
+ imd->orientation = metadata_read_int(imd->image_fd, "Exif.Image.Orientation", EXIF_ORIENTATION_TOP_LEFT);
imd->image_fd->exif_orientation = imd->orientation;
}
}
imd->cm = NULL;
}
- pixbuf_renderer_set_pixbuf((PixbufRenderer *)imd->pr, pixbuf, zoom);
- pixbuf_renderer_set_orientation((PixbufRenderer *)imd->pr, imd->orientation);
+ if (lazy)
+ {
+ pixbuf_renderer_set_pixbuf_lazy((PixbufRenderer *)imd->pr, pixbuf, zoom, imd->orientation);
+ }
+ else
+ {
+ pixbuf_renderer_set_pixbuf((PixbufRenderer *)imd->pr, pixbuf, zoom);
+ pixbuf_renderer_set_orientation((PixbufRenderer *)imd->pr, imd->orientation);
+ }
+
+ if (pixbuf) g_object_unref(pixbuf);
if (imd->color_profile_enable)
{
+ ExifData *exif = NULL;
+
+ if (imd->color_profile_use_image) exif = exif_read_fd(imd->image_fd);
+
if (!image_post_process_color(imd, 0, exif, FALSE))
{
/* fixme: note error to user */
// image_state_set(imd, IMAGE_STATE_COLOR_ADJ);
}
- }
+ if (exif) exif_free_fd(imd->image_fd, exif);
- exif_free_fd(imd->image_fd, exif);
+ }
if (imd->cm || imd->desaturate)
pixbuf_renderer_set_post_process_func((PixbufRenderer *)imd->pr, image_post_process_tile_color_cb, (gpointer) imd, (imd->cm != NULL) );
return NULL;
}
-static void image_loader_sync_data(ImageLoader *il, gpointer data)
+static void image_loader_sync_read_ahead_data(ImageLoader *il, gpointer old_data, gpointer data)
{
- /* change data for the callbacks directly */
+ if (g_signal_handlers_disconnect_by_func(G_OBJECT(il), (GCallback)image_read_ahead_error_cb, old_data))
+ g_signal_connect (G_OBJECT(il), "error", (GCallback)image_read_ahead_error_cb, data);
+
+ if (g_signal_handlers_disconnect_by_func(G_OBJECT(il), (GCallback)image_read_ahead_done_cb, old_data))
+ g_signal_connect (G_OBJECT(il), "done", (GCallback)image_read_ahead_done_cb, data);
+}
+
+static void image_loader_sync_data(ImageLoader *il, gpointer old_data, gpointer data)
+{
+ if (g_signal_handlers_disconnect_by_func(G_OBJECT(il), (GCallback)image_load_area_cb, old_data))
+ g_signal_connect (G_OBJECT(il), "area_ready", (GCallback)image_load_area_cb, data);
- il->data_area_ready = data;
- il->data_error = data;
- il->data_done = data;
- il->data_percent = data;
+ if (g_signal_handlers_disconnect_by_func(G_OBJECT(il), (GCallback)image_load_error_cb, old_data))
+ g_signal_connect (G_OBJECT(il), "error", (GCallback)image_load_error_cb, data);
+
+ if (g_signal_handlers_disconnect_by_func(G_OBJECT(il), (GCallback)image_load_done_cb, old_data))
+ g_signal_connect (G_OBJECT(il), "done", (GCallback)image_load_done_cb, data);
}
/* this is more like a move function
imd->il = source->il;
source->il = NULL;
- image_loader_sync_data(imd->il, imd);
+ image_loader_sync_data(imd->il, source, imd);
imd->delay_alter_type = source->delay_alter_type;
source->delay_alter_type = ALTER_NONE;
image_loader_free(imd->read_ahead_il);
imd->read_ahead_il = source->read_ahead_il;
source->read_ahead_il = NULL;
- if (imd->read_ahead_il) image_loader_sync_data(imd->read_ahead_il, imd);
+ if (imd->read_ahead_il) image_loader_sync_read_ahead_data(imd->read_ahead_il, source, imd);
file_data_unref(imd->read_ahead_fd);
imd->read_ahead_fd = source->read_ahead_fd;
pixbuf_renderer_zoom_set((PixbufRenderer *)imd->pr, zoom);
}
-void image_zoom_set_fill_geometry(ImageWindow *imd, gint vertical)
+void image_zoom_set_fill_geometry(ImageWindow *imd, gboolean vertical)
{
PixbufRenderer *pr;
gdouble zoom;
ImageWindow *imd = data;
if (!imd || !image_get_pixbuf(imd) ||
- /* imd->il || */ /* loading in progress - do not check - it should start from the beginning anyway */
+ /* imd->il || */ /* loading in progress - do not check - it should start from the beginning anyway */
!imd->image_fd || /* nothing to reload */
imd->state == IMAGE_STATE_NONE /* loading not started, no need to reload */
) return;
if (frame)
{
imd->frame = gtk_frame_new(NULL);
- gtk_widget_ref(imd->pr);
+#if GTK_CHECK_VERSION(2,12,0)
+ g_object_ref(imd->pr);
+#else
+ gtk_widget_ref(imd->pr);
+#endif
if (imd->has_frame != -1) gtk_container_remove(GTK_CONTAINER(imd->widget), imd->pr);
gtk_container_add(GTK_CONTAINER(imd->frame), imd->pr);
- gtk_widget_unref(imd->pr);
+
+#if GTK_CHECK_VERSION(2,12,0)
+ g_object_unref(imd->pr);
+#else
+ gtk_widget_unref(imd->pr);
+#endif
g_signal_connect(G_OBJECT(imd->frame), "expose_event",
G_CALLBACK(selectable_frame_expose_cb), NULL);
g_signal_connect_after(G_OBJECT(imd->frame), "expose_event",
G_CALLBACK(image_focus_expose), imd);
-
- gtk_box_pack_start_defaults(GTK_BOX(imd->widget), imd->frame);
- gtk_widget_show(imd->frame);
+#if GTK_CHECK_VERSION(2,14,0)
+ gtk_box_pack_start(GTK_BOX(imd->widget), imd->frame, TRUE, TRUE, 0);
+#else
+ gtk_box_pack_start_defaults(GTK_BOX(imd->widget), imd->frame);
+#endif
+ gtk_widget_show(imd->frame);
}
else
{
+#if GTK_CHECK_VERSION(2,12,0)
+ g_object_ref(imd->pr);
+#else
gtk_widget_ref(imd->pr);
+#endif
if (imd->frame)
{
gtk_container_remove(GTK_CONTAINER(imd->frame), imd->pr);
gtk_widget_destroy(imd->frame);
imd->frame = NULL;
}
+#if GTK_CHECK_VERSION(2,14,0)
+ gtk_box_pack_start(GTK_BOX(imd->widget), imd->pr, TRUE, TRUE, 0);
+#else
gtk_box_pack_start_defaults(GTK_BOX(imd->widget), imd->pr);
- gtk_widget_unref(imd->pr);
+#endif
+
+#if GTK_CHECK_VERSION(2,12,0)
+ g_object_unref(imd->pr);
+#else
+ gtk_widget_unref(imd->pr);
+#endif
}
gtk_widget_show(imd->pr);
return imd;
}
+/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */