Re: Thumbnails for PostScript/PDF files
- From: Luis Villa <louie ximian com>
- To: nautilus-list gnome org
- Subject: Re: Thumbnails for PostScript/PDF files
- Date: 19 Jul 2002 11:21:55 -0400
This is a really cool idea for the 2.1.x branch when that opens :)
Luis
On Fri, 2002-07-19 at 09:44, Dave Malcolm wrote:
> Reasoning that one can never have enough eye-candy I've experimented with
> adding thumbnail generation for ps and PDF files to libnautilus-private.
>
> Attached is a patch against nautilus-2.0.0 (I have to use garnome rather than
> CVS I'm afraid). It's also the first time I've sent a patch so I suspect the
> format I've used is less than ideal.
>
> The patch invokes "gs" on any ps files it finds on local drives, attempting
> to create a temporary png of the first page of the document. This gets
> loaded and scaled down to thumbnail-size.
>
> The patch works (kind-of) but has numerous issues:
> - probably not secure
> - if the conversion fails the thumbnailing thread gets very confused, and
> tends to hang Nautilus
> - it blocks the thumbnailing thread; so if the conversion takes a long time
> you won't get any other thumbnails for ages... This is common for
> reasonable-sized input files.
> - there probably ought to be a speed tradeoff option for this kind of thing
> given the impact on CPU load of running gs.
> - it can work with PDF files as well, but I removed this as it failed too
> often (with the consequences as mentioned above)
> - the resulting thumbnails don't look as good as I hoped they might. They
> would probably look better if we embedded the image of the document content
> inside the frame that gets used for text files. But I'm not sure how to do
> that robustly.
> - gs spits out info to stdout (this can be suppressed by adding a "-dQUIET"
> when the command-line is generated, but it's useful for now for debugging)
>
> Ultimately I'd like later versions of Nautilus to have an extensible system
> for generating thumbnails, with support for many different file formats (not
> just image files), and I hope this is a step in the right direction. If
> nothing else it highlights some pitfalls :-)
>
> Any thoughts?
>
> Dave
> ----
>
> diff --recursive -x*.o -x*.server -U5 download/nautilus-2.0.0/libnautilus-private/nautilus-icon-factory.c work/nautilus-2.0.0/libnautilus-private/nautilus-icon-factory.c
> --- download/nautilus-2.0.0/libnautilus-private/nautilus-icon-factory.c Sun May 12 00:53:49 2002
> +++ work/nautilus-2.0.0/libnautilus-private/nautilus-icon-factory.c Thu Jul 18 19:54:46 2002
> @@ -1199,10 +1199,22 @@
> /* handle SVG files */
> if (uri == NULL && icon_name == NULL
> && nautilus_file_is_mime_type (file, "image/svg")) {
> uri = g_strdup (file_uri);
> }
> +
> + /* handle local ps files */
> + if (uri == NULL && icon_name == NULL ) {
> + if (nautilus_file_is_mime_type (file, "application/postscript")) {
> + if (is_local) {
> + uri = nautilus_get_thumbnail_uri (file);
> + if (uri == NULL) {
> + icon_name = g_strdup (ICON_NAME_THUMBNAIL_LOADING);
> + }
> + }
> + }
> + }
>
> /* Get the generic icon set for this file. */
> g_free (file_uri);
> if (icon_name == NULL) {
> icon_name = get_icon_name_for_file (file);
> diff --recursive -x*.o -x*.server -U5 download/nautilus-2.0.0/libnautilus-private/nautilus-thumbnails.c work/nautilus-2.0.0/libnautilus-private/nautilus-thumbnails.c
> --- download/nautilus-2.0.0/libnautilus-private/nautilus-thumbnails.c Sat Jun 1 20:35:14 2002
> +++ work/nautilus-2.0.0/libnautilus-private/nautilus-thumbnails.c Fri Jul 19 13:42:55 2002
> @@ -856,10 +856,129 @@
> }
> g_free (invalid_uri);
> }
>
>
> +
> +GdkPixbuf *
> +nautilus_thumbnail_invoke_gs (const char *uri)
> +{
> + /* This should only be called for local files.
> + We create a filename within the temp directory.
> + We then invoke "gs" on the uri, outputting the result as a 256 colour png to the
> + temporary filename.
> + Finally we load the png and delete the tempfile. */
> + int tmp_file_handle;
> + gchar *command_line, *local_path;
> + gchar *tmp_file = NULL;
> + GdkPixbuf *image = NULL;
> + gboolean success = FALSE;
> +
> +
> +#ifdef DEBUG_THUMBNAILS
> + g_message("(Thumbnail Thread) nautilus_thumbnail_invoke_gs (%s)\n",uri);
> +#endif
> +
> +#if 1
> + /* Obtain a temporary filename */
> + /* FIXME: is this method secure? */
> + tmp_file_handle = g_file_open_tmp (NULL, &tmp_file, NULL);
> +
> + if (-1 != tmp_file_handle) {
> + close(tmp_file_handle);
> + }
> +#else
> + tmp_file = g_strdup("/home/david/temp.png");
> +#endif
> +
> + if (tmp_file) {
> +#ifdef DEBUG_THUMBNAILS
> + g_message ("(Thumbnail Thread) tmp_file has name \"%s\"\n", tmp_file);
> +#endif
> +
> + /* This function should only be called for local URIs, hence it should be possible to convert from a URI into a regular filename */
> + local_path = gnome_vfs_get_local_path_from_uri (uri);
> +
> +#ifdef DEBUG_THUMBNAILS
> + g_message ("(Thumbnail Thread) local_path = \"%s\"\n", local_path);
> +#endif
> +
> +
> + if (local_path) {
> +
> + /* The command line invokes gs with the following options:
> + -sDEVICE=png256 specifies 256 colour png output. I experimented with png16m but it took much longer and with no improvement in quality.
> + -sOutputFile specifies the output filename
> + There follows the input filename
> + */
> + command_line = g_strdup_printf ("gs -dNOPAUSE -dBATCH -dSAFER -sDEVICE=png256 -sOutputFile=%s -dLastPage=1 %s",tmp_file, local_path);
> +
> +#ifdef DEBUG_THUMBNAILS
> + g_message ("(Thumbnail Thread) command_line = \"%s\"\n", command_line);
> +#endif
> +
> + /* FIXME: how much of a security risk is this? */
> + success = g_spawn_command_line_sync (command_line,
> + NULL, /* gchar **standard_output */
> + NULL, /* gchar **standard_error */
> + NULL, /* gint *exit_status */
> + NULL /* GError **error */);
> +
> + g_free (command_line);
> + g_free(local_path);
> + }
> +
> + if (success) {
> +#ifdef DEBUG_THUMBNAILS
> + g_message ("(Thumbnail Thread) command_line was a success; trying to load = \"%s\"\n", tmp_file);
> +#endif
> +
> + image = gdk_pixbuf_new_from_file (tmp_file, NULL);
> +
> +#ifdef DEBUG_THUMBNAILS
> + if (image) {
> + g_message ("(Thumbnail Thread) image was loaded OK (%d wide by %d high)\n", gdk_pixbuf_get_width (image), gdk_pixbuf_get_height (image) );
> + } else {
> + g_message ("(Thumbnail Thread) image failed to load\n");
> + }
> +
> + /* Explicitly delete the temp file to avoid filling obscure directories on the user's hard disk with large image files */
> + remove (tmp_file);
> +#endif
> + } else {
> +#ifdef DEBUG_THUMBNAILS
> + g_message ("(Thumbnail Thread) command_line was a failure\n");
> +#endif
> + }
> +
> + g_free (tmp_file);
> + }
> +
> + return image;
> +}
> +
> +GdkPixbuf *
> +nautilus_thumbnail_load_ps (const char *uri)
> +{
> + GdkPixbuf *image = NULL;
> +
> +#ifdef DEBUG_THUMBNAILS
> + g_message("(Thumbnail Thread) nautilus_thumbnail_load_ps (%s)\n",uri);
> +#endif
> +
> +#if 1
> + image = nautilus_thumbnail_invoke_gs (uri);
> +#else
> + image = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
> + 64, 256);
> +
> + gdk_pixbuf_fill (image, 0xff00ff);
> +#endif
> +
> + return image;
> +}
> +
> /* This creates one thumbnail in the thumbnail thread. */
> static void
> thumbnail_thread_make_thumbnail (NautilusThumbnailInfo *info)
> {
> GdkPixbuf* full_size_image = NULL;
> @@ -905,10 +1024,12 @@
> #ifdef HAVE_LIBJPEG
> } else if (eel_strcasecmp (info->mime_type, "image/jpeg") == 0) {
> full_size_image = nautilus_thumbnail_load_scaled_jpeg
> (info->image_uri, 96, 96);
> #endif
> + } else if (eel_strcasecmp (info->mime_type, "application/postscript") == 0) {
> + full_size_image = nautilus_thumbnail_load_ps (info->image_uri);
> } else {
> full_size_image = eel_gdk_pixbuf_load (info->image_uri);
> }
>
> /* If we have managed to create a pixbuf from the image, scale it to
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]