Re: Thumbnails for PostScript/PDF files



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]