Subject: Re: bug#10112: ImageMagick doesn't display some image formats

From: Juri Linkov <[email-masked]>
Date: Thu, 24 Nov 2011 21:09:12 +0200

> So at least moving `MagickSetResolution' a few lines below and calling after
> `MagickPingImage' will allow the read-only images to be correctly displayed:

Patch installed.

> Read-only formats like .dot have only read-functions, but not write-functions
> (the error being "no encode delegate for this image format").

I think we should expose ImageMagick error messages to Emacs.
The patch below adds a new function `imagemagick_error' that is
called in places where the ImageMagick returns `MagickFalse' status.
It puts the error message to the *Messages* buffer.

This function helps to understand why ImageMagick fails to display
images.  For instance, now with more informative error message
it reveals why Gnus can't display some ImageMagick formats
demonstrated at http://debbugs.gnu.org/9044#41
The error message is:

  no decode delegate for this image format `' @ error/blob.c/BlobToImage/349

This means that ImageMagick is unable to read a TGA image from Blob,
i.e. when the image is defined by the :data tag like Gnus does.
OTOH, when a TGA image is defined by the :file tag, then ImageMagick
can read it and display correctly.

We could try to write an image to a temporary file before displaying it,
but I'm not sure if it's worth the trouble to overcome shortcomings
of ImageMagick.

=== modified file 'src/image.c'
--- src/image.c	2011-11-24 19:02:39 +0000
+++ src/image.c	2011-11-24 19:08:18 +0000
@@ -7564,6 +7564,19 @@ (at your option) any later version.
 					    MagickPixelPacket *);
 #endif
 
+static void
+imagemagick_error (MagickWand *wand)
+{
+  char *description;
+  ExceptionType severity;
+
+  description = MagickGetException (wand,&severity);
+  image_error ("ImageMagick error: %s",
+	       make_string (description, strlen (description)),
+	       Qnil);
+  description = (char *) MagickRelinquishMemory (description);
+}
+
 /* Helper function for imagemagick_load, which does the actual loading
    given contents and size, apart from frame and image structures,
    passed from imagemagick_load.  Uses librimagemagick to do most of
@@ -7628,6 +7641,13 @@ (at your option) any later version.
       status = MagickPingImageBlob (ping_wand, contents, size);
     }
 
+  if (status == MagickFalse)
+    {
+      imagemagick_error (ping_wand);
+      DestroyMagickWand (ping_wand);
+      return 0;
+    }
+
   MagickSetResolution (ping_wand, 2, 2);
 
   if (! (0 <= ino && ino < MagickGetNumberImages (ping_wand)))
@@ -7669,7 +7689,10 @@ (at your option) any later version.
     {
       image_wand = NewMagickWand ();
       if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse)
-	goto imagemagick_error;
+	{
+	  imagemagick_error (image_wand);
+	  goto imagemagick_error;
+	}
     }
 
   /* If width and/or height is set in the display spec assume we want
@@ -7697,6 +7720,7 @@ (at your option) any later version.
       if (status == MagickFalse)
 	{
 	  image_error ("Imagemagick scale failed", Qnil, Qnil);
+	  imagemagick_error (image_wand);
 	  goto imagemagick_error;
 	}
     }
@@ -7751,6 +7775,7 @@ (at your option) any later version.
       if (status == MagickFalse)
         {
           image_error ("Imagemagick image rotate failed", Qnil, Qnil);
+	  imagemagick_error (image_wand);
           goto imagemagick_error;
         }
     }