* image.c (imagemagick_load_image): Don't use garbage pointer image_wand.
[bpt/emacs.git] / src / image.c
index 11c6aa8..3d17244 100644 (file)
@@ -67,6 +67,7 @@ typedef struct x_bitmap_record Bitmap_Record;
 
 
 #ifdef HAVE_NTGUI
+#include "w32.h"
 #include "w32term.h"
 
 /* W32_TODO : Color tables on W32.  */
@@ -137,7 +138,7 @@ static void free_color_table (void);
 static unsigned long *colors_in_color_table (int *n);
 static unsigned long lookup_pixel_color (struct frame *f, unsigned long p);
 #endif
-INFUN (Finit_image_library, 2);
+static Lisp_Object Finit_image_library (Lisp_Object, Lisp_Object);
 
 /* Code to deal with bitmaps.  Bitmaps are referenced by their bitmap
    id, which is just an int that this section returns.  Bitmaps are
@@ -556,10 +557,6 @@ x_create_bitmap_mask (struct frame *f, int id)
 
 static struct image_type *image_types;
 
-/* Cache for delayed-loading image types.  */
-
-static Lisp_Object Vimage_type_cache;
-
 /* The symbol `xbm' which is used as the type symbol for XBM images.  */
 
 static Lisp_Object Qxbm;
@@ -587,9 +584,12 @@ static void x_laplace (struct frame *, struct image *);
 static void x_emboss (struct frame *, struct image *);
 static int x_build_heuristic_mask (struct frame *, struct image *,
                                    Lisp_Object);
-
+#ifdef HAVE_NTGUI
 #define CACHE_IMAGE_TYPE(type, status) \
-  do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
+  do { Vlibrary_cache = Fcons (Fcons (type, status), Vlibrary_cache); } while (0)
+#else
+#define CACHE_IMAGE_TYPE(type, status)
+#endif
 
 #define ADD_IMAGE_TYPE(type) \
   do { Vimage_types = Fcons (type, Vimage_types); } while (0)
@@ -623,7 +623,7 @@ define_image_type (struct image_type *type, int loaded)
 /* Look up image type SYMBOL, and return a pointer to its image_type
    structure.  Value is null if SYMBOL is not a known image type.  */
 
-static INLINE struct image_type *
+static inline struct image_type *
 lookup_image_type (Lisp_Object symbol)
 {
   struct image_type *type;
@@ -982,7 +982,6 @@ or omitted means use the selected frame.  */)
                 Image type independent image structures
  ***********************************************************************/
 
-static struct image *make_image (Lisp_Object spec, unsigned hash);
 static void free_image (struct frame *f, struct image *img);
 static int check_image_size (struct frame *f, int width, int height);
 
@@ -991,7 +990,7 @@ static int check_image_size (struct frame *f, int width, int height);
    SPEC.  SPEC has a hash value of HASH.  */
 
 static struct image *
-make_image (Lisp_Object spec, unsigned int hash)
+make_image (Lisp_Object spec, EMACS_UINT hash)
 {
   struct image *img = (struct image *) xmalloc (sizeof *img);
   Lisp_Object file = image_spec_value (spec, QCfile, NULL);
@@ -1388,7 +1387,6 @@ x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name,
                             Image Cache
  ***********************************************************************/
 
-static struct image *search_image_cache (struct frame *, Lisp_Object, unsigned);
 static void cache_image (struct frame *f, struct image *img);
 static void postprocess_image (struct frame *, struct image *);
 
@@ -1414,7 +1412,7 @@ make_image_cache (void)
 /* Find an image matching SPEC in the cache, and return it.  If no
    image is found, return NULL.  */
 static struct image *
-search_image_cache (struct frame *f, Lisp_Object spec, unsigned int hash)
+search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash)
 {
   struct image *img;
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
@@ -1523,7 +1521,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
        {
          /* Free cache based on timestamp.  */
          EMACS_TIME t;
-         unsigned long old;
+         time_t old;
          int delay, nimages = 0;
 
          for (i = 0; i < c->used; ++i)
@@ -1714,7 +1712,7 @@ int
 lookup_image (struct frame *f, Lisp_Object spec)
 {
   struct image *img;
-  unsigned hash;
+  EMACS_UINT hash;
   EMACS_TIME now;
 
   /* F must be a window-system frame, and SPEC must be a valid image
@@ -1892,7 +1890,7 @@ mark_image_cache (struct image_cache *c)
 #ifdef HAVE_NTGUI
 
 /* Macro for defining functions that will be loaded from image DLLs.  */
-#define DEF_IMGLIB_FN(rettype,func,args) rettype (FAR CDECL *fn_##func)args
+#define DEF_IMGLIB_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
 
 /* Macro for loading those image functions from the library.  */
 #define LOAD_IMGLIB_FN(lib,func) {                                     \
@@ -1900,34 +1898,6 @@ mark_image_cache (struct image_cache *c)
     if (!fn_##func) return 0;                                          \
   }
 
-/* Load a DLL implementing an image type.
-   The argument LIBRARIES is usually the variable
-   `dynamic-library-alist', which associates a symbol, identifying
-   an external DLL library, to a list of possible filenames.
-   The function returns NULL if no library could be loaded for
-   the given symbol, or if the library was previously loaded;
-   else the handle of the DLL.  */
-static HMODULE
-w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
-{
-  HMODULE library = NULL;
-
-  if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
-    {
-      Lisp_Object dlls = Fassq (type, libraries);
-
-      if (CONSP (dlls))
-        for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
-          {
-            CHECK_STRING_CAR (dlls);
-            if (library = LoadLibrary (SDATA (XCAR (dlls))))
-              break;
-          }
-    }
-
-  return library;
-}
-
 #endif /* HAVE_NTGUI */
 
 static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
@@ -2142,9 +2112,6 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int he
                              File Handling
  ***********************************************************************/
 
-static unsigned char *slurp_file (char *, int *);
-
-
 /* Find image file FILE.  Look in data-directory/images, then
    x-bitmap-file-path.  Value is the encoded full name of the file
    found, or nil if not found.  */
@@ -2181,7 +2148,7 @@ x_find_image_file (Lisp_Object file)
    occurred.  *SIZE is set to the size of the file.  */
 
 static unsigned char *
-slurp_file (char *file, int *size)
+slurp_file (char *file, ptrdiff_t *size)
 {
   FILE *fp = NULL;
   unsigned char *buf = NULL;
@@ -2189,6 +2156,7 @@ slurp_file (char *file, int *size)
 
   if (stat (file, &st) == 0
       && (fp = fopen (file, "rb")) != NULL
+      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
       && (buf = (unsigned char *) xmalloc (st.st_size),
          fread (buf, 1, st.st_size, fp) == st.st_size))
     {
@@ -2359,7 +2327,7 @@ xbm_image_p (Lisp_Object object)
          int i;
 
          /* Number of elements of the vector must be >= height.  */
-         if (XVECTOR (data)->size < height)
+         if (ASIZE (data) < height)
            return 0;
 
          /* Each string or bool-vector in data must be large enough
@@ -2844,7 +2812,7 @@ xbm_load (struct frame *f, struct image *img)
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
@@ -3779,7 +3747,7 @@ xpm_put_color_table_h (Lisp_Object color_table,
                        Lisp_Object color)
 {
   struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
-  unsigned hash_code;
+  EMACS_UINT hash_code;
   Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
 
   hash_lookup (table, chars, &hash_code);
@@ -4069,7 +4037,7 @@ xpm_load (struct frame *f,
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
@@ -5051,6 +5019,7 @@ pbm_read_file (file, size)
 
   if (stat (SDATA (file), &st) == 0
       && (fp = fopen (SDATA (file), "rb")) != NULL
+      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
       && (buf = (char *) xmalloc (st.st_size),
          fread (buf, 1, st.st_size, fp) == st.st_size))
     {
@@ -5085,7 +5054,7 @@ pbm_load (struct frame *f, struct image *img)
   enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
   unsigned char *contents = NULL;
   unsigned char *end, *p;
-  int size;
+  ptrdiff_t size;
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
 
@@ -5452,7 +5421,6 @@ init_png_functions (Lisp_Object libraries)
 {
   HMODULE library;
 
-  /* Try loading libpng under probable names.  */
   if (!(library = w32_delayed_load (libraries, Qpng)))
     return 0;
 
@@ -7106,22 +7074,19 @@ static const int interlace_increment[] = {8, 8, 4, 2};
 static int
 gif_load (struct frame *f, struct image *img)
 {
-  Lisp_Object file, specified_file;
-  Lisp_Object specified_data;
-  int rc, width, height, x, y, i;
-  boolean transparent_p = 0;
+  Lisp_Object file;
+  int rc, width, height, x, y, i, j;
   XImagePtr ximg;
   ColorMapObject *gif_color_map;
   unsigned long pixel_colors[256];
   GifFileType *gif;
-  Lisp_Object image;
-  int ino, image_height, image_width;
+  int image_height, image_width;
   gif_memory_source memsrc;
-  unsigned char *raster;
-  unsigned int transparency_color_index IF_LINT (= 0);
-
-  specified_file = image_spec_value (img->spec, QCfile, NULL);
-  specified_data = image_spec_value (img->spec, QCdata, NULL);
+  Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+  Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
+  Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL);
+  unsigned long bgcolor = 0;
+  int idx;
 
   if (NILP (specified_data))
     {
@@ -7172,40 +7137,31 @@ gif_load (struct frame *f, struct image *img)
 
   /* Read entire contents.  */
   rc = fn_DGifSlurp (gif);
-  if (rc == GIF_ERROR)
+  if (rc == GIF_ERROR || gif->ImageCount <= 0)
     {
       image_error ("Error reading `%s'", img->spec, Qnil);
       fn_DGifCloseFile (gif);
       return 0;
     }
 
-  image = image_spec_value (img->spec, QCindex, NULL);
-  ino = INTEGERP (image) ? XFASTINT (image) : 0;
-  if (ino >= gif->ImageCount)
-    {
-      image_error ("Invalid image number `%s' in image `%s'",
-                  image, img->spec);
-      fn_DGifCloseFile (gif);
-      return 0;
-    }
-
-  for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++)
-    if ((gif->SavedImages[ino].ExtensionBlocks[i].Function
-        == GIF_LOCAL_DESCRIPTOR_EXTENSION)
-       && gif->SavedImages[ino].ExtensionBlocks[i].ByteCount == 4
-       /* Transparency enabled?  */
-       && gif->SavedImages[ino].ExtensionBlocks[i].Bytes[0] & 1)
+  /* Which sub-image are we to display?  */
+  {
+    Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL);
+    idx = INTEGERP (image_number) ? XFASTINT (image_number) : 0;
+    if (idx < 0 || idx >= gif->ImageCount)
       {
-       transparent_p = 1;
-       transparency_color_index
-         = (unsigned char) gif->SavedImages[ino].ExtensionBlocks[i].Bytes[3];
+       image_error ("Invalid image number `%s' in image `%s'",
+                    image_number, img->spec);
+       fn_DGifCloseFile (gif);
+       return 0;
       }
+  }
 
-  img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
-  img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
-  image_height = gif->SavedImages[ino].ImageDesc.Height;
+  img->corners[TOP_CORNER] = gif->SavedImages[idx].ImageDesc.Top;
+  img->corners[LEFT_CORNER] = gif->SavedImages[idx].ImageDesc.Left;
+  image_height = gif->SavedImages[idx].ImageDesc.Height;
   img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
-  image_width = gif->SavedImages[ino].ImageDesc.Width;
+  image_width = gif->SavedImages[idx].ImageDesc.Width;
   img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
 
   width = img->width = max (gif->SWidth,
@@ -7229,44 +7185,10 @@ gif_load (struct frame *f, struct image *img)
       return 0;
     }
 
-  /* Allocate colors.  */
-  gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
-  if (!gif_color_map)
-    gif_color_map = gif->SColorMap;
-  init_color_table ();
-  memset (pixel_colors, 0, sizeof pixel_colors);
-
-  if (gif_color_map)
-    for (i = 0; i < gif_color_map->ColorCount; ++i)
-      {
-       if (transparent_p && transparency_color_index == i)
-         {
-           Lisp_Object specified_bg
-             = image_spec_value (img->spec, QCbackground, NULL);
-           pixel_colors[i] = STRINGP (specified_bg)
-             ? x_alloc_image_color (f, img, specified_bg,
-                                    FRAME_BACKGROUND_PIXEL (f))
-             : FRAME_BACKGROUND_PIXEL (f);
-         }
-       else
-         {
-           int r = gif_color_map->Colors[i].Red << 8;
-           int g = gif_color_map->Colors[i].Green << 8;
-           int b = gif_color_map->Colors[i].Blue << 8;
-           pixel_colors[i] = lookup_rgb_color (f, r, g, b);
-         }
-      }
-
-#ifdef COLOR_TABLE_SUPPORT
-  img->colors = colors_in_color_table (&img->ncolors);
-  free_color_table ();
-#endif /* COLOR_TABLE_SUPPORT */
-
-  /* Clear the part of the screen image that are not covered by
-     the image from the GIF file.  Full animated GIF support
-     requires more than can be done here (see the gif89 spec,
-     disposal methods).  Let's simply assume that the part
-     not covered by a sub-image is in the frame's background color.  */
+  /* Clear the part of the screen image not covered by the image.
+     Full animated GIF support requires more here (see the gif89 spec,
+     disposal methods).  Let's simply assume that the part not covered
+     by a sub-image is in the frame's background color.  */
   for (y = 0; y < img->corners[TOP_CORNER]; ++y)
     for (x = 0; x < width; ++x)
       XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
@@ -7283,55 +7205,119 @@ gif_load (struct frame *f, struct image *img)
        XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
     }
 
-  /* Read the GIF image into the X image.  We use a local variable
-     `raster' here because RasterBits below is a char *, and invites
-     problems with bytes >= 0x80.  */
-  raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
-
-  if (gif->SavedImages[ino].ImageDesc.Interlace)
-    {
-      int pass;
-      int row = interlace_start[0];
+  /* Read the GIF image into the X image.   */
 
-      pass = 0;
+  /* FIXME: With the current implementation, loading an animated gif
+     is quadratic in the number of animation frames, since each frame
+     is a separate struct image.  We must provide a way for a single
+     gif_load call to construct and save all animation frames.  */
 
-      for (y = 0; y < image_height; y++)
+  init_color_table ();
+  if (STRINGP (specified_bg))
+    bgcolor = x_alloc_image_color (f, img, specified_bg,
+                                  FRAME_BACKGROUND_PIXEL (f));
+  for (j = 0; j <= idx; ++j)
+    {
+      /* We use a local variable `raster' here because RasterBits is a
+        char *, which invites problems with bytes >= 0x80.  */
+      struct SavedImage *subimage = gif->SavedImages + j;
+      unsigned char *raster = (unsigned char *) subimage->RasterBits;
+      int transparency_color_index = -1;
+      int disposal = 0;
+
+      /* Find the Graphic Control Extension block for this sub-image.
+        Extract the disposal method and transparency color.  */
+      for (i = 0; i < subimage->ExtensionBlockCount; i++)
        {
-         if (row >= image_height)
-           {
-             row = interlace_start[++pass];
-             while (row >= image_height)
-               row = interlace_start[++pass];
-           }
+         ExtensionBlock *extblock = subimage->ExtensionBlocks + i;
 
-         for (x = 0; x < image_width; x++)
+         if ((extblock->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION)
+             && extblock->ByteCount == 4
+             && extblock->Bytes[0] & 1)
            {
-             int c = raster[(y * image_width) + x];
-             XPutPixel (ximg, x + img->corners[LEFT_CORNER],
-                        row + img->corners[TOP_CORNER], pixel_colors[c]);
+             /* From gif89a spec: 1 = "keep in place", 2 = "restore
+                to background".  Treat any other value like 2.  */
+             disposal = (extblock->Bytes[0] >> 2) & 7;
+             transparency_color_index = (unsigned char) extblock->Bytes[3];
+             break;
            }
-
-         row += interlace_increment[pass];
        }
-    }
-  else
-    {
-      for (y = 0; y < image_height; ++y)
-       for (x = 0; x < image_width; ++x)
+
+      /* We can't "keep in place" the first subimage.  */
+      if (j == 0)
+       disposal = 2;
+
+      /* Allocate subimage colors.  */
+      memset (pixel_colors, 0, sizeof pixel_colors);
+      gif_color_map = subimage->ImageDesc.ColorMap;
+      if (!gif_color_map)
+       gif_color_map = gif->SColorMap;
+
+      if (gif_color_map)
+       for (i = 0; i < gif_color_map->ColorCount; ++i)
          {
-           int c = raster[y * image_width + x];
-           XPutPixel (ximg, x + img->corners[LEFT_CORNER],
-                      y + img->corners[TOP_CORNER], pixel_colors[c]);
+           if (transparency_color_index == i)
+             pixel_colors[i] = STRINGP (specified_bg)
+               ? bgcolor : FRAME_BACKGROUND_PIXEL (f);
+           else
+             {
+               int r = gif_color_map->Colors[i].Red << 8;
+               int g = gif_color_map->Colors[i].Green << 8;
+               int b = gif_color_map->Colors[i].Blue << 8;
+               pixel_colors[i] = lookup_rgb_color (f, r, g, b);
+             }
          }
+
+      /* Apply the pixel values.  */
+      if (gif->SavedImages[j].ImageDesc.Interlace)
+       {
+         int row, pass;
+
+         for (y = 0, row = interlace_start[0], pass = 0;
+              y < image_height;
+              y++, row += interlace_increment[pass])
+           {
+             if (row >= image_height)
+               {
+                 row = interlace_start[++pass];
+                 while (row >= image_height)
+                   row = interlace_start[++pass];
+               }
+
+             for (x = 0; x < image_width; x++)
+               {
+                 int c = raster[y * image_width + x];
+                 if (transparency_color_index != c || disposal != 1)
+                   XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+                              row + img->corners[TOP_CORNER], pixel_colors[c]);
+               }
+           }
+       }
+      else
+       {
+         for (y = 0; y < image_height; ++y)
+           for (x = 0; x < image_width; ++x)
+             {
+               int c = raster[y * image_width + x];
+               if (transparency_color_index != c || disposal != 1)
+                 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+                            y + img->corners[TOP_CORNER], pixel_colors[c]);
+             }
+       }
     }
 
+#ifdef COLOR_TABLE_SUPPORT
+  img->colors = colors_in_color_table (&img->ncolors);
+  free_color_table ();
+#endif /* COLOR_TABLE_SUPPORT */
+
   /* Save GIF image extension data for `image-metadata'.
      Format is (count IMAGES extension-data (FUNCTION "BYTES" ...)).  */
   img->data.lisp_val = Qnil;
-  if (gif->SavedImages[ino].ExtensionBlockCount > 0)
+  if (gif->SavedImages[idx].ExtensionBlockCount > 0)
     {
-      ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
-      for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
+      ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks;
+      for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++)
        /* Append (... FUNCTION "BYTES") */
        img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
                                    Fcons (make_number (ext->Function),
@@ -7381,6 +7367,10 @@ gif_load (struct frame *f, struct image *img)
 
 Lisp_Object Qimagemagick;
 
+static int imagemagick_image_p (Lisp_Object);
+static int imagemagick_load (struct frame *, struct image *);
+static void imagemagick_clear_image (struct frame *, struct image *);
+
 /* Indices of image specification fields in imagemagick_format.  */
 
 enum imagemagick_keyword_index
@@ -7423,6 +7413,18 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
     {":crop",          IMAGE_DONT_CHECK_VALUE_TYPE,            0}
   };
 
+/* Structure describing the image type for any image handled via
+   ImageMagick.  */
+
+static struct image_type imagemagick_type =
+  {
+    &Qimagemagick,
+    imagemagick_image_p,
+    imagemagick_load,
+    imagemagick_clear_image,
+    NULL
+  };
+
 /* Free X resources of imagemagick image IMG which is used on frame F.  */
 
 static void
@@ -7454,38 +7456,29 @@ imagemagick_image_p (Lisp_Object object)
 #define DrawRectangle DrawRectangleGif
 #include <wand/MagickWand.h>
 
-/* imagemagick_load_image is a helper function for imagemagick_load,
-   which does the actual loading given contents and size, apart from
-   frame and image structures, passed from imagemagick_load.
+/* 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
+   the image processing.
 
-   Uses librimagemagick to do most of the image processing.
+   F is a pointer to the Emacs frame; IMG to the image structure to
+   prepare; CONTENTS is the string containing the IMAGEMAGICK data to
+   be parsed; SIZE is the number of bytes of data; and FILENAME is
+   either the file name or the image data.
 
-   Return non-zero if successful.
-*/
+   Return non-zero if successful.  */
 
 static int
-imagemagick_load_image (/* Pointer to emacs frame structure.  */
-                        struct frame *f,
-                        /* Pointer to emacs image structure.  */
-                        struct image *img,
-                        /* String containing the IMAGEMAGICK data to
-                           be parsed.  */
-                        unsigned char *contents,
-                        /* Size of data in bytes.  */
-                        unsigned int size,
-                        /* Filename, either pass filename or
-                           contents/size.  */
-                        unsigned char *filename)
+imagemagick_load_image (struct frame *f, struct image *img,
+                       unsigned char *contents, unsigned int size,
+                       char *filename)
 {
   unsigned long width;
   unsigned long height;
 
-  MagickBooleanType
-    status;
+  MagickBooleanType status;
 
   XImagePtr ximg;
-  Lisp_Object specified_bg;
-  XColor background;
   int x;
   int y;
 
@@ -7496,7 +7489,7 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
   MagickPixelPacket  pixel;
   Lisp_Object image;
   Lisp_Object value;
-  Lisp_Object crop, geometry;
+  Lisp_Object crop;
   long ino;
   int desired_width, desired_height;
   double rotation;
@@ -7543,8 +7536,8 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
 
   DestroyMagickWand (ping_wand);
 
-  /* Now, after pinging, we know how many images are inside the
-     file.  If it's not a bundle, the number is one.  */
+  /* Now we know how many images are inside the file.  If it's not a
+     bundle, the number is one.  */
 
   if (filename != NULL)
     {
@@ -7557,23 +7550,18 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
       im_image = ReadImage (image_info, exception);
       DestroyExceptionInfo (exception);
 
-      if (im_image != NULL)
-       {
-         image_wand = NewMagickWandFromImage (im_image);
-          DestroyImage(im_image);
-         status = MagickTrue;
-       }
-      else
-       status = MagickFalse;
+      if (im_image == NULL)
+       goto imagemagick_no_wand;
+      image_wand = NewMagickWandFromImage (im_image);
+      DestroyImage(im_image);
     }
   else
     {
       image_wand = NewMagickWand ();
-      status = MagickReadImageBlob (image_wand, contents, size);
+      if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse)
+       goto imagemagick_error;
     }
 
-  if (status == MagickFalse) goto imagemagick_error;
-
   /* If width and/or height is set in the display spec assume we want
      to scale to those values.  If either h or w is unspecified, the
      unspecified should be calculated from the specified to preserve
@@ -7614,7 +7602,7 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
          than the alternatives, but it still reads the entire image into memory
          before croping, which is aparently difficult to avoid when using
          imagemagick.  */
-      int w, h, x, y;
+      int w, h;
       w = XFASTINT (XCAR (crop));
       crop = XCDR (crop);
       if (CONSP (crop) && INTEGERP (XCAR (crop)))
@@ -7657,8 +7645,8 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
         }
     }
 
-  /* Finaly we are done manipulating the image, figure out resulting
-     width, height, and then transfer ownerwship to Emacs.  */
+  /* Finally we are done manipulating the image.  Figure out the
+     resulting width/height and transfer ownerwship to Emacs.  */
   height = MagickGetImageHeight (image_wand);
   width = MagickGetImageWidth (image_wand);
 
@@ -7728,7 +7716,7 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
          method is also well tested. Some aspects of this method are
          ad-hoc and needs to be more researched. */
       int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/
-      char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
+      const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
       /* Try to create a x pixmap to hold the imagemagick pixmap.  */
       if (!x_create_x_image_and_pixmap (f, width, height, imagedepth,
                                         &ximg, &img->pixmap))
@@ -7801,6 +7789,7 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
 
  imagemagick_error:
   DestroyMagickWand (image_wand);
+ imagemagick_no_wand:
   MagickWandTerminus ();
   /* TODO more cleanup.  */
   image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
@@ -7813,8 +7802,7 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
    the prototype thus needs to be compatible with that structure.  */
 
 static int
-imagemagick_load (struct frame *f,
-                  struct image *img)
+imagemagick_load (struct frame *f, struct image *img)
 {
   int success_p = 0;
   Lisp_Object file_name;
@@ -7831,7 +7819,7 @@ imagemagick_load (struct frame *f,
          image_error ("Cannot find image file `%s'", file_name, Qnil);
          return 0;
        }
-      success_p = imagemagick_load_image (f, img, 0, 0, SDATA (file));
+      success_p = imagemagick_load_image (f, img, 0, 0, SSDATA (file));
     }
   /* Else its not a file, its a lisp object.  Load the image from a
      lisp object rather than a file.  */
@@ -7852,36 +7840,18 @@ imagemagick_load (struct frame *f,
   return success_p;
 }
 
-/* Structure describing the image type `imagemagick'.  Its the same
-   type of structure defined for all image formats, handled by Emacs
-   image functions.  See struct image_type in dispextern.h.  */
+DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0,
+       doc: /* Return a list of image types supported by ImageMagick.
+Each entry in this list is a symbol named after an ImageMagick format
+tag.  See the ImageMagick manual for a list of ImageMagick formats and
+their descriptions (http://www.imagemagick.org/script/formats.php).
 
-static struct image_type imagemagick_type =
-  {
-    /* An identifier showing that this is an image structure for the
-       IMAGEMAGICK format.  */
-    &Qimagemagick,
-    /* Handle to a function that can be used to identify a IMAGEMAGICK
-       file.  */
-    imagemagick_image_p,
-    /* Handle to function used to load a IMAGEMAGICK file.  */
-    imagemagick_load,
-    /* Handle to function to free resources for IMAGEMAGICK.  */
-    imagemagick_clear_image,
-    /* An internal field to link to the next image type in a list of
-       image types, will be filled in when registering the format.  */
-    NULL
-  };
-
-
-DEFUE ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0,
-       doc: /* Return the image types supported by ImageMagick.
-Note that ImageMagick recognizes many file-types that Emacs does not recognize
-as images, such as .c.  */)
+Note that ImageMagick recognizes many file-types that Emacs does not
+recognize as images, such as C.  See `imagemagick-types-inhibit'.  */)
   (void)
 {
   Lisp_Object typelist = Qnil;
-  unsigned long numf;
+  unsigned long numf = 0;
   ExceptionInfo ex;
   char **imtypes = GetMagickList ("*", &numf, &ex);
   int i;
@@ -7910,7 +7880,7 @@ static int svg_image_p (Lisp_Object object);
 static int svg_load (struct frame *f, struct image *img);
 
 static int svg_load_image (struct frame *, struct image *,
-                           unsigned char *, unsigned int);
+                           unsigned char *, ptrdiff_t);
 
 /* The symbol `svg' identifying images of this type. */
 
@@ -7997,7 +7967,6 @@ DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions);
 DEF_IMGLIB_FN (gboolean, rsvg_handle_write);
 DEF_IMGLIB_FN (gboolean, rsvg_handle_close);
 DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf);
-DEF_IMGLIB_FN (void, rsvg_handle_free);
 
 DEF_IMGLIB_FN (int, gdk_pixbuf_get_width);
 DEF_IMGLIB_FN (int, gdk_pixbuf_get_height);
@@ -8030,7 +7999,6 @@ init_svg_functions (Lisp_Object libraries)
   LOAD_IMGLIB_FN (library, rsvg_handle_write);
   LOAD_IMGLIB_FN (library, rsvg_handle_close);
   LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
-  LOAD_IMGLIB_FN (library, rsvg_handle_free);
 
   LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
   LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
@@ -8056,7 +8024,6 @@ init_svg_functions (Lisp_Object libraries)
 #define fn_rsvg_handle_write           rsvg_handle_write
 #define fn_rsvg_handle_close           rsvg_handle_close
 #define fn_rsvg_handle_get_pixbuf      rsvg_handle_get_pixbuf
-#define fn_rsvg_handle_free            rsvg_handle_free
 
 #define fn_gdk_pixbuf_get_width                  gdk_pixbuf_get_width
 #define fn_gdk_pixbuf_get_height         gdk_pixbuf_get_height
@@ -8088,7 +8055,7 @@ svg_load (struct frame *f, struct image *img)
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
@@ -8098,7 +8065,7 @@ svg_load (struct frame *f, struct image *img)
        }
 
       /* Read the entire file into memory.  */
-      contents = slurp_file (SDATA (file), &size);
+      contents = slurp_file (SSDATA (file), &size);
       if (contents == NULL)
        {
          image_error ("Error loading SVG image `%s'", img->spec, Qnil);
@@ -8137,11 +8104,11 @@ static int
 svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  */
                struct image *img,       /* Pointer to emacs image structure.  */
                unsigned char *contents, /* String containing the SVG XML data to be parsed.  */
-               unsigned int size)       /* Size of data in bytes.  */
+               ptrdiff_t size)          /* Size of data in bytes.  */
 {
   RsvgHandle *rsvg_handle;
   RsvgDimensionData dimension_data;
-  GError *error = NULL;
+  GError *err = NULL;
   GdkPixbuf *pixbuf;
   int width;
   int height;
@@ -8160,13 +8127,13 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   rsvg_handle = fn_rsvg_handle_new ();
 
   /* Parse the contents argument and fill in the rsvg_handle.  */
-  fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
-  if (error) goto rsvg_error;
+  fn_rsvg_handle_write (rsvg_handle, contents, size, &err);
+  if (err) goto rsvg_error;
 
   /* The parsing is complete, rsvg_handle is ready to used, close it
      for further writes.  */
-  fn_rsvg_handle_close (rsvg_handle, &error);
-  if (error) goto rsvg_error;
+  fn_rsvg_handle_close (rsvg_handle, &err);
+  if (err) goto rsvg_error;
 
   fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
   if (! check_image_size (f, dimension_data.width, dimension_data.height))
@@ -8206,7 +8173,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
      color.  */
   specified_bg = image_spec_value (img->spec, QCbackground, NULL);
   if (!STRINGP (specified_bg)
-      || !x_defined_color (f, SDATA (specified_bg), &background, 0))
+      || !x_defined_color (f, SSDATA (specified_bg), &background, 0))
     {
 #ifndef HAVE_NS
       background.pixel = FRAME_BACKGROUND_PIXEL (f);
@@ -8281,7 +8248,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   /* FIXME: Use error->message so the user knows what is the actual
      problem with the image.  */
   image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
-  fn_g_error_free (error);
+  fn_g_error_free (err);
   return 0;
 }
 
@@ -8398,7 +8365,7 @@ gs_image_p (Lisp_Object object)
     }
   else if (VECTORP (tem))
     {
-      if (XVECTOR (tem)->size != 4)
+      if (ASIZE (tem) != 4)
        return 0;
       for (i = 0; i < 4; ++i)
        if (!INTEGERP (XVECTOR (tem)->contents[i]))
@@ -8585,7 +8552,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
 
 #if GLYPH_DEBUG
 
-DEFUE ("imagep", Fimagep, Simagep, 1, 1, 0,
+DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
        doc: /* Value is non-nil if SPEC is a valid image specification.  */)
   (Lisp_Object spec)
 {
@@ -8593,7 +8560,7 @@ DEFUE ("imagep", Fimagep, Simagep, 1, 1, 0,
 }
 
 
-DEFUE ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
+DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
   (Lisp_Object spec)
 {
   int id = -1;
@@ -8631,12 +8598,16 @@ Libraries to load are specified in alist LIBRARIES (usually, the value
 of `dynamic-library-alist', which see).  */)
   (Lisp_Object type, Lisp_Object libraries)
 {
-  Lisp_Object tested;
-
+#ifdef HAVE_NTGUI
   /* Don't try to reload the library.  */
-  tested = Fassq (type, Vimage_type_cache);
+  Lisp_Object tested = Fassq (type, Vlibrary_cache);
   if (CONSP (tested))
     return XCDR (tested);
+#endif
+
+  /* Types pbm and xbm are built-in and always available.  */
+  if (EQ (type, Qpbm) || EQ (type, Qxbm))
+    return Qt;
 
 #if defined (HAVE_XPM) || defined (HAVE_NS)
   if (EQ (type, Qxpm))
@@ -8670,10 +8641,8 @@ of `dynamic-library-alist', which see).  */)
 
 #if defined (HAVE_IMAGEMAGICK)
   if (EQ (type, Qimagemagick))
-    {
-      return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions,
-                                 libraries);
-    }
+    return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions,
+                                libraries);
 #endif
 
 #ifdef HAVE_GHOSTSCRIPT
@@ -8714,9 +8683,6 @@ as a ratio to the frame height and width.  If the value is
 non-numeric, there is no explicit limit on the size of images.  */);
   Vmax_image_size = make_float (MAX_IMAGE_SIZE);
 
-  Vimage_type_cache = Qnil;
-  staticpro (&Vimage_type_cache);
-
   Qpbm = intern_c_string ("pbm");
   staticpro (&Qpbm);
   ADD_IMAGE_TYPE (Qpbm);