Commit 5209289d authored by Christian Neumair's avatar Christian Neumair Committed by Christian Neumair

Scale down huge pixbufs when loading. Massively speed up loading of

2008-06-30  Christian Neumair  <cneumair@gnome.org>

	* libnautilus-private/nautilus-directory-async.c (thumbnail_done),
	(thumbnail_loader_size_prepared), (get_pixbuf_for_content),
	(thumbnail_start):
	* libnautilus-private/nautilus-file.h:
	Scale down huge pixbufs when loading. Massively speed up loading of
	directories where the original image is used as thumbnail.
	Also try to write the whole file at once rather than writing in chunks.

	* libnautilus-private/nautilus-file-private.h:
	* libnautilus-private/nautilus-file.c (nautilus_file_get_icon):
	Rewrite some flaky parts of thumbnailing.

	Never scale any thumbnails up.
	Always compose thumbnail on the fly instead storing it once and
	scaling it up and down.
	Add flag to force that thumbnail size matches
	the output icon size for tree view.

	* src/file-manager/fm-list-model.c (fm_list_model_get_value):
	Use this flag.

svn path=/trunk/; revision=14309
parent d9156a31
2008-06-30 Christian Neumair <cneumair@gnome.org>
* libnautilus-private/nautilus-directory-async.c (thumbnail_done),
(thumbnail_loader_size_prepared), (get_pixbuf_for_content),
(thumbnail_start):
* libnautilus-private/nautilus-file.h:
Scale down huge pixbufs when loading. Massively speed up loading of
directories where the original image is used as thumbnail.
Also try to write the whole file at once rather than writing in chunks.
* libnautilus-private/nautilus-file-private.h:
* libnautilus-private/nautilus-file.c (nautilus_file_get_icon):
Rewrite some flaky parts of thumbnailing.
Never scale any thumbnails up.
Always compose thumbnail on the fly instead storing it once and
scaling it up and down.
Add flag to force that thumbnail size matches
the output icon size for tree view.
* src/file-manager/fm-list-model.c (fm_list_model_get_value):
Use this flag.
2008-06-29 Cosimo Cecchi <cosimoc@gnome.org>
* README: Remove reference to the need of a GNOME 2.4 environment
......
......@@ -3768,7 +3768,6 @@ thumbnail_done (NautilusDirectory *directory,
g_object_unref (file->details->thumbnail);
file->details->thumbnail = NULL;
}
file->details->thumbnail_size = 0;
if (pixbuf) {
thumb_mtime_str = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::MTime");
if (thumb_mtime_str) {
......@@ -3838,6 +3837,35 @@ thumbnail_state_free (ThumbnailState *state)
g_free (state);
}
extern int cached_thumbnail_size;
/* scale very large images down to the max. size we need */
static void
thumbnail_loader_size_prepared (GdkPixbufLoader *loader,
int width,
int height,
gpointer user_data)
{
int max_thumbnail_size;
double aspect_ratio;
aspect_ratio = ((double) width) / height;
/* cf. nautilus_file_get_icon() */
max_thumbnail_size = NAUTILUS_ICON_SIZE_LARGEST * cached_thumbnail_size / NAUTILUS_ICON_SIZE_STANDARD;
if (MAX (width, height) > max_thumbnail_size) {
if (width > height) {
width = max_thumbnail_size;
height = width / aspect_ratio;
} else {
height = max_thumbnail_size;
width = height * aspect_ratio;
}
gdk_pixbuf_loader_set_size (loader, width, height);
}
}
static GdkPixbuf *
get_pixbuf_for_content (goffset file_len,
char *file_contents)
......@@ -3849,11 +3877,14 @@ get_pixbuf_for_content (goffset file_len,
pixbuf = NULL;
loader = gdk_pixbuf_loader_new ();
g_signal_connect (loader, "size-prepared",
G_CALLBACK (thumbnail_loader_size_prepared),
NULL);
/* For some reason we have to write in chunks, or gdk-pixbuf fails */
res = TRUE;
while (res && file_len > 0) {
chunk_len = MIN (32*1024, file_len);
chunk_len = file_len;
res = gdk_pixbuf_loader_write (loader, file_contents, chunk_len, NULL);
file_contents += chunk_len;
file_len -= chunk_len;
......@@ -3959,7 +3990,7 @@ thumbnail_start (NautilusDirectory *directory,
state->file = file;
state->cancellable = g_cancellable_new ();
if (file->details->thumbnail_size > 128) {
if (file->details->thumbnail_wants_original) {
state->tried_original = TRUE;
state->trying_original = TRUE;
location = nautilus_file_get_location (file);
......
......@@ -107,7 +107,6 @@ struct NautilusFileDetails
char *thumbnail_path;
GdkPixbuf *thumbnail;
time_t thumbnail_mtime;
int thumbnail_size; /* 0 means original unframed thumbnail */
GList *mime_list; /* If this is a directory, the list of MIME types in it. */
char *top_left_text;
......@@ -182,6 +181,7 @@ struct NautilusFileDetails
eel_boolean_bit got_custom_activation_location : 1;
eel_boolean_bit thumbnail_is_up_to_date : 1;
eel_boolean_bit thumbnail_wants_original : 1;
eel_boolean_bit thumbnail_tried_original : 1;
eel_boolean_bit thumbnailing_failed : 1;
......
......@@ -3228,7 +3228,7 @@ get_custom_icon (NautilusFile *file)
static int cached_thumbnail_limit;
static int cached_thumbnail_size;
int cached_thumbnail_size;
static int show_image_thumbs;
GFilesystemPreviewType
......@@ -3387,51 +3387,52 @@ nautilus_file_get_icon (NautilusFile *file,
return icon;
}
modified_size = size * cached_thumbnail_size / NAUTILUS_ICON_SIZE_STANDARD;
if (flags & NAUTILUS_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
modified_size = size;
} else {
modified_size = size * cached_thumbnail_size / NAUTILUS_ICON_SIZE_STANDARD;
}
if (flags & NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS &&
nautilus_file_should_show_thumbnail (file)) {
if (file->details->thumbnail) {
if (file->details->thumbnail_size == modified_size) {
scaled_pixbuf = g_object_ref (file->details->thumbnail);
} else {
int w, h, s;
double scale;
if (file->details->thumbnail_size == 0) {
raw_pixbuf = g_object_ref (file->details->thumbnail);
} else {
raw_pixbuf = nautilus_thumbnail_unframe_image (file->details->thumbnail);
}
int w, h, s;
double scale;
w = gdk_pixbuf_get_width (raw_pixbuf);
h = gdk_pixbuf_get_height (raw_pixbuf);
s = MAX (w, h);
scale = (double)modified_size / s;
raw_pixbuf = g_object_ref (file->details->thumbnail);
/* These compensate for the size of the frame which will be added around the raw image */
w = gdk_pixbuf_get_width (raw_pixbuf);
h = gdk_pixbuf_get_height (raw_pixbuf);
s = MAX (w, h);
scale = (double)modified_size / s;
if (scale > 0.99) {
/* never scale any thumbnails up */
scaled_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
gdk_pixbuf_get_has_alpha (raw_pixbuf),
gdk_pixbuf_get_bits_per_sample (raw_pixbuf),
w * scale, h * scale);
gdk_pixbuf_fill (scaled_pixbuf, 0xffffff00);
gdk_pixbuf_copy_area (raw_pixbuf,
0, 0, w, h,
scaled_pixbuf,
(gdk_pixbuf_get_width (scaled_pixbuf) - w) / 2,
(gdk_pixbuf_get_height (scaled_pixbuf) - h) / 2);
} else {
scaled_pixbuf = gdk_pixbuf_scale_simple (raw_pixbuf,
NAUTILUS_THUMBNAIL_FRAME_LEFT + w * scale + NAUTILUS_THUMBNAIL_FRAME_RIGHT,
NAUTILUS_THUMBNAIL_FRAME_TOP + h * scale + NAUTILUS_THUMBNAIL_FRAME_BOTTOM,
w * scale, h * scale,
GDK_INTERP_BILINEAR);
nautilus_thumbnail_frame_image (&scaled_pixbuf);
g_object_unref (raw_pixbuf);
if (modified_size > file->details->thumbnail_size) {
/* Invalidate if we resize upward (and the
loaded was not the original raw version, w/ size 0).
*/
if (file->details->thumbnail_size != 0 ||
(modified_size > 128 && !file->details->thumbnail_tried_original)) {
nautilus_file_invalidate_attributes (file, NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL);
}
file->details->thumbnail_size = modified_size;
g_object_unref (file->details->thumbnail);
file->details->thumbnail = g_object_ref (scaled_pixbuf);
}
}
nautilus_thumbnail_frame_image (&scaled_pixbuf);
g_object_unref (raw_pixbuf);
if (modified_size > 128 &&
!file->details->thumbnail_wants_original) {
/* Invalidate if we resize upward */
file->details->thumbnail_wants_original = TRUE;
nautilus_file_invalidate_attributes (file, NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL);
}
icon = nautilus_icon_info_new_for_pixbuf (scaled_pixbuf);
......
......@@ -77,7 +77,9 @@ typedef enum {
NAUTILUS_FILE_ICON_FLAGS_IGNORE_VISITING = (1<<1),
NAUTILUS_FILE_ICON_FLAGS_EMBEDDING_TEXT = (1<<2),
NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT = (1<<3),
NAUTILUS_FILE_ICON_FLAGS_FOR_OPEN_FOLDER = (1<<4)
NAUTILUS_FILE_ICON_FLAGS_FOR_OPEN_FOLDER = (1<<4),
/* whether the thumbnail size must match the display icon size */
NAUTILUS_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE = (1<<5)
} NautilusFileIconFlags;
/* Emblems sometimes displayed for NautilusFiles. Do not localize. */
......
......@@ -286,7 +286,8 @@ fm_list_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, int column
zoom_level = fm_list_model_get_zoom_level_from_column_id (column);
icon_size = nautilus_get_icon_size_for_zoom_level (zoom_level);
flags = NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS;
flags = NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS |
NAUTILUS_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE;
if (model->details->drag_view != NULL) {
GtkTreePath *path_a, *path_b;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment