Enable giving hints to ImageMagick via :content-type
authorLars Magne Ingebrigtsen <larsi@gnus.org>
Tue, 13 Aug 2013 17:45:34 +0000 (19:45 +0200)
committerLars Magne Ingebrigtsen <larsi@gnus.org>
Tue, 13 Aug 2013 17:45:34 +0000 (19:45 +0200)
2013-08-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>

* image.el (image-content-type-suffixes): New variable.

2013-08-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>

* image.c (imagemagick_filename_hint): New function to possibly
apply `image-content-type-suffixes'.
(imagemagick_load_image): Use it.

doc/lispref/ChangeLog
doc/lispref/display.texi
etc/NEWS
lisp/ChangeLog
lisp/image.el
src/ChangeLog
src/image.c

index 42b9600..0d7d13e 100644 (file)
@@ -1,3 +1,8 @@
+2013-08-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * display.texi (ImageMagick Images): Mention :content-type and
+       `image-content-type-suffixes'.
+
 2013-08-13  Xue Fuqiao  <xfq.free@gmail.com>
 
        * positions.texi (Word Motion): Remove redundant sentence.
index 6b8d241..f2fd51e 100644 (file)
@@ -4664,6 +4664,14 @@ and if @code{:height} is set it will have precedence over
 wish.  @code{:max-width} and @code{:max-height} will always preserve
 the aspect ratio.
 
+@item :content-type
+ImageMagick tries to auto-detect the image type, but it isn't always
+able to.  By using @code{:content-type}, we can give ImageMagick a
+hint to try to help it.  It's used in conjuction with the
+@code{image-content-type-suffixes} variable, which provides a mapping
+from content types to file name suffixes.  This is then given to
+ImageMagick as a file name hint.
+
 @item :rotation
 Specifies a rotation angle in degrees.
 
index 715f790..80310ea 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -896,6 +896,10 @@ treated as images.
 *** ImageMagick images now support the :max-width and :max-height
 keywords.
 
+*** Some data types aren't auto-detected by ImageMagick.  Adding
+:content-type to `create-image' may help if the content type is in the
+new variable `image-content-type-suffixes'.
+
 ** Minibuffer
 
 *** In minibuffer filename prompts, `C-M-f' and `C-M-b' now move to the
index 11e5e91..c6f11fe 100644 (file)
@@ -1,3 +1,7 @@
+2013-08-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * image.el (image-content-type-suffixes): New variable.
+
 2013-08-13  Fabián Ezequiel Gallina  <fgallina@gnu.org>
 
        * progmodes/python.el (python-imenu--build-tree)
index 804dc3a..de69490 100644 (file)
@@ -99,6 +99,14 @@ AUTODETECT can be
  - maybe  auto-detect only if the image type is available
            (see `image-type-available-p').")
 
+(defvar image-content-type-suffixes
+  '((image/x-icon "ico"))
+  "Alist of MIME Content-Type headers to file name suffixes.
+This is used as a hint by the ImageMagick library when detecting
+image types.  If `create-image' is called with a :content-type
+matching found in this alist, the ImageMagick library will be
+told that the data would have this suffix if saved to a file.")
+
 (defcustom image-load-path
   (list (file-name-as-directory (expand-file-name "images" data-directory))
         'data-directory 'load-path)
index 1cb8002..c60b2c1 100644 (file)
@@ -1,3 +1,9 @@
+2013-08-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * image.c (imagemagick_filename_hint): New function to possibly
+       apply `image-content-type-suffixes'.
+       (imagemagick_load_image): Use it.
+
 2013-08-13  Eli Zaretskii  <eliz@gnu.org>
 
        * decompress.c (Fzlib_decompress_region) [WINDOWSNT]: Return Qnil
index ae38b4f..35cbbb6 100644 (file)
@@ -551,6 +551,7 @@ static Lisp_Object QCheuristic_mask;
 static Lisp_Object QCcolor_symbols;
 static Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry;
 static Lisp_Object QCcrop, QCrotation;
+static Lisp_Object QCcontent_type;
 
 /* Other symbols.  */
 
@@ -7740,6 +7741,7 @@ enum imagemagick_keyword_index
     IMAGEMAGICK_WIDTH,
     IMAGEMAGICK_MAX_HEIGHT,
     IMAGEMAGICK_MAX_WIDTH,
+    IMAGEMAGICK_CONTENT_TYPE,
     IMAGEMAGICK_ROTATION,
     IMAGEMAGICK_CROP,
     IMAGEMAGICK_LAST
@@ -7764,6 +7766,7 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
     {":width",         IMAGE_INTEGER_VALUE,                    0},
     {":max-height",    IMAGE_INTEGER_VALUE,                    0},
     {":max-width",     IMAGE_INTEGER_VALUE,                    0},
+    {":content-type",  IMAGE_SYMBOL_VALUE,                     0},
     {":rotation",      IMAGE_NUMBER_VALUE,                     0},
     {":crop",          IMAGE_DONT_CHECK_VALUE_TYPE,            0}
   };
@@ -7842,6 +7845,30 @@ imagemagick_error (MagickWand *wand)
   description = (char *) MagickRelinquishMemory (description);
 }
 
+/* Possibly give ImageMagick some extra help to determine the image
+   type by supplying a "dummy" filename based on the Content-Type. */
+
+static char*
+imagemagick_filename_hint (Lisp_Object spec)
+{
+  Lisp_Object content_type = image_spec_value (spec, QCcontent_type, NULL);
+  Lisp_Object symbol = intern ("image-content-type-suffixes");
+  Lisp_Object suffix;
+  char *name, *prefix = "/tmp/foo.";
+
+  if (NILP (Fboundp (symbol)))
+    return NULL;
+
+  suffix = Fcar (Fcdr (Fassq (content_type, Fsymbol_value (symbol))));
+  if (! STRINGP (suffix))
+    return NULL;
+
+  name = xmalloc (strlen (prefix) + SBYTES (suffix) + 1);
+  strcpy(name, prefix);
+  strcat(name, SDATA (suffix));
+  return name;
+}
+
 /* 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
@@ -7875,6 +7902,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
   int desired_width, desired_height;
   double rotation;
   int pixelwidth;
+  char *filename_hint = NULL;
 
   /* Handle image index for image types who can contain more than one image.
      Interface :index is same as for GIF.  First we "ping" the image to see how
@@ -7888,6 +7916,12 @@ imagemagick_load_image (struct frame *f, struct image *img,
   ping_wand = NewMagickWand ();
   /* MagickSetResolution (ping_wand, 2, 2);   (Bug#10112)  */
 
+  if (! filename)
+    filename_hint = imagemagick_filename_hint (img->spec);
+
+  if (filename_hint)
+    MagickSetFilename (ping_wand, filename_hint);
+
   status = filename
     ? MagickPingImage (ping_wand, filename)
     : MagickPingImageBlob (ping_wand, contents, size);
@@ -7920,6 +7954,9 @@ imagemagick_load_image (struct frame *f, struct image *img,
 
   image_wand = NewMagickWand ();
 
+  if (filename_hint)
+    MagickSetFilename (image_wand, filename_hint);
+
   if ((filename
        ? MagickReadImage (image_wand, filename)
        : MagickReadImageBlob (image_wand, contents, size))
@@ -8163,11 +8200,16 @@ imagemagick_load_image (struct frame *f, struct image *img,
   /* `MagickWandTerminus' terminates the imagemagick environment.  */
   MagickWandTerminus ();
 
+  if (filename_hint)
+    free (filename_hint);
+
   return 1;
 
  imagemagick_error:
   DestroyMagickWand (image_wand);
   if (bg_wand) DestroyPixelWand (bg_wand);
+  if (filename_hint)
+    free (filename_hint);
 
   MagickWandTerminus ();
   /* TODO more cleanup.  */
@@ -9105,6 +9147,7 @@ non-numeric, there is no explicit limit on the size of images.  */);
   DEFSYM (Qpostscript, "postscript");
   DEFSYM (QCmax_width, ":max-width");
   DEFSYM (QCmax_height, ":max-height");
+  DEFSYM (QCcontent_type, ":content-type");
 #ifdef HAVE_GHOSTSCRIPT
   ADD_IMAGE_TYPE (Qpostscript);
   DEFSYM (QCloader, ":loader");