void vnr_tools_apply_embedded_orientation (GdkPixbufAnimation **anim) { GdkPixbuf *pixbuf; GdkPixbuf *original; if(!gdk_pixbuf_animation_is_static_image (*anim)) return; pixbuf = gdk_pixbuf_animation_get_static_image (*anim); original = pixbuf; pixbuf = gdk_pixbuf_apply_embedded_orientation(pixbuf); if(original == pixbuf) { g_object_unref(pixbuf); return; } GdkPixbufSimpleAnim *s_anim; s_anim = gdk_pixbuf_simple_anim_new (gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), -1); gdk_pixbuf_simple_anim_add_frame(s_anim, pixbuf); g_object_unref(pixbuf); g_object_unref(*anim); *anim = GDK_PIXBUF_ANIMATION(s_anim); }
static void file_buffer_ready_cb (void **buffer, gsize count, GError *error, gpointer user_data) { GthPixbufListTask *self = user_data; GInputStream *istream; GdkPixbuf *pixbuf; if (error != NULL) { gth_task_completed (GTH_TASK (self), error); return; } istream = g_memory_input_stream_new_from_data (*buffer, count, NULL); pixbuf = gdk_pixbuf_new_from_stream (istream, gth_task_get_cancellable (GTH_TASK (self)), &error); if (pixbuf != NULL) { self->priv->original_pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf); g_object_unref (pixbuf); } else self->priv->original_pixbuf = NULL; g_object_unref (istream); if (self->priv->original_pixbuf == NULL) { gth_task_completed (GTH_TASK (self), error); return; } gth_pixbuf_task_set_source (GTH_PIXBUF_TASK (self->priv->task), self->priv->original_pixbuf); gth_task_exec (self->priv->task, gth_task_get_cancellable (GTH_TASK (self))); }
GdkPixbuf * hd_pixbuf_utils_load_scaled_and_cropped (GFile *file, HDImageSize *size, char **etag, GCancellable *cancellable, GError **error) { GFileInputStream *stream = NULL; GdkPixbufLoader *loader = NULL; GdkPixbuf *pixbuf = NULL; /* Open file for read */ stream = g_file_read (file, cancellable, error); if (!stream) goto cleanup; /* Create pixbuf loader */ loader = gdk_pixbuf_loader_new (); g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), size); if (!get_etag_from_file_input_stream (stream, etag, cancellable, error)) goto cleanup; if (!read_from_input_stream_into_pixbuf_loader (G_INPUT_STREAM (stream), loader, cancellable, error)) goto cleanup; /* Set resulting pixbuf */ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); if (pixbuf) { GdkPixbuf *rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf); pixbuf = scale_and_crop_pixbuf (rotated, size); g_object_unref (rotated); } else g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, "NULL Pixbuf returned from loader"); cleanup: if (stream) g_object_unref (stream); if (loader) g_object_unref (loader); return pixbuf; }
static GthImage * facebook_thumbnail_loader (GInputStream *istream, GthFileData *file_data, int requested_size, int *original_width, int *original_height, gboolean *loaded_original, gpointer user_data, GCancellable *cancellable, GError **error) { GthImage *image = NULL; FacebookPhoto *photo; const char *uri; photo = (FacebookPhoto *) g_file_info_get_attribute_object (file_data->info, "facebook::object"); uri = facebook_photo_get_thumbnail_url (photo, requested_size); if (uri == NULL) uri = facebook_photo_get_original_url (photo); if (uri != NULL) { GFile *file; void *buffer; gsize size; file = g_file_new_for_uri (uri); if (_g_file_load_in_buffer (file, &buffer, &size, cancellable, error)) { GInputStream *stream; GdkPixbuf *pixbuf; stream = g_memory_input_stream_new_from_data (buffer, size, g_free); pixbuf = gdk_pixbuf_new_from_stream (stream, cancellable, error); if (pixbuf != NULL) { GdkPixbuf *rotated; rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf); g_object_unref (pixbuf); pixbuf = rotated; image = gth_image_new_for_pixbuf (pixbuf); } g_object_unref (pixbuf); g_object_unref (stream); } g_object_unref (file); } else *error = g_error_new_literal (GTH_ERROR, 0, "cannot generate the thumbnail"); return image; }
static void update_preview_cb (GtkFileChooser *file_chooser, gpointer data) { GtkImage *preview = GTK_IMAGE (data); g_autofree char *filename = gtk_file_chooser_get_preview_filename (file_chooser); gint preview_width = 0; gint preview_height = 0; struct g_stat st_buf; g_autoptr(GdkPixbuf) pixbuf = NULL; GdkPixbufFormat *preview_format = gdk_pixbuf_get_file_info (filename, &preview_width, &preview_height); if (!filename || g_stat (filename, &st_buf) || (!S_ISREG (st_buf.st_mode))) { gtk_file_chooser_set_preview_widget_active (file_chooser, FALSE); return; // stat failed or file is not regular } if (!preview_format || preview_width <= 0 || preview_height <= 0 || preview_width > MAX_PREVIEW_SOURCE_SIZE || preview_height > MAX_PREVIEW_SOURCE_SIZE) { gtk_file_chooser_set_preview_widget_active (file_chooser, FALSE); return; // unpreviewable, 0px, or unsafely large } if (preview_width > MAX_PREVIEW_SIZE || preview_height > MAX_PREVIEW_SIZE) { pixbuf = gdk_pixbuf_new_from_file_at_size (filename, MAX_PREVIEW_SIZE, MAX_PREVIEW_SIZE, NULL); } else { pixbuf = gdk_pixbuf_new_from_file (filename, NULL); } pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf); gtk_widget_set_size_request (GTK_WIDGET (preview), gdk_pixbuf_get_width (pixbuf) + 6, gdk_pixbuf_get_height (pixbuf) + 6); gtk_image_set_from_pixbuf (preview, pixbuf); gtk_file_chooser_set_preview_widget_active (file_chooser, pixbuf != NULL); }
GdkPixbuf * file_to_pixbuf (const char *path, guint destination_size, GError **error) { GdkPixbuf *pixbuf, *tmp_pixbuf; GFile *file; char *uri; int original_width, original_height; file = g_file_new_for_path (path); uri = g_file_get_uri (file); pixbuf = _gdk_pixbuf_new_from_uri_at_scale (uri, destination_size, error); if (pixbuf == NULL) return NULL; tmp_pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf); gdk_pixbuf_copy_options (pixbuf, tmp_pixbuf); gdk_pixbuf_remove_option (tmp_pixbuf, "orientation"); g_object_unref (pixbuf); pixbuf = tmp_pixbuf; original_width = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pixbuf), "gnome-original-width")); original_height = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pixbuf), "gnome-original-height")); if (original_width > 0 && original_height > 0) { char *tmp; tmp = g_strdup_printf ("%d", original_width); gdk_pixbuf_set_option (pixbuf, "tEXt::Thumb::Image::Width", tmp); g_free (tmp); tmp = g_strdup_printf ("%d", original_height); gdk_pixbuf_set_option (pixbuf, "tEXt::Thumb::Image::Height", tmp); g_free (tmp); } return pixbuf; }
static GdkPixbuf * impl_load_pixbuf_data (const guchar *data, gsize size, int available_width, int available_height, int scale, GError **error) { GdkPixbufLoader *pixbuf_loader = NULL; GdkPixbuf *rotated_pixbuf = NULL; GdkPixbuf *pixbuf; gboolean success; Dimensions available_dimensions; int width_before_rotation, width_after_rotation; pixbuf_loader = gdk_pixbuf_loader_new (); available_dimensions.width = available_width; available_dimensions.height = available_height; available_dimensions.scale = scale; g_signal_connect (pixbuf_loader, "size-prepared", G_CALLBACK (on_image_size_prepared), &available_dimensions); success = gdk_pixbuf_loader_write (pixbuf_loader, data, size, error); if (!success) goto out; success = gdk_pixbuf_loader_close (pixbuf_loader, error); if (!success) goto out; pixbuf = gdk_pixbuf_loader_get_pixbuf (pixbuf_loader); width_before_rotation = gdk_pixbuf_get_width (pixbuf); rotated_pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf); width_after_rotation = gdk_pixbuf_get_width (rotated_pixbuf); /* There is currently no way to tell if the pixbuf will need to be rotated before it is loaded, * so we only check that once it is loaded, and reload it again if it needs to be rotated in order * to use the available width and height correctly. * See http://bugzilla.gnome.org/show_bug.cgi?id=579003 */ if (width_before_rotation != width_after_rotation) { g_object_unref (pixbuf_loader); g_object_unref (rotated_pixbuf); rotated_pixbuf = NULL; pixbuf_loader = gdk_pixbuf_loader_new (); /* We know that the image will later be rotated, so we reverse the available dimensions. */ available_dimensions.width = available_height; available_dimensions.height = available_width; available_dimensions.scale = scale; g_signal_connect (pixbuf_loader, "size-prepared", G_CALLBACK (on_image_size_prepared), &available_dimensions); success = gdk_pixbuf_loader_write (pixbuf_loader, data, size, error); if (!success) goto out; success = gdk_pixbuf_loader_close (pixbuf_loader, error); if (!success) goto out; pixbuf = gdk_pixbuf_loader_get_pixbuf (pixbuf_loader); rotated_pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf); } out: if (pixbuf_loader) g_object_unref (pixbuf_loader); return rotated_pixbuf; }
static GdkPixbuf* _vfs_thumbnail_load( const char* file_path, const char* uri, int size, time_t mtime ) { #if GLIB_CHECK_VERSION(2, 16, 0) GChecksum *cs; #else md5_state_t md5_state; md5_byte_t md5[ 16 ]; #endif char file_name[ 40 ]; char* thumbnail_file; char mtime_str[ 32 ]; const char* thumb_mtime; int i, w, h; struct stat statbuf; GdkPixbuf* thumbnail, *result = NULL; int create_size; if ( size > 256 ) create_size = 512; else if ( size > 128 ) create_size = 256; else create_size = 128; gboolean file_is_video = FALSE; #ifdef HAVE_FFMPEG VFSMimeType* mimetype = vfs_mime_type_get_from_file_name( file_path ); if ( mimetype ) { if ( strncmp( vfs_mime_type_get_type( mimetype ), "video/", 6 ) == 0 ) file_is_video = TRUE; vfs_mime_type_unref( mimetype ); } #endif if ( file_is_video == FALSE ) { if ( !gdk_pixbuf_get_file_info( file_path, &w, &h ) ) return NULL; /* image format cannot be recognized */ /* If the image itself is very small, we should load it directly */ if ( w <= create_size && h <= create_size ) { if( w <= size && h <= size ) return gdk_pixbuf_new_from_file( file_path, NULL ); return gdk_pixbuf_new_from_file_at_size( file_path, size, size, NULL ); } } #if GLIB_CHECK_VERSION(2, 16, 0) cs = g_checksum_new(G_CHECKSUM_MD5); g_checksum_update(cs, uri, strlen(uri)); memcpy( file_name, g_checksum_get_string(cs), 32 ); g_checksum_free(cs); #else md5_init( &md5_state ); md5_append( &md5_state, ( md5_byte_t * ) uri, strlen( uri ) ); md5_finish( &md5_state, md5 ); for ( i = 0; i < 16; ++i ) sprintf( ( file_name + i * 2 ), "%02x", md5[ i ] ); #endif strcpy( ( file_name + 32 ), ".png" ); thumbnail_file = g_build_filename( g_get_home_dir(), ".thumbnails/normal", file_name, NULL ); if( G_UNLIKELY( 0 == mtime ) ) { if( stat( file_path, &statbuf ) != -1 ) mtime = statbuf.st_mtime; } if ( file_is_video && time( NULL ) - mtime < 5 ) /* if mod time of video being thumbnailed is less than 5 sec ago, * don't create a thumbnail (is copying?) * FIXME: This means that a newly saved file may not show a thumbnail * until refresh. */ return NULL; /* load existing thumbnail */ thumbnail = gdk_pixbuf_new_from_file( thumbnail_file, NULL ); if ( thumbnail ) { w = gdk_pixbuf_get_width( thumbnail ); h = gdk_pixbuf_get_height( thumbnail ); } if ( !thumbnail || ( w < size && h < size ) || !( thumb_mtime = gdk_pixbuf_get_option( thumbnail, "tEXt::Thumb::MTime" ) ) || atol( thumb_mtime ) != mtime ) { if( thumbnail ) g_object_unref( thumbnail ); /* create new thumbnail */ if ( file_is_video == FALSE ) { thumbnail = gdk_pixbuf_new_from_file_at_size( file_path, create_size, create_size, NULL ); if ( thumbnail ) { // Note: gdk_pixbuf_apply_embedded_orientation returns a new // pixbuf or same with incremented ref count, so unref GdkPixbuf* thumbnail_old = thumbnail; thumbnail = gdk_pixbuf_apply_embedded_orientation( thumbnail ); g_object_unref( thumbnail_old ); sprintf( mtime_str, "%lu", mtime ); gdk_pixbuf_save( thumbnail, thumbnail_file, "png", NULL, "tEXt::Thumb::URI", uri, "tEXt::Thumb::MTime", mtime_str, NULL ); chmod( thumbnail_file, 0600 ); /* only the owner can read it. */ } } #ifdef HAVE_FFMPEG else { video_thumbnailer* video_thumb = video_thumbnailer_create(); /* Setting a callback to allow silencing of stdout/stderr messages * from the library. This is no longer required since v2.0.11, where * silence is the default. It can be used for debugging in 2.0.11 * and later. */ //video_thumbnailer_set_log_callback(on_video_thumbnailer_log_message); if ( video_thumb ) { video_thumb->seek_percentage = 25; video_thumb->overlay_film_strip = 1; video_thumb->thumbnail_size = create_size; video_thumbnailer_generate_thumbnail_to_file( video_thumb, file_path, thumbnail_file ); video_thumbnailer_destroy( video_thumb ); chmod( thumbnail_file, 0600 ); /* only the owner can read it. */ thumbnail = gdk_pixbuf_new_from_file( thumbnail_file, NULL ); } } #endif } if ( thumbnail ) { w = gdk_pixbuf_get_width( thumbnail ); h = gdk_pixbuf_get_height( thumbnail ); if ( w > h ) { h = h * size / w; w = size; } else if ( h > w ) { w = w * size / h; h = size; } else { w = h = size; } if ( w > 0 && h > 0 ) result = gdk_pixbuf_scale_simple( thumbnail, w, h, GDK_INTERP_BILINEAR ); g_object_unref( thumbnail ); } g_free( thumbnail_file ); return result; }
static GthImage * flickr_thumbnail_loader (GInputStream *istream, GthFileData *file_data, int requested_size, int *original_width, int *original_height, gboolean *loaded_original, gpointer user_data, GCancellable *cancellable, GError **error) { GthImage *image = NULL; GthThumbLoader *thumb_loader = user_data; FlickrPhoto *photo; const char *uri = NULL; photo = (FlickrPhoto *) g_file_info_get_attribute_object (file_data->info, "flickr::object"); requested_size = gth_thumb_loader_get_requested_size (thumb_loader); if (requested_size == FLICKR_SIZE_SMALL_SQUARE) uri = photo->url[FLICKR_URL_SQ]; else if (requested_size == FLICKR_SIZE_THUMBNAIL) uri = photo->url[FLICKR_URL_T]; else if (requested_size == FLICKR_SIZE_SMALL) uri = photo->url[FLICKR_URL_S]; else if (requested_size == FLICKR_SIZE_MEDIUM) uri = photo->url[FLICKR_URL_M]; if (uri == NULL) uri = photo->url[FLICKR_URL_O]; if (uri != NULL) { GFile *file; void *buffer; gsize size; file = g_file_new_for_uri (uri); if (_g_file_load_in_buffer (file, &buffer, &size, cancellable, error)) { GInputStream *stream; GdkPixbuf *pixbuf; stream = g_memory_input_stream_new_from_data (buffer, size, g_free); pixbuf = gdk_pixbuf_new_from_stream (stream, cancellable, error); if (pixbuf != NULL) { GdkPixbuf *rotated; rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf); g_object_unref (pixbuf); pixbuf = rotated; image = gth_image_new_for_pixbuf (pixbuf); } g_object_unref (pixbuf); g_object_unref (stream); } g_object_unref (file); } else *error = g_error_new_literal (GTH_ERROR, 0, "cannot generate the thumbnail"); return image; }
GthImage * gth_pixbuf_new_from_file (GInputStream *istream, GthFileData *file_data, int requested_size, int *original_width, int *original_height, gboolean *loaded_original, gboolean scale_to_original, GCancellable *cancellable, GError **error) { ScaleData scale_data; GdkPixbufLoader *pixbuf_loader; GdkPixbuf *pixbuf; GthImage *image; gboolean original_size_rotated = FALSE; if (original_width != NULL) *original_width = -1; if (original_height != NULL) *original_height = -1; 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, istream, requested_size, cancellable, error); g_object_unref (pixbuf_loader); if ((pixbuf != NULL) && scale_to_original) { GdkPixbuf *tmp; tmp = _gdk_pixbuf_scale_simple_safe (pixbuf, scale_data.original_width, scale_data.original_height, GDK_INTERP_NEAREST); g_object_unref (pixbuf); pixbuf = tmp; } if ((original_width != NULL) && (original_height != NULL)) { if (file_data != NULL) { char *path; path = g_file_get_path (file_data->file); if (path != NULL) { gdk_pixbuf_get_file_info (path, &scale_data.original_width, &scale_data.original_height); original_size_rotated = TRUE; g_free (path); } } } if (pixbuf != NULL) { GdkPixbuf *rotated; rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf); if (rotated != NULL) { if (! original_size_rotated) { /* swap width and height */ int tmp = scale_data.original_width; scale_data.original_width = scale_data.original_height; scale_data.original_height =tmp; } g_object_unref (pixbuf); pixbuf = rotated; } } image = gth_image_new (); if (pixbuf != NULL) { cairo_surface_t *surface; cairo_surface_metadata_t *metadata; surface = _cairo_image_surface_create_from_pixbuf (pixbuf); metadata = _cairo_image_surface_get_metadata (surface); metadata->original_width = scale_data.original_width; metadata->original_height = scale_data.original_height; metadata->has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); gth_image_set_cairo_surface (image, surface); } if (original_width != NULL) *original_width = scale_data.original_width; if (original_height != NULL) *original_height = scale_data.original_height; if (loaded_original != NULL) *loaded_original = (pixbuf != NULL) && (scale_data.original_width == gdk_pixbuf_get_width (pixbuf)) && (scale_data.original_height == gdk_pixbuf_get_height (pixbuf)); _g_object_unref (pixbuf); return image; }
GthImage * gth_pixbuf_new_from_file (GInputStream *istream, GthFileData *file_data, int requested_size, int *original_width, int *original_height, gboolean scale_to_original, GCancellable *cancellable, GError **error) { ScaleData scale_data; GdkPixbufLoader *pixbuf_loader; GdkPixbuf *pixbuf; GthImage *image; if (original_width != NULL) *original_width = -1; if (original_height != NULL) *original_height = -1; 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, istream, requested_size, cancellable, error); g_object_unref (pixbuf_loader); if ((pixbuf != NULL) && scale_to_original) { GdkPixbuf *tmp; tmp = _gdk_pixbuf_scale_simple_safe (pixbuf, scale_data.original_width, scale_data.original_height, GDK_INTERP_NEAREST); g_object_unref (pixbuf); pixbuf = tmp; } if (pixbuf != NULL) { GdkPixbuf *rotated; rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf); if (rotated != NULL) { scale_data.original_width = gdk_pixbuf_get_width (rotated); scale_data.original_height = gdk_pixbuf_get_height (rotated); g_object_unref (pixbuf); pixbuf = rotated; } } image = gth_image_new_for_pixbuf (pixbuf); if (original_width != NULL) *original_width = scale_data.original_width; if (original_height != NULL) *original_height = scale_data.original_height; _g_object_unref (pixbuf); return image; }
static GthImage * picasa_web_thumbnail_loader (GInputStream *istream, GthFileData *file_data, int requested_size, int *original_width, int *original_height, gboolean *loaded_original, gpointer user_data, GCancellable *cancellable, GError **error) { GthImage *image = NULL; GthThumbLoader *thumb_loader = user_data; PicasaWebPhoto *photo; const char *uri; photo = (PicasaWebPhoto *) g_file_info_get_attribute_object (file_data->info, "gphoto::object"); requested_size = gth_thumb_loader_get_requested_size (thumb_loader); if (requested_size == 72) uri = photo->thumbnail_72; else if (requested_size == 144) uri = photo->thumbnail_144; else if (requested_size == 288) uri = photo->thumbnail_288; else uri = NULL; if (uri == NULL) uri = photo->uri; if (uri != NULL) { GFile *file; void *buffer; gsize size; file = g_file_new_for_uri (uri); if (_g_file_load_in_buffer (file, &buffer, &size, cancellable, error)) { GInputStream *stream; GdkPixbuf *pixbuf; stream = g_memory_input_stream_new_from_data (buffer, size, g_free); pixbuf = gdk_pixbuf_new_from_stream (stream, cancellable, error); if (pixbuf != NULL) { GdkPixbuf *rotated; rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf); g_object_unref (pixbuf); pixbuf = rotated; image = gth_image_new_for_pixbuf (pixbuf); } g_object_unref (pixbuf); g_object_unref (stream); } g_object_unref (file); } else *error = g_error_new_literal (GTH_ERROR, 0, "cannot generate the thumbnail"); return image; }
void generate_thumbnails_with_gdk_pixbuf(ThumbnailTask* task) { /* FIXME: only formats supported by GdkPixbuf should be handled this way. */ GFile* gf = fm_path_to_gfile(task->fi->path); GFileInputStream* ins; GdkPixbuf* normal_pix = NULL; GdkPixbuf* large_pix = NULL; DEBUG("generate thumbnail for %s", task->fi->path->name); if( ins = g_file_read(gf, generator_cancellable, NULL) ) { GdkPixbuf* ori_pix; gssize len; ori_pix = gdk_pixbuf_new_from_stream(G_INPUT_STREAM(ins), generator_cancellable, NULL); if(ori_pix) /* if the original image is successfully loaded */ { const char* orientation_str = gdk_pixbuf_get_option(ori_pix, "orientation"); int width = gdk_pixbuf_get_width(ori_pix); int height = gdk_pixbuf_get_height(ori_pix); gboolean need_save; if(task->flags & GENERATE_NORMAL) { /* don't create thumbnails for images which are too small */ if(width <=128 && height <= 128) { normal_pix = (GdkPixbuf*)g_object_ref(ori_pix); need_save = FALSE; } else { normal_pix = scale_pix(ori_pix, 128); need_save = TRUE; } if(orientation_str) { GdkPixbuf* rotated; gdk_pixbuf_set_option(normal_pix, "orientation", orientation_str); rotated = gdk_pixbuf_apply_embedded_orientation(normal_pix); g_object_unref(normal_pix); normal_pix = rotated; } if(need_save) save_thumbnail_to_disk(task, normal_pix, task->normal_path); } if(task->flags & GENERATE_LARGE) { /* don't create thumbnails for images which are too small */ if(width <=256 && height <= 256) { large_pix = (GdkPixbuf*)g_object_ref(ori_pix); need_save = FALSE; } else { large_pix = scale_pix(ori_pix, 256); need_save = TRUE; } if(orientation_str) { GdkPixbuf* rotated; gdk_pixbuf_set_option(large_pix, "orientation", orientation_str); rotated = gdk_pixbuf_apply_embedded_orientation(large_pix); g_object_unref(large_pix); large_pix = rotated; } if(need_save) save_thumbnail_to_disk(task, large_pix, task->large_path); } g_object_unref(ori_pix); } g_input_stream_close(G_INPUT_STREAM(ins), NULL, NULL); } G_LOCK(queue); thumbnail_task_finish(task, normal_pix, large_pix); cur_generating = NULL; G_UNLOCK(queue); if(normal_pix) g_object_unref(normal_pix); if(large_pix) g_object_unref(large_pix); g_object_unref(gf); }