]> code.delx.au - gnu-emacs/blobdiff - src/image.c
Really fix last change.
[gnu-emacs] / src / image.c
index 947428cff6e414224f714d84fb85dac80403b93d..1c9b262c8cb59054f399fb8bc9b295320f06f590 100644 (file)
@@ -1,7 +1,6 @@
 /* Functions for image support on window system.
-   Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-                 Free Software Foundation, Inc.
+
+Copyright (C) 1989, 1992-2012 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -20,12 +19,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
-#include <math.h>
-#include <ctype.h>
-
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif
 
 #ifdef HAVE_PNG
 #if defined HAVE_LIBPNG_PNG_H
@@ -37,6 +31,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <setjmp.h>
 
+#include <c-ctype.h>
+
 /* This makes the fields of a Display accessible, in Xlib header files.  */
 
 #define XLIB_ILLEGAL_ACCESS
@@ -53,15 +49,23 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "termhooks.h"
 #include "font.h"
 
-#ifdef HAVE_X_WINDOWS
-#include "xterm.h"
-#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
+#endif /* HAVE_SYS_STAT_H */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif /* HAVE_SYS_TYPES_H */
 
+#ifdef HAVE_WINDOW_SYSTEM
+#include TERM_HEADER
+#endif /* HAVE_WINDOW_SYSTEM */
+
+#ifdef HAVE_X_WINDOWS
 #define COLOR_TABLE_SUPPORT 1
 
 typedef struct x_bitmap_record Bitmap_Record;
-#define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
+#define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y)
 #define NO_PIXMAP None
 
 #define RGB_PIXEL_COLOR unsigned long
@@ -70,15 +74,13 @@ typedef struct x_bitmap_record Bitmap_Record;
 #define PIX_MASK_DRAW  1
 #endif /* HAVE_X_WINDOWS */
 
-
 #ifdef HAVE_NTGUI
-#include "w32term.h"
-
+#include "w32.h"
 /* W32_TODO : Color tables on W32.  */
 #undef COLOR_TABLE_SUPPORT
 
 typedef struct w32_bitmap_record Bitmap_Record;
-#define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
+#define GET_PIXEL(ximg, x, y) GetPixel (ximg, x, y)
 #define NO_PIXMAP 0
 
 #define RGB_PIXEL_COLOR COLORREF
@@ -86,15 +88,9 @@ typedef struct w32_bitmap_record Bitmap_Record;
 #define PIX_MASK_RETAIN        0
 #define PIX_MASK_DRAW  1
 
-#define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
 #define x_defined_color w32_defined_color
 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
 
-/* Functions from w32term.c that depend on XColor (so can't go in w32term.h
-   without modifying lots of files).  */
-extern void x_query_colors (struct frame *f, XColor *colors, int ncolors);
-extern void x_query_color (struct frame *f, XColor *color);
-
 /* Version of libpng that we were compiled with, or -1 if no PNG
    support was compiled in.  This is tested by w32-win.el to correctly
    set up the alist used to search for PNG libraries.  */
@@ -102,15 +98,11 @@ Lisp_Object Qlibpng_version;
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
-#include "nsterm.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
 #undef COLOR_TABLE_SUPPORT
 
 typedef struct ns_bitmap_record Bitmap_Record;
 
-#define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
+#define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y)
 #define NO_PIXMAP 0
 
 #define RGB_PIXEL_COLOR unsigned long
@@ -119,29 +111,25 @@ typedef struct ns_bitmap_record Bitmap_Record;
 #define PIX_MASK_RETAIN        0
 #define PIX_MASK_DRAW  1
 
-#define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
 #define x_defined_color(f, name, color_def, alloc) \
   ns_defined_color (f, name, color_def, alloc, 0)
-#define FRAME_X_SCREEN(f) 0
 #define DefaultDepthOfScreen(screen) x_display_list->n_planes
 #endif /* HAVE_NS */
 
 
-/* Search path for bitmap files.  */
-
-Lisp_Object Vx_bitmap_file_path;
+/* The symbol `postscript' identifying images of this type.  */
 
+static Lisp_Object Qpostscript;
 
-static void x_disable_image P_ ((struct frame *, struct image *));
-static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
-                                 Lisp_Object));
+static void x_disable_image (struct frame *, struct image *);
+static void x_edge_detection (struct frame *, struct image *, Lisp_Object,
+                              Lisp_Object);
 
-static void init_color_table P_ ((void));
-static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
+static void init_color_table (void);
+static unsigned long lookup_rgb_color (struct frame *f, int r, int g, int b);
 #ifdef COLOR_TABLE_SUPPORT
-static void free_color_table P_ ((void));
-static unsigned long *colors_in_color_table P_ ((int *n));
-static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
+static void free_color_table (void);
+static unsigned long *colors_in_color_table (int *n);
 #endif
 
 /* Code to deal with bitmaps.  Bitmaps are referenced by their bitmap
@@ -162,7 +150,7 @@ XGetImage (Display *display, Pixmap pixmap, int x, int y,
            unsigned long plane_mask, int format)
 {
   /* TODO: not sure what this function is supposed to do.. */
-  ns_retain_object(pixmap);
+  ns_retain_object (pixmap);
   return pixmap;
 }
 
@@ -170,7 +158,7 @@ XGetImage (Display *display, Pixmap pixmap, int x, int y,
 unsigned long
 XGetPixel (XImagePtr ximage, int x, int y)
 {
-  return ns_get_pixel(ximage, x, y);
+  return ns_get_pixel (ximage, x, y);
 }
 
 /* use with imgs created by ns_image_for_XPM; alpha set to 1;
@@ -178,7 +166,7 @@ XGetPixel (XImagePtr ximage, int x, int y)
 void
 XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
 {
-  ns_put_pixel(ximage, x, y, pixel);
+  ns_put_pixel (ximage, x, y, pixel);
 }
 #endif /* HAVE_NS */
 
@@ -186,36 +174,29 @@ XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
 /* Functions to access the contents of a bitmap, given an id.  */
 
 int
-x_bitmap_height (f, id)
-     FRAME_PTR f;
-     int id;
+x_bitmap_height (FRAME_PTR f, ptrdiff_t id)
 {
   return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
 }
 
 int
-x_bitmap_width (f, id)
-     FRAME_PTR f;
-     int id;
+x_bitmap_width (FRAME_PTR f, ptrdiff_t id)
 {
   return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
 }
 
 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
 int
-x_bitmap_pixmap (f, id)
-     FRAME_PTR f;
-     int id;
+x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id)
 {
+  /* HAVE_NTGUI needs the explicit cast here.  */
   return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
 }
 #endif
 
 #ifdef HAVE_X_WINDOWS
 int
-x_bitmap_mask (f, id)
-     FRAME_PTR f;
-     int id;
+x_bitmap_mask (FRAME_PTR f, ptrdiff_t id)
 {
   return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
 }
@@ -223,21 +204,11 @@ x_bitmap_mask (f, id)
 
 /* Allocate a new bitmap record.  Returns index of new record.  */
 
-static int
-x_allocate_bitmap_record (f)
-     FRAME_PTR f;
+static ptrdiff_t
+x_allocate_bitmap_record (FRAME_PTR f)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int i;
-
-  if (dpyinfo->bitmaps == NULL)
-    {
-      dpyinfo->bitmaps_size = 10;
-      dpyinfo->bitmaps
-       = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
-      dpyinfo->bitmaps_last = 1;
-      return 1;
-    }
+  ptrdiff_t i;
 
   if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
     return ++dpyinfo->bitmaps_last;
@@ -246,33 +217,27 @@ x_allocate_bitmap_record (f)
     if (dpyinfo->bitmaps[i].refcount == 0)
       return i + 1;
 
-  dpyinfo->bitmaps_size *= 2;
-  dpyinfo->bitmaps
-    = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
-                                 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
+  dpyinfo->bitmaps =
+    xpalloc (dpyinfo->bitmaps, &dpyinfo->bitmaps_size,
+            10, -1, sizeof *dpyinfo->bitmaps);
   return ++dpyinfo->bitmaps_last;
 }
 
 /* Add one reference to the reference count of the bitmap with id ID.  */
 
 void
-x_reference_bitmap (f, id)
-     FRAME_PTR f;
-     int id;
+x_reference_bitmap (FRAME_PTR f, ptrdiff_t id)
 {
   ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
 }
 
 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS.  */
 
-int
-x_create_bitmap_from_data (f, bits, width, height)
-     struct frame *f;
-     char *bits;
-     unsigned int width, height;
+ptrdiff_t
+x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsigned int height)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int id;
+  ptrdiff_t id;
 
 #ifdef HAVE_X_WINDOWS
   Pixmap bitmap;
@@ -293,7 +258,7 @@ x_create_bitmap_from_data (f, bits, width, height)
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
-  void *bitmap = ns_image_from_XBM(bits, width, height);
+  void *bitmap = ns_image_from_XBM (bits, width, height);
   if (!bitmap)
       return -1;
 #endif
@@ -327,10 +292,8 @@ x_create_bitmap_from_data (f, bits, width, height)
 
 /* Create bitmap from file FILE for frame F.  */
 
-int
-x_create_bitmap_from_file (f, file)
-     struct frame *f;
-     Lisp_Object file;
+ptrdiff_t
+x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
@@ -339,8 +302,8 @@ x_create_bitmap_from_file (f, file)
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
-  int id;
-  void *bitmap = ns_image_from_file(file);
+  ptrdiff_t id;
+  void *bitmap = ns_image_from_file (file);
 
   if (!bitmap)
       return -1;
@@ -349,18 +312,19 @@ x_create_bitmap_from_file (f, file)
   id = x_allocate_bitmap_record (f);
   dpyinfo->bitmaps[id - 1].img = bitmap;
   dpyinfo->bitmaps[id - 1].refcount = 1;
-  dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
+  dpyinfo->bitmaps[id - 1].file = xmalloc (SBYTES (file) + 1);
   dpyinfo->bitmaps[id - 1].depth = 1;
-  dpyinfo->bitmaps[id - 1].height = ns_image_width(bitmap);
-  dpyinfo->bitmaps[id - 1].width = ns_image_height(bitmap);
-  strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
+  dpyinfo->bitmaps[id - 1].height = ns_image_width (bitmap);
+  dpyinfo->bitmaps[id - 1].width = ns_image_height (bitmap);
+  strcpy (dpyinfo->bitmaps[id - 1].file, SSDATA (file));
   return id;
 #endif
 
 #ifdef HAVE_X_WINDOWS
   unsigned int width, height;
   Pixmap bitmap;
-  int xhot, yhot, result, id;
+  int xhot, yhot, result;
+  ptrdiff_t id;
   Lisp_Object found;
   int fd;
   char *filename;
@@ -370,7 +334,7 @@ x_create_bitmap_from_file (f, file)
     {
       if (dpyinfo->bitmaps[id].refcount
          && dpyinfo->bitmaps[id].file
-         && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
+         && !strcmp (dpyinfo->bitmaps[id].file, SSDATA (file)))
        {
          ++dpyinfo->bitmaps[id].refcount;
          return id + 1;
@@ -383,7 +347,7 @@ x_create_bitmap_from_file (f, file)
     return -1;
   emacs_close (fd);
 
-  filename = (char *) SDATA (found);
+  filename = SSDATA (found);
 
   result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                            filename, &width, &height, &bitmap, &xhot, &yhot);
@@ -394,11 +358,11 @@ x_create_bitmap_from_file (f, file)
   dpyinfo->bitmaps[id - 1].pixmap = bitmap;
   dpyinfo->bitmaps[id - 1].have_mask = 0;
   dpyinfo->bitmaps[id - 1].refcount = 1;
-  dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
+  dpyinfo->bitmaps[id - 1].file = xmalloc (SBYTES (file) + 1);
   dpyinfo->bitmaps[id - 1].depth = 1;
   dpyinfo->bitmaps[id - 1].height = height;
   dpyinfo->bitmaps[id - 1].width = width;
-  strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
+  strcpy (dpyinfo->bitmaps[id - 1].file, SSDATA (file));
 
   return id;
 #endif /* HAVE_X_WINDOWS */
@@ -407,9 +371,7 @@ x_create_bitmap_from_file (f, file)
 /* Free bitmap B.  */
 
 static void
-free_bitmap_record (dpyinfo, bm)
-     Display_Info *dpyinfo;
-     Bitmap_Record *bm;
+free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm)
 {
 #ifdef HAVE_X_WINDOWS
   XFreePixmap (dpyinfo->display, bm->pixmap);
@@ -422,7 +384,7 @@ free_bitmap_record (dpyinfo, bm)
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
-  ns_release_object(bm->img);
+  ns_release_object (bm->img);
 #endif
 
   if (bm->file)
@@ -435,9 +397,7 @@ free_bitmap_record (dpyinfo, bm)
 /* Remove reference to bitmap with id number ID.  */
 
 void
-x_destroy_bitmap (f, id)
-     FRAME_PTR f;
-     int id;
+x_destroy_bitmap (FRAME_PTR f, ptrdiff_t id)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
@@ -447,9 +407,9 @@ x_destroy_bitmap (f, id)
 
       if (--bm->refcount == 0)
        {
-         BLOCK_INPUT;
+         block_input ();
          free_bitmap_record (dpyinfo, bm);
-         UNBLOCK_INPUT;
+         unblock_input ();
        }
     }
 }
@@ -457,10 +417,9 @@ x_destroy_bitmap (f, id)
 /* Free all the bitmaps for the display specified by DPYINFO.  */
 
 void
-x_destroy_all_bitmaps (dpyinfo)
-     Display_Info *dpyinfo;
+x_destroy_all_bitmaps (Display_Info *dpyinfo)
 {
-  int i;
+  ptrdiff_t i;
   Bitmap_Record *bm = dpyinfo->bitmaps;
 
   for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
@@ -476,25 +435,23 @@ x_destroy_all_bitmaps (dpyinfo)
 /* Useful functions defined in the section
    `Image type independent image structures' below. */
 
-static unsigned long four_corners_best P_ ((XImagePtr ximg,
-                                           int *corners,
-                                           unsigned long width,
-                                           unsigned long height));
+static unsigned long four_corners_best (XImagePtr ximg,
+                                        int *corners,
+                                        unsigned long width,
+                                        unsigned long height);
 
-static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
-                                           int depth, XImagePtr *ximg,
-                                           Pixmap *pixmap));
+static int x_create_x_image_and_pixmap (struct frame *f, int width, int height,
+                                        int depth, XImagePtr *ximg,
+                                        Pixmap *pixmap);
 
-static void x_destroy_x_image P_ ((XImagePtr ximg));
+static void x_destroy_x_image (XImagePtr ximg);
 
 
 /* Create a mask of a bitmap. Note is this not a perfect mask.
    It's nicer with some borders in this context */
 
 int
-x_create_bitmap_mask (f, id)
-     struct frame *f;
-     int id;
+x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
 {
   Pixmap pixmap, mask;
   XImagePtr ximg, mask_img;
@@ -513,19 +470,19 @@ x_create_bitmap_mask (f, id)
   width = x_bitmap_width (f, id);
   height = x_bitmap_height (f, id);
 
-  BLOCK_INPUT;
+  block_input ();
   ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
                    ~0, ZPixmap);
 
   if (!ximg)
     {
-      UNBLOCK_INPUT;
+      unblock_input ();
       return -1;
     }
 
   result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
 
-  UNBLOCK_INPUT;
+  unblock_input ();
   if (!result)
     {
       XDestroyImage (ximg);
@@ -557,7 +514,7 @@ x_create_bitmap_mask (f, id)
        }
     }
 
-  xassert (interrupt_input_blocked);
+  eassert (input_blocked_p ());
   gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
   XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
             width, height);
@@ -579,61 +536,44 @@ x_create_bitmap_mask (f, id)
                            Image types
  ***********************************************************************/
 
-/* Value is the number of elements of vector VECTOR.  */
-
-#define DIM(VECTOR)    (sizeof (VECTOR) / sizeof *(VECTOR))
-
 /* List of supported image types.  Use define_image_type to add new
    types.  Use lookup_image_type to find a type for a given symbol.  */
 
 static struct image_type *image_types;
 
-/* A list of symbols, one for each supported image type.  */
-
-Lisp_Object Vimage_types;
-
-/* An alist of image types and libraries that implement the type.  */
-
-Lisp_Object Vimage_library_alist;
-
-/* 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.  */
 
-Lisp_Object Qxbm;
+static Lisp_Object Qxbm;
 
 /* Keywords.  */
 
-extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
-extern Lisp_Object QCdata, QCtype;
-extern Lisp_Object Qcenter;
-Lisp_Object QCascent, QCmargin, QCrelief, Qcount;
-Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
+Lisp_Object QCascent, QCmargin, QCrelief;
+Lisp_Object QCconversion;
+static Lisp_Object QCheuristic_mask;
+static Lisp_Object QCcolor_symbols;
+static Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry;
+static Lisp_Object QCcrop, QCrotation;
 
 /* Other symbols.  */
 
-Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
-
-/* Time in seconds after which images should be removed from the cache
-   if not displayed.  */
-
-Lisp_Object Vimage_cache_eviction_delay;
+static Lisp_Object Qcount, Qextension_data, Qdelay;
+static Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
 
 /* Function prototypes.  */
 
-static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded));
-static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
-static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
-static void x_laplace P_ ((struct frame *, struct image *));
-static void x_emboss P_ ((struct frame *, struct image *));
-static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
-                                      Lisp_Object));
-
+static struct image_type *define_image_type (struct image_type *);
+static struct image_type *lookup_image_type (Lisp_Object);
+static void image_error (const char *format, Lisp_Object, Lisp_Object);
+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)
@@ -641,49 +581,47 @@ static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
 /* Define a new image type from TYPE.  This adds a copy of TYPE to
    image_types and caches the loading status of TYPE.  */
 
-static Lisp_Object
-define_image_type (type, loaded)
-     struct image_type *type;
-     int loaded;
+static struct image_type *
+define_image_type (struct image_type *type)
 {
-  Lisp_Object success;
+  struct image_type *p = NULL;
+  Lisp_Object target_type = *type->type;
+  int type_valid = 1;
 
-  if (!loaded)
-    success = Qnil;
-  else
+  block_input ();
+
+  for (p = image_types; p; p = p->next)
+    if (EQ (*p->type, target_type))
+      goto done;
+
+  if (type->init)
+    {
+#ifdef HAVE_NTGUI
+      /* If we failed to load the library before, don't try again.  */
+      Lisp_Object tested = Fassq (target_type, Vlibrary_cache);
+      if (CONSP (tested) && NILP (XCDR (tested)))
+       type_valid = 0;
+      else
+#endif
+       {
+         type_valid = type->init ();
+         CACHE_IMAGE_TYPE (target_type, type_valid ? Qt : Qnil);
+       }
+    }
+
+  if (type_valid)
     {
       /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
          The initialized data segment is read-only.  */
-      struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
-      bcopy (type, p, sizeof *p);
+      p = xmalloc (sizeof *p);
+      *p = *type;
       p->next = image_types;
       image_types = p;
-      success = Qt;
     }
 
-  CACHE_IMAGE_TYPE (*type->type, success);
-  return success;
-}
-
-
-/* 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 *
-lookup_image_type (symbol)
-     Lisp_Object symbol;
-{
-  struct image_type *type;
-
-  /* We must initialize the image-type if it hasn't been already.  */
-  if (NILP (Finit_image_library (symbol, Vimage_library_alist)))
-    return 0;                  /* unimplemented */
-
-  for (type = image_types; type; type = type->next)
-    if (EQ (symbol, *type->type))
-      break;
-
-  return type;
+ done:
+  unblock_input ();
+  return p;
 }
 
 
@@ -695,8 +633,7 @@ lookup_image_type (symbol)
    image type.  */
 
 int
-valid_image_p (object)
-     Lisp_Object object;
+valid_image_p (Lisp_Object object)
 {
   int valid_p = 0;
 
@@ -731,9 +668,7 @@ valid_image_p (object)
    therefore simply displays a message.  */
 
 static void
-image_error (format, arg1, arg2)
-     char *format;
-     Lisp_Object arg1, arg2;
+image_error (const char *format, Lisp_Object arg1, Lisp_Object arg2)
 {
   add_to_log (format, arg1, arg2);
 }
@@ -751,7 +686,7 @@ enum image_value_type
   IMAGE_STRING_OR_NIL_VALUE,
   IMAGE_SYMBOL_VALUE,
   IMAGE_POSITIVE_INTEGER_VALUE,
-  IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
+  IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR,
   IMAGE_NON_NEGATIVE_INTEGER_VALUE,
   IMAGE_ASCENT_VALUE,
   IMAGE_INTEGER_VALUE,
@@ -765,7 +700,7 @@ enum image_value_type
 struct image_keyword
 {
   /* Name of keyword.  */
-  char *name;
+  const char *name;
 
   /* The type of value allowed.  */
   enum image_value_type type;
@@ -781,9 +716,9 @@ struct image_keyword
 };
 
 
-static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
-                                int, Lisp_Object));
-static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
+static int parse_image_spec (Lisp_Object, struct image_keyword *,
+                             int, Lisp_Object);
+static Lisp_Object image_spec_value (Lisp_Object, Lisp_Object, int *);
 
 
 /* Parse image spec SPEC according to KEYWORDS.  A valid image spec
@@ -793,11 +728,8 @@ static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
    allowed keyword/value pairs.  Value is non-zero if SPEC is valid.  */
 
 static int
-parse_image_spec (spec, keywords, nkeywords, type)
-     Lisp_Object spec;
-     struct image_keyword *keywords;
-     int nkeywords;
-     Lisp_Object type;
+parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
+                 int nkeywords, Lisp_Object type)
 {
   int i;
   Lisp_Object plist;
@@ -824,7 +756,7 @@ parse_image_spec (spec, keywords, nkeywords, type)
 
       /* Find key in KEYWORDS.  Error if not found.  */
       for (i = 0; i < nkeywords; ++i)
-       if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
+       if (strcmp (keywords[i].name, SSDATA (SYMBOL_NAME (key))) == 0)
          break;
 
       if (i == nkeywords)
@@ -833,10 +765,9 @@ parse_image_spec (spec, keywords, nkeywords, type)
       /* Record that we recognized the keyword.  If a keywords
         was found more than once, it's an error.  */
       keywords[i].value = value;
-      ++keywords[i].count;
-
       if (keywords[i].count > 1)
        return 0;
+      ++keywords[i].count;
 
       /* Check type of value against allowed type.  */
       switch (keywords[i].type)
@@ -857,29 +788,30 @@ parse_image_spec (spec, keywords, nkeywords, type)
          break;
 
        case IMAGE_POSITIVE_INTEGER_VALUE:
-         if (!INTEGERP (value) || XINT (value) <= 0)
+         if (! RANGED_INTEGERP (1, value, INT_MAX))
            return 0;
          break;
 
-       case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
-         if (INTEGERP (value) && XINT (value) >= 0)
+       case IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR:
+         if (RANGED_INTEGERP (0, value, INT_MAX))
            break;
          if (CONSP (value)
-             && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
-             && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
+             && RANGED_INTEGERP (0, XCAR (value), INT_MAX)
+             && RANGED_INTEGERP (0, XCDR (value), INT_MAX))
            break;
          return 0;
 
        case IMAGE_ASCENT_VALUE:
          if (SYMBOLP (value) && EQ (value, Qcenter))
            break;
-         else if (INTEGERP (value)
-                  && XINT (value) >= 0
-                  && XINT (value) <= 100)
+         else if (RANGED_INTEGERP (0, value, 100))
            break;
          return 0;
 
        case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
+         /* Unlike the other integer-related cases, this one does not
+            verify that VALUE fits in 'int'.  This is because callers
+            want EMACS_INT.  */
          if (!INTEGERP (value) || XINT (value) < 0)
            return 0;
          break;
@@ -889,9 +821,7 @@ parse_image_spec (spec, keywords, nkeywords, type)
 
        case IMAGE_FUNCTION_VALUE:
          value = indirect_function (value);
-         if (SUBRP (value)
-             || COMPILEDP (value)
-             || (CONSP (value) && EQ (XCAR (value), Qlambda)))
+         if (!NILP (Ffunctionp (value)))
            break;
          return 0;
 
@@ -901,7 +831,7 @@ parse_image_spec (spec, keywords, nkeywords, type)
          break;
 
        case IMAGE_INTEGER_VALUE:
-         if (!INTEGERP (value))
+         if (! TYPE_RANGED_INTEGERP (int, value))
            return 0;
          break;
 
@@ -911,7 +841,7 @@ parse_image_spec (spec, keywords, nkeywords, type)
          break;
 
        default:
-         abort ();
+         emacs_abort ();
          break;
        }
 
@@ -933,13 +863,11 @@ parse_image_spec (spec, keywords, nkeywords, type)
    to 1 if KEY was found in SPEC, set it to 0 otherwise.  */
 
 static Lisp_Object
-image_spec_value (spec, key, found)
-     Lisp_Object spec, key;
-     int *found;
+image_spec_value (Lisp_Object spec, Lisp_Object key, int *found)
 {
   Lisp_Object tail;
 
-  xassert (valid_image_p (spec));
+  eassert (valid_image_p (spec));
 
   for (tail = XCDR (spec);
        CONSP (tail) && CONSP (XCDR (tail));
@@ -965,8 +893,7 @@ PIXELS non-nil means return the size in pixels, otherwise return the
 size in canonical character units.
 FRAME is the frame on which the image will be displayed.  FRAME nil
 or omitted means use the selected frame.  */)
-     (spec, pixels, frame)
-     Lisp_Object spec, pixels, frame;
+  (Lisp_Object spec, Lisp_Object pixels, Lisp_Object frame)
 {
   Lisp_Object size;
 
@@ -974,7 +901,7 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = check_x_frame (frame);
-      int id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec);
       struct image *img = IMAGE_FROM_ID (f, id);
       int width = img->width + 2 * img->hmargin;
       int height = img->height + 2 * img->vmargin;
@@ -996,8 +923,7 @@ DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
        doc: /* Return t if image SPEC has a mask bitmap.
 FRAME is the frame on which the image will be displayed.  FRAME nil
 or omitted means use the selected frame.  */)
-     (spec, frame)
-     Lisp_Object spec, frame;
+  (Lisp_Object spec, Lisp_Object frame)
 {
   Lisp_Object mask;
 
@@ -1005,7 +931,7 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = check_x_frame (frame);
-      int id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec);
       struct image *img = IMAGE_FROM_ID (f, id);
       if (img->mask)
        mask = Qt;
@@ -1016,12 +942,11 @@ or omitted means use the selected frame.  */)
   return mask;
 }
 
-DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
-       doc: /* Return extension data for image SPEC.
+DEFUN ("image-metadata", Fimage_metadata, Simage_metadata, 1, 2, 0,
+       doc: /* Return metadata for image SPEC.
 FRAME is the frame on which the image will be displayed.  FRAME nil
 or omitted means use the selected frame.  */)
-     (spec, frame)
-     Lisp_Object spec, frame;
+  (Lisp_Object spec, Lisp_Object frame)
 {
   Lisp_Object ext;
 
@@ -1029,9 +954,9 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = check_x_frame (frame);
-      int id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec);
       struct image *img = IMAGE_FROM_ID (f, id);
-      ext = img->data.lisp_val;
+      ext = img->lisp_data;
     }
 
   return ext;
@@ -1042,31 +967,24 @@ or omitted means use the selected frame.  */)
                 Image type independent image structures
  ***********************************************************************/
 
-static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
-static void free_image P_ ((struct frame *f, struct image *img));
-static int check_image_size P_ ((struct frame *f, int width, int height));
-
-#define MAX_IMAGE_SIZE 6.0
-Lisp_Object Vmax_image_size;
+static void free_image (struct frame *f, struct image *img);
 
+#define MAX_IMAGE_SIZE 10.0
 /* Allocate and return a new image structure for image specification
    SPEC.  SPEC has a hash value of HASH.  */
 
 static struct image *
-make_image (spec, hash)
-     Lisp_Object spec;
-     unsigned hash;
+make_image (Lisp_Object spec, EMACS_UINT hash)
 {
-  struct image *img = (struct image *) xmalloc (sizeof *img);
+  struct image *img = xzalloc (sizeof *img);
   Lisp_Object file = image_spec_value (spec, QCfile, NULL);
 
-  xassert (valid_image_p (spec));
-  bzero (img, sizeof *img);
+  eassert (valid_image_p (spec));
   img->dependencies = NILP (file) ? Qnil : list1 (file);
   img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
-  xassert (img->type != NULL);
+  eassert (img->type != NULL);
   img->spec = spec;
-  img->data.lisp_val = Qnil;
+  img->lisp_data = Qnil;
   img->ascent = DEFAULT_IMAGE_ASCENT;
   img->hash = hash;
   img->corners[BOT_CORNER] = -1;  /* Full image */
@@ -1077,9 +995,7 @@ make_image (spec, hash)
 /* Free image IMG which was used on frame F, including its resources.  */
 
 static void
-free_image (f, img)
-     struct frame *f;
-     struct image *img;
+free_image (struct frame *f, struct image *img)
 {
   if (img)
     {
@@ -1105,11 +1021,8 @@ free_image (f, img)
 /* Return 1 if the given widths and heights are valid for display;
    otherwise, return 0. */
 
-int
-check_image_size (f, width, height)
-     struct frame *f;
-     int width;
-     int height;
+static int
+check_image_size (struct frame *f, int width, int height)
 {
   int w, h;
 
@@ -1117,7 +1030,8 @@ check_image_size (f, width, height)
     return 0;
 
   if (INTEGERP (Vmax_image_size))
-    w = h = XINT (Vmax_image_size);
+    return (width <= XINT (Vmax_image_size)
+           && height <= XINT (Vmax_image_size));
   else if (FLOATP (Vmax_image_size))
     {
       if (f != NULL)
@@ -1127,28 +1041,21 @@ check_image_size (f, width, height)
        }
       else
        w = h = 1024;  /* Arbitrary size for unknown frame. */
-      w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
-      h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
+      return (width <= XFLOAT_DATA (Vmax_image_size) * w
+             && height <= XFLOAT_DATA (Vmax_image_size) * h);
     }
   else
     return 1;
-
-  return (width <= w && height <= h);
 }
 
 /* Prepare image IMG for display on frame F.  Must be called before
    drawing an image.  */
 
 void
-prepare_image_for_display (f, img)
-     struct frame *f;
-     struct image *img;
+prepare_image_for_display (struct frame *f, struct image *img)
 {
-  EMACS_TIME t;
-
   /* We're about to display IMG, so set its timestamp to `now'.  */
-  EMACS_GET_TIME (t);
-  img->timestamp = EMACS_SECS (t);
+  img->timestamp = current_emacs_time ();
 
   /* If IMG doesn't have a pixmap yet, load it now, using the image
      type dependent loader function.  */
@@ -1162,10 +1069,7 @@ prepare_image_for_display (f, img)
    drawn in face FACE.  */
 
 int
-image_ascent (img, face, slice)
-     struct image *img;
-     struct face *face;
-     struct glyph_slice *slice;
+image_ascent (struct image *img, struct face *face, struct glyph_slice *slice)
 {
   int height;
   int ascent;
@@ -1191,15 +1095,15 @@ image_ascent (img, face, slice)
             because a typical font is `top-heavy' (due to the presence
             uppercase letters), so the image placement should err towards
             being top-heavy too.  It also just generally looks better.  */
-         ascent = (height + FONT_BASE(face->font)
-                    - FONT_DESCENT(face->font) + 1) / 2;
+         ascent = (height + FONT_BASE (face->font)
+                    - FONT_DESCENT (face->font) + 1) / 2;
 #endif /* HAVE_NTGUI */
        }
       else
        ascent = height / 2;
     }
   else
-    ascent = (int) (height * img->ascent / 100.0);
+    ascent = height * (img->ascent / 100.0);
 
   return ascent;
 }
@@ -1211,12 +1115,10 @@ image_ascent (img, face, slice)
    On W32, XIMG is assumed to a device context with the bitmap selected.  */
 
 static RGB_PIXEL_COLOR
-four_corners_best (ximg, corners, width, height)
-     XImagePtr_or_DC ximg;
-     int *corners;
-     unsigned long width, height;
+four_corners_best (XImagePtr_or_DC ximg, int *corners,
+                  unsigned long width, unsigned long height)
 {
-  RGB_PIXEL_COLOR corner_pixels[4], best;
+  RGB_PIXEL_COLOR corner_pixels[4], best IF_LINT (= 0);
   int i, best_count;
 
   if (corners && corners[BOT_CORNER] >= 0)
@@ -1264,10 +1166,10 @@ four_corners_best (ximg, corners, width, height)
 #elif defined (HAVE_NS)
 
 #define Destroy_Image(ximg, dummy) \
-  ns_release_object(ximg)
+  ns_release_object (ximg)
 
 #define Free_Pixmap(display, pixmap) \
-  ns_release_object(pixmap)
+  ns_release_object (pixmap)
 
 #else
 
@@ -1286,10 +1188,7 @@ four_corners_best (ximg, corners, width, height)
    use for the heuristic.  */
 
 RGB_PIXEL_COLOR
-image_background (img, f, ximg)
-     struct image *img;
-     struct frame *f;
-     XImagePtr_or_DC ximg;
+image_background (struct image *img, struct frame *f, XImagePtr_or_DC ximg)
 {
   if (! img->background_valid)
     /* IMG doesn't have a background yet, try to guess a reasonable value.  */
@@ -1328,10 +1227,7 @@ image_background (img, f, ximg)
    existing XImage object to use for the heuristic.  */
 
 int
-image_background_transparent (img, f, mask)
-     struct image *img;
-     struct frame *f;
-     XImagePtr_or_DC mask;
+image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_DC mask)
 {
   if (! img->background_transparent_valid)
     /* IMG doesn't have a background yet, try to guess a reasonable value.  */
@@ -1376,13 +1272,13 @@ image_background_transparent (img, f, mask)
                  Helper functions for X image types
  ***********************************************************************/
 
-static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
-                                int, int));
-static void x_clear_image P_ ((struct frame *f, struct image *img));
-static unsigned long x_alloc_image_color P_ ((struct frame *f,
-                                             struct image *img,
-                                             Lisp_Object color_name,
-                                             unsigned long dflt));
+static void x_clear_image_1 (struct frame *, struct image *, int,
+                             int, int);
+static void x_clear_image (struct frame *f, struct image *img);
+static unsigned long x_alloc_image_color (struct frame *f,
+                                          struct image *img,
+                                          Lisp_Object color_name,
+                                          unsigned long dflt);
 
 
 /* Clear X resources of image IMG on frame F.  PIXMAP_P non-zero means
@@ -1391,10 +1287,8 @@ static unsigned long x_alloc_image_color P_ ((struct frame *f,
    the image, if any.  */
 
 static void
-x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
-     struct frame *f;
-     struct image *img;
-     int pixmap_p, mask_p, colors_p;
+x_clear_image_1 (struct frame *f, struct image *img, int pixmap_p, int mask_p,
+                int colors_p)
 {
   if (pixmap_p && img->pixmap)
     {
@@ -1427,13 +1321,11 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
 /* Free X resources of image IMG which is used on frame F.  */
 
 static void
-x_clear_image (f, img)
-     struct frame *f;
-     struct image *img;
+x_clear_image (struct frame *f, struct image *img)
 {
-  BLOCK_INPUT;
+  block_input ();
   x_clear_image_1 (f, img, 1, 1, 1);
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 
@@ -1443,26 +1335,24 @@ x_clear_image (f, img)
    color.  */
 
 static unsigned long
-x_alloc_image_color (f, img, color_name, dflt)
-     struct frame *f;
-     struct image *img;
-     Lisp_Object color_name;
-     unsigned long dflt;
+x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name,
+                    unsigned long dflt)
 {
   XColor color;
   unsigned long result;
 
-  xassert (STRINGP (color_name));
+  eassert (STRINGP (color_name));
 
-  if (x_defined_color (f, SDATA (color_name), &color, 1))
+  if (x_defined_color (f, SSDATA (color_name), &color, 1)
+      && img->ncolors < min (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *img->colors,
+                            INT_MAX))
     {
       /* This isn't called frequently so we get away with simply
         reallocating the color vector to the needed size, here.  */
-      ++img->ncolors;
-      img->colors =
-       (unsigned long *) xrealloc (img->colors,
-                                   img->ncolors * sizeof *img->colors);
-      img->colors[img->ncolors - 1] = color.pixel;
+      ptrdiff_t ncolors = img->ncolors + 1;
+      img->colors = xrealloc (img->colors, ncolors * sizeof *img->colors);
+      img->colors[ncolors - 1] = color.pixel;
+      img->ncolors = ncolors;
       result = color.pixel;
     }
   else
@@ -1477,25 +1367,23 @@ x_alloc_image_color (f, img, color_name, dflt)
                             Image Cache
  ***********************************************************************/
 
-static struct image *search_image_cache P_ ((struct frame *, Lisp_Object, unsigned));
-static void cache_image P_ ((struct frame *f, struct image *img));
-static void postprocess_image P_ ((struct frame *, struct image *));
+static void cache_image (struct frame *f, struct image *img);
+static void postprocess_image (struct frame *, struct image *);
 
 /* Return a new, initialized image cache that is allocated from the
    heap.  Call free_image_cache to free an image cache.  */
 
 struct image_cache *
-make_image_cache ()
+make_image_cache (void)
 {
-  struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
+  struct image_cache *c = xzalloc (sizeof *c);
   int size;
 
-  bzero (c, sizeof *c);
-  c->size = 50;
-  c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
+  size = 50;
+  c->images = xmalloc (size * sizeof *c->images);
+  c->size = size;
   size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
-  c->buckets = (struct image **) xmalloc (size);
-  bzero (c->buckets, size);
+  c->buckets = xzalloc (size);
   return c;
 }
 
@@ -1503,10 +1391,7 @@ make_image_cache ()
 /* Find an image matching SPEC in the cache, and return it.  If no
    image is found, return NULL.  */
 static struct image *
-search_image_cache (f, spec, hash)
-     struct frame *f;
-     Lisp_Object spec;
-     unsigned hash;
+search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash)
 {
   struct image *img;
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
@@ -1539,9 +1424,7 @@ search_image_cache (f, spec, hash)
 /* Search frame F for an image with spec SPEC, and free it.  */
 
 static void
-uncache_image (f, spec)
-     struct frame *f;
-     Lisp_Object spec;
+uncache_image (struct frame *f, Lisp_Object spec)
 {
   struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
   if (img)
@@ -1558,16 +1441,15 @@ uncache_image (f, spec)
    caches.  */
 
 void
-free_image_cache (f)
-     struct frame *f;
+free_image_cache (struct frame *f)
 {
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
   if (c)
     {
-      int i;
+      ptrdiff_t i;
 
       /* Cache should not be referenced by any frame when freed.  */
-      xassert (c->refcount == 0);
+      eassert (c->refcount == 0);
 
       for (i = 0; i < c->used; ++i)
        free_image (f, c->images[i]);
@@ -1587,34 +1469,62 @@ free_image_cache (f)
    If image-cache-eviction-delay is non-nil, this frees images in the cache
    which weren't displayed for at least that many seconds.  */
 
-void
+static void
 clear_image_cache (struct frame *f, Lisp_Object filter)
 {
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
 
-  if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay)))
+  if (c)
     {
-      EMACS_TIME t;
-      unsigned long old;
-      int i, nfreed;
-
-      EMACS_GET_TIME (t);
-      old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
+      ptrdiff_t i, nfreed = 0;
 
       /* Block input so that we won't be interrupted by a SIGIO
         while being in an inconsistent state.  */
-      BLOCK_INPUT;
+      block_input ();
 
-      for (i = nfreed = 0; i < c->used; ++i)
+      if (!NILP (filter))
+       {
+         /* Filter image cache.  */
+         for (i = 0; i < c->used; ++i)
+           {
+             struct image *img = c->images[i];
+             if (img && (EQ (Qt, filter)
+                         || !NILP (Fmember (filter, img->dependencies))))
+               {
+                 free_image (f, img);
+                 ++nfreed;
+               }
+           }
+       }
+      else if (INTEGERP (Vimage_cache_eviction_delay))
        {
-         struct image *img = c->images[i];
-         if (img != NULL
-             && (NILP (filter) ? img->timestamp < old
-                 : (EQ (Qt, filter)
-                    || !NILP (Fmember (filter, img->dependencies)))))
+         /* Free cache based on timestamp.  */
+         EMACS_TIME old, t;
+         double delay;
+         ptrdiff_t nimages = 0;
+
+         for (i = 0; i < c->used; ++i)
+           if (c->images[i])
+             nimages++;
+
+         /* If the number of cached images has grown unusually large,
+            decrease the cache eviction delay (Bug#6230).  */
+         delay = XINT (Vimage_cache_eviction_delay);
+         if (nimages > 40)
+           delay = 1600 * delay / nimages / nimages;
+         delay = max (delay, 1);
+
+         t = current_emacs_time ();
+         old = sub_emacs_time (t, EMACS_TIME_FROM_DOUBLE (delay));
+
+         for (i = 0; i < c->used; ++i)
            {
-             free_image (f, img);
-             ++nfreed;
+             struct image *img = c->images[i];
+             if (img && EMACS_TIME_LT (img->timestamp, old))
+               {
+                 free_image (f, img);
+                 ++nfreed;
+               }
            }
        }
 
@@ -1628,15 +1538,15 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
 
          FOR_EACH_FRAME (tail, frame)
            {
-             struct frame *f = XFRAME (frame);
-             if (FRAME_IMAGE_CACHE (f) == c)
-               clear_current_matrices (f);
+             struct frame *fr = XFRAME (frame);
+             if (FRAME_IMAGE_CACHE (fr) == c)
+               clear_current_matrices (fr);
            }
 
          ++windows_or_buffers_changed;
        }
 
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 
@@ -1660,8 +1570,7 @@ FILTER nil or a frame means clear all images in the selected frame.
 FILTER t means clear the image caches of all frames.
 Anything else, means only clear those images which refer to FILTER,
 which is then usually a filename.  */)
-     (filter)
-     Lisp_Object filter;
+  (Lisp_Object filter)
 {
   if (!(EQ (filter, Qnil) || FRAMEP (filter)))
     clear_image_caches (filter);
@@ -1672,15 +1581,16 @@ which is then usually a filename.  */)
 }
 
 
-DEFUN ("image-refresh", Fimage_refresh, Simage_refresh,
+DEFUN ("image-flush", Fimage_flush, Simage_flush,
        1, 2, 0,
-       doc: /* Refresh the image with specification SPEC on frame FRAME.
-If SPEC specifies an image file, the displayed image is updated with
-the current contents of that file.
+       doc: /* Fush the image with specification SPEC on frame FRAME.
+This removes the image from the Emacs image cache.  If SPEC specifies
+an image file, the next redisplay of this image will read from the
+current contents of that file.
+
 FRAME nil or omitted means use the selected frame.
 FRAME t means refresh the image on all frames.  */)
-     (spec, frame)
-     Lisp_Object spec, frame;
+  (Lisp_Object spec, Lisp_Object frame)
 {
   if (!valid_image_p (spec))
     error ("Invalid image specification");
@@ -1706,9 +1616,7 @@ FRAME t means refresh the image on all frames.  */)
    by the image's specification,  */
 
 static void
-postprocess_image (f, img)
-     struct frame *f;
-     struct image *img;
+postprocess_image (struct frame *f, struct image *img)
 {
   /* Manipulation of the image's mask.  */
   if (img->pixmap)
@@ -1780,25 +1688,16 @@ postprocess_image (f, img)
 /* Return the id of image with Lisp specification SPEC on frame F.
    SPEC must be a valid Lisp image specification (see valid_image_p).  */
 
-int
-lookup_image (f, spec)
-     struct frame *f;
-     Lisp_Object spec;
+ptrdiff_t
+lookup_image (struct frame *f, Lisp_Object spec)
 {
-  struct image_cache *c;
   struct image *img;
-  unsigned hash;
-  struct gcpro gcpro1;
-  EMACS_TIME now;
+  EMACS_UINT hash;
 
   /* F must be a window-system frame, and SPEC must be a valid image
      specification.  */
-  xassert (FRAME_WINDOW_P (f));
-  xassert (valid_image_p (spec));
-
-  c = FRAME_IMAGE_CACHE (f);
-
-  GCPRO1 (spec);
+  eassert (FRAME_WINDOW_P (f));
+  eassert (valid_image_p (spec));
 
   /* Look up SPEC in the hash table of the image cache.  */
   hash = sxhash (spec, 0);
@@ -1812,9 +1711,7 @@ lookup_image (f, spec)
   /* If not found, create a new image and cache it.  */
   if (img == NULL)
     {
-      extern Lisp_Object Qpostscript;
-
-      BLOCK_INPUT;
+      block_input ();
       img = make_image (spec, hash);
       cache_image (f, img);
       img->load_failed_p = img->type->load (f, img) == 0;
@@ -1841,6 +1738,7 @@ lookup_image (f, spec)
             `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
             `:background COLOR'.  */
          Lisp_Object ascent, margin, relief, bg;
+         int relief_bound;
 
          ascent = image_spec_value (spec, QCascent, NULL);
          if (INTEGERP (ascent))
@@ -1849,19 +1747,17 @@ lookup_image (f, spec)
            img->ascent = CENTERED_IMAGE_ASCENT;
 
          margin = image_spec_value (spec, QCmargin, NULL);
-         if (INTEGERP (margin) && XINT (margin) >= 0)
+         if (INTEGERP (margin))
            img->vmargin = img->hmargin = XFASTINT (margin);
-         else if (CONSP (margin) && INTEGERP (XCAR (margin))
-                  && INTEGERP (XCDR (margin)))
+         else if (CONSP (margin))
            {
-             if (XINT (XCAR (margin)) > 0)
-               img->hmargin = XFASTINT (XCAR (margin));
-             if (XINT (XCDR (margin)) > 0)
-               img->vmargin = XFASTINT (XCDR (margin));
+             img->hmargin = XFASTINT (XCAR (margin));
+             img->vmargin = XFASTINT (XCDR (margin));
            }
 
          relief = image_spec_value (spec, QCrelief, NULL);
-         if (INTEGERP (relief))
+         relief_bound = INT_MAX - max (img->hmargin, img->vmargin);
+         if (RANGED_INTEGERP (- relief_bound, relief, relief_bound))
            {
              img->relief = XINT (relief);
              img->hmargin += eabs (img->relief);
@@ -1886,14 +1782,11 @@ lookup_image (f, spec)
            postprocess_image (f, img);
        }
 
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 
   /* We're using IMG, so set its timestamp to `now'.  */
-  EMACS_GET_TIME (now);
-  img->timestamp = EMACS_SECS (now);
-
-  UNGCPRO;
+  img->timestamp = current_emacs_time ();
 
   /* Value is the image id.  */
   return img->id;
@@ -1903,12 +1796,10 @@ lookup_image (f, spec)
 /* Cache image IMG in the image cache of frame F.  */
 
 static void
-cache_image (f, img)
-     struct frame *f;
-     struct image *img;
+cache_image (struct frame *f, struct image *img)
 {
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
-  int i;
+  ptrdiff_t i;
 
   /* Find a free slot in c->images.  */
   for (i = 0; i < c->used; ++i)
@@ -1917,11 +1808,7 @@ cache_image (f, img)
 
   /* If no free slot found, maybe enlarge c->images.  */
   if (i == c->used && c->used == c->size)
-    {
-      c->size *= 2;
-      c->images = (struct image **) xrealloc (c->images,
-                                             c->size * sizeof *c->images);
-    }
+    c->images = xpalloc (c->images, &c->size, 1, -1, sizeof *c->images);
 
   /* Add IMG to c->images, and assign IMG an id.  */
   c->images[i] = img;
@@ -1945,14 +1832,13 @@ cache_image (f, img)
 /* Mark Lisp objects in image IMG.  */
 
 static void
-mark_image (img)
-     struct image *img;
+mark_image (struct image *img)
 {
   mark_object (img->spec);
   mark_object (img->dependencies);
 
-  if (!NILP (img->data.lisp_val))
-    mark_object (img->data.lisp_val);
+  if (!NILP (img->lisp_data))
+    mark_object (img->lisp_data);
 }
 
 
@@ -1961,7 +1847,7 @@ mark_image_cache (struct image_cache *c)
 {
   if (c)
     {
-      int i;
+      ptrdiff_t i;
       for (i = 0; i < c->used; ++i)
        if (c->images[i])
          mark_image (c->images[i]);
@@ -1977,7 +1863,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) rettype (FAR CDECL *fn_##func)()
+#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) {                                     \
@@ -1985,41 +1871,52 @@ mark_image_cache (struct image_cache *c)
     if (!fn_##func) return 0;                                          \
   }
 
-/* Load a DLL implementing an image type.
-   The `image-library-alist' variable associates a symbol,
-   identifying an image type, to a list of possible filenames.
-   The function returns NULL if no library could be loaded for
-   the given image type, or if the library was previously loaded;
-   else the handle of the DLL.  */
-static HMODULE
-w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
+#endif /* HAVE_NTGUI */
+
+static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
+                                        XImagePtr *, Pixmap *);
+static void x_destroy_x_image (XImagePtr);
+static void x_put_x_image (struct frame *, XImagePtr, Pixmap, int, int);
+
+/* Return nonzero if XIMG's size WIDTH x HEIGHT doesn't break the
+   windowing system.
+   WIDTH and HEIGHT must both be positive.
+   If XIMG is null, assume it is a bitmap.  */
+static int
+x_check_image_size (XImagePtr ximg, int width, int height)
 {
-  HMODULE library = NULL;
+#ifdef HAVE_X_WINDOWS
+  /* Respect Xlib's limits: it cannot deal with images that have more
+     than INT_MAX (and/or UINT_MAX) bytes.  And respect Emacs's limits
+     of PTRDIFF_MAX (and/or SIZE_MAX) bytes for any object.  */
+  enum
+  {
+    XLIB_BYTES_MAX = min (INT_MAX, UINT_MAX),
+    X_IMAGE_BYTES_MAX = min (XLIB_BYTES_MAX, min (PTRDIFF_MAX, SIZE_MAX))
+  };
 
-  if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
+  int bitmap_pad, depth, bytes_per_line;
+  if (ximg)
     {
-      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;
-          }
+      bitmap_pad = ximg->bitmap_pad;
+      depth = ximg->depth;
+      bytes_per_line = ximg->bytes_per_line;
     }
-
-  return library;
+  else
+    {
+      bitmap_pad = 8;
+      depth = 1;
+      bytes_per_line = (width >> 3) + ((width & 7) != 0);
+    }
+  return (width <= (INT_MAX - (bitmap_pad - 1)) / depth
+         && height <= X_IMAGE_BYTES_MAX / bytes_per_line);
+#else
+  /* FIXME: Implement this check for the HAVE_NS and HAVE_NTGUI cases.
+     For now, assume that every image size is allowed on these systems.  */
+  return 1;
+#endif
 }
 
-#endif /* HAVE_NTGUI */
-
-static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
-                                           XImagePtr *, Pixmap *));
-static void x_destroy_x_image P_ ((XImagePtr));
-static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
-
-
 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
    frame F.  Set *XIMG and *PIXMAP to the XImage and Pixmap created.
    Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
@@ -2030,18 +1927,15 @@ static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
    should indicate the bit depth of the image.  */
 
 static int
-x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
-     struct frame *f;
-     int width, height, depth;
-     XImagePtr *ximg;
-     Pixmap *pixmap;
+x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
+                            XImagePtr *ximg, Pixmap *pixmap)
 {
 #ifdef HAVE_X_WINDOWS
   Display *display = FRAME_X_DISPLAY (f);
   Window window = FRAME_X_WINDOW (f);
   Screen *screen = FRAME_X_SCREEN (f);
 
-  xassert (interrupt_input_blocked);
+  eassert (input_blocked_p ());
 
   if (depth <= 0)
     depth = DefaultDepthOfScreen (screen);
@@ -2054,8 +1948,17 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
       return 0;
     }
 
+  if (! x_check_image_size (*ximg, width, height))
+    {
+      x_destroy_x_image (*ximg);
+      *ximg = NULL;
+      image_error ("Image too large (%dx%d)",
+                  make_number (width), make_number (height));
+      return 0;
+    }
+
   /* Allocate image raster.  */
-  (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
+  (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height);
 
   /* Allocate a pixmap of the same size.  */
   *pixmap = XCreatePixmap (display, window, width, height, depth);
@@ -2097,17 +2000,12 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
   /* Bitmaps with a depth less than 16 need a palette.  */
   /* BITMAPINFO structure already contains the first RGBQUAD.  */
   if (depth < 16)
-    palette_colors = 1 << depth - 1;
+    palette_colors = 1 << (depth - 1);
 
   *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
-  if (*ximg == NULL)
-    {
-      image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
-      return 0;
-    }
 
-  header = &((*ximg)->info.bmiHeader);
-  bzero (&((*ximg)->info), sizeof (BITMAPINFO));
+  header = &(*ximg)->info.bmiHeader;
+  memset (&(*ximg)->info, 0, sizeof (BITMAPINFO));
   header->biSize = sizeof (*header);
   header->biWidth = width;
   header->biHeight = -height;  /* negative indicates a top-down bitmap.  */
@@ -2146,7 +2044,7 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
       DWORD err = GetLastError ();
       Lisp_Object errcode;
       /* All system errors are < 10000, so the following is safe.  */
-      XSETINT (errcode, (int) err);
+      XSETINT (errcode, err);
       image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
       x_destroy_x_image (*ximg);
       return 0;
@@ -2157,7 +2055,7 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
-  *pixmap = ns_image_for_XPM(width, height, depth);
+  *pixmap = ns_image_for_XPM (width, height, depth);
   if (*pixmap == 0)
     {
       *ximg = NULL;
@@ -2173,10 +2071,9 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
 /* Destroy XImage XIMG.  Free XIMG->data.  */
 
 static void
-x_destroy_x_image (ximg)
-     XImagePtr ximg;
+x_destroy_x_image (XImagePtr ximg)
 {
-  xassert (interrupt_input_blocked);
+  eassert (input_blocked_p ());
   if (ximg)
     {
 #ifdef HAVE_X_WINDOWS
@@ -2190,7 +2087,7 @@ x_destroy_x_image (ximg)
       xfree (ximg);
 #endif /* HAVE_NTGUI */
 #ifdef HAVE_NS
-      ns_release_object(ximg);
+      ns_release_object (ximg);
 #endif /* HAVE_NS */
     }
 }
@@ -2200,16 +2097,12 @@ x_destroy_x_image (ximg)
    are width and height of both the image and pixmap.  */
 
 static void
-x_put_x_image (f, ximg, pixmap, width, height)
-     struct frame *f;
-     XImagePtr ximg;
-     Pixmap pixmap;
-     int width, height;
+x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int height)
 {
 #ifdef HAVE_X_WINDOWS
   GC gc;
 
-  xassert (interrupt_input_blocked);
+  eassert (input_blocked_p ());
   gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
   XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
   XFreeGC (FRAME_X_DISPLAY (f), gc);
@@ -2224,8 +2117,8 @@ x_put_x_image (f, ximg, pixmap, width, height)
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
-  xassert (ximg == pixmap);
-  ns_retain_object(ximg);
+  eassert (ximg == pixmap);
+  ns_retain_object (ximg);
 #endif
 }
 
@@ -2234,28 +2127,21 @@ x_put_x_image (f, ximg, pixmap, width, height)
                              File Handling
  ***********************************************************************/
 
-static unsigned char *slurp_file P_ ((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.  */
 
 Lisp_Object
-x_find_image_file (file)
-     Lisp_Object file;
+x_find_image_file (Lisp_Object file)
 {
   Lisp_Object file_found, search_path;
-  struct gcpro gcpro1, gcpro2;
   int fd;
 
-  file_found = Qnil;
   /* TODO I think this should use something like image-load-path
      instead.  Unfortunately, that can contain non-string elements.  */
   search_path = Fcons (Fexpand_file_name (build_string ("images"),
                                          Vdata_directory),
                       Vx_bitmap_file_path);
-  GCPRO2 (file_found, search_path);
 
   /* Try to find FILE in data-directory/images, then x-bitmap-file-path.  */
   fd = openp (search_path, file, Qnil, &file_found, Qnil);
@@ -2268,7 +2154,6 @@ x_find_image_file (file)
       close (fd);
     }
 
-  UNGCPRO;
   return file_found;
 }
 
@@ -2278,9 +2163,7 @@ x_find_image_file (file)
    occurred.  *SIZE is set to the size of the file.  */
 
 static unsigned char *
-slurp_file (file, size)
-     char *file;
-     int *size;
+slurp_file (char *file, ptrdiff_t *size)
 {
   FILE *fp = NULL;
   unsigned char *buf = NULL;
@@ -2288,7 +2171,8 @@ slurp_file (file, size)
 
   if (stat (file, &st) == 0
       && (fp = fopen (file, "rb")) != NULL
-      && (buf = (unsigned char *) xmalloc (st.st_size),
+      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
+      && (buf = xmalloc (st.st_size),
          fread (buf, 1, st.st_size, fp) == st.st_size))
     {
       *size = st.st_size;
@@ -2314,15 +2198,15 @@ slurp_file (file, size)
                              XBM images
  ***********************************************************************/
 
-static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
-static int xbm_load P_ ((struct frame *f, struct image *img));
-static int xbm_load_image P_ ((struct frame *f, struct image *img,
-                              unsigned char *, unsigned char *));
-static int xbm_image_p P_ ((Lisp_Object object));
-static int xbm_read_bitmap_data P_ ((struct frame *f,
-                                    unsigned char *, unsigned char *,
-                                    int *, int *, unsigned char **, int));
-static int xbm_file_p P_ ((Lisp_Object));
+static int xbm_scan (unsigned char **, unsigned char *, char *, int *);
+static int xbm_load (struct frame *f, struct image *img);
+static int xbm_load_image (struct frame *f, struct image *img,
+                           unsigned char *, unsigned char *);
+static int xbm_image_p (Lisp_Object object);
+static int xbm_read_bitmap_data (struct frame *f,
+                                 unsigned char *, unsigned char *,
+                                 int *, int *, char **, int);
+static int xbm_file_p (Lisp_Object);
 
 
 /* Indices of image specification fields in xbm_format, below.  */
@@ -2358,7 +2242,7 @@ static const struct image_keyword xbm_format[XBM_LAST] =
   {":foreground",      IMAGE_STRING_OR_NIL_VALUE,              0},
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -2373,6 +2257,7 @@ static struct image_type xbm_type =
   xbm_image_p,
   xbm_load,
   x_clear_image,
+  NULL,
   NULL
 };
 
@@ -2415,16 +2300,15 @@ enum xbm_token
    displayed is used.  */
 
 static int
-xbm_image_p (object)
-     Lisp_Object object;
+xbm_image_p (Lisp_Object object)
 {
   struct image_keyword kw[XBM_LAST];
 
-  bcopy (xbm_format, kw, sizeof kw);
+  memcpy (kw, xbm_format, sizeof kw);
   if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
     return 0;
 
-  xassert (EQ (kw[XBM_TYPE].value, Qxbm));
+  eassert (EQ (kw[XBM_TYPE].value, Qxbm));
 
   if (kw[XBM_FILE].count)
     {
@@ -2456,17 +2340,17 @@ xbm_image_p (object)
         data.  */
       if (VECTORP (data))
        {
-         int i;
+         EMACS_INT i;
 
          /* Number of elements of the vector must be >= height.  */
-         if (XVECTOR_SIZE (data) < height)
+         if (ASIZE (data) < height)
            return 0;
 
          /* Each string or bool-vector in data must be large enough
             for one line of the image.  */
          for (i = 0; i < height; ++i)
            {
-             Lisp_Object elt = XVECTOR (data)->contents[i];
+             Lisp_Object elt = AREF (data, i);
 
              if (STRINGP (elt))
                {
@@ -2491,7 +2375,7 @@ xbm_image_p (object)
        }
       else if (BOOL_VECTOR_P (data))
        {
-         if (XBOOL_VECTOR (data)->size < width * height)
+         if (XBOOL_VECTOR (data)->size / height < width)
            return 0;
        }
       else
@@ -2509,22 +2393,19 @@ xbm_image_p (object)
    scanning a number, store its value in *IVAL.  */
 
 static int
-xbm_scan (s, end, sval, ival)
-     unsigned char **s, *end;
-     char *sval;
-     int *ival;
+xbm_scan (unsigned char **s, unsigned char *end, char *sval, int *ival)
 {
   unsigned int c;
 
  loop:
 
   /* Skip white space.  */
-  while (*s < end && (c = *(*s)++, isspace (c)))
+  while (*s < end && (c = *(*s)++, c_isspace (c)))
     ;
 
   if (*s >= end)
     c = 0;
-  else if (isdigit (c))
+  else if (c_isdigit (c))
     {
       int value = 0, digit;
 
@@ -2536,7 +2417,7 @@ xbm_scan (s, end, sval, ival)
              while (*s < end)
                {
                  c = *(*s)++;
-                 if (isdigit (c))
+                 if (c_isdigit (c))
                    digit = c - '0';
                  else if (c >= 'a' && c <= 'f')
                    digit = c - 'a' + 10;
@@ -2547,11 +2428,11 @@ xbm_scan (s, end, sval, ival)
                  value = 16 * value + digit;
                }
            }
-         else if (isdigit (c))
+         else if (c_isdigit (c))
            {
              value = c - '0';
              while (*s < end
-                    && (c = *(*s)++, isdigit (c)))
+                    && (c = *(*s)++, c_isdigit (c)))
                value = 8 * value + c - '0';
            }
        }
@@ -2559,7 +2440,7 @@ xbm_scan (s, end, sval, ival)
        {
          value = c - '0';
          while (*s < end
-                && (c = *(*s)++, isdigit (c)))
+                && (c = *(*s)++, c_isdigit (c)))
            value = 10 * value + c - '0';
        }
 
@@ -2568,11 +2449,11 @@ xbm_scan (s, end, sval, ival)
       *ival = value;
       c = XBM_TK_NUMBER;
     }
-  else if (isalpha (c) || c == '_')
+  else if (c_isalpha (c) || c == '_')
     {
       *sval++ = c;
       while (*s < end
-            && (c = *(*s)++, (isalnum (c) || c == '_')))
+            && (c = *(*s)++, (c_isalnum (c) || c == '_')))
        *sval++ = c;
       *sval = 0;
       if (*s < end)
@@ -2612,8 +2493,8 @@ w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
 
   w1 = (width + 7) / 8;         /* nb of 8bits elt in X bitmap */
   w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
-  bits = (unsigned char *) alloca (height * w2);
-  bzero (bits, height * w2);
+  bits = alloca (height * w2);
+  memset (bits, 0, height * w2);
   for (i = 0; i < height; i++)
     {
       p = bits + i*w2;
@@ -2631,10 +2512,8 @@ w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
 }
 
 static void
-convert_mono_to_color_image (f, img, foreground, background)
-     struct frame *f;
-     struct image *img;
-     COLORREF foreground, background;
+convert_mono_to_color_image (struct frame *f, struct image *img,
+                            COLORREF foreground, COLORREF background)
 {
   HDC hdc, old_img_dc, new_img_dc;
   HGDIOBJ old_prev, new_prev;
@@ -2676,12 +2555,9 @@ convert_mono_to_color_image (f, img, foreground, background)
 
 
 static void
-Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
-     struct frame *f;
-     struct image *img;
-     char *data;
-     RGB_PIXEL_COLOR fg, bg;
-     int non_default_colors;
+Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
+                               RGB_PIXEL_COLOR fg, RGB_PIXEL_COLOR bg,
+                               int non_default_colors)
 {
 #ifdef HAVE_NTGUI
   img->pixmap
@@ -2692,16 +2568,18 @@ Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
     convert_mono_to_color_image (f, img, fg, bg);
 
 #elif defined (HAVE_NS)
-  img->pixmap = ns_image_from_XBM(data, img->width, img->height);
+  img->pixmap = ns_image_from_XBM (data, img->width, img->height);
 
 #else
-  img->pixmap
-    = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
+  img->pixmap =
+   (x_check_image_size (0, img->width, img->height)
+    ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
                                   FRAME_X_WINDOW (f),
                                   data,
                                   img->width, img->height,
                                   fg, bg,
-                                  DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
+                                  DefaultDepthOfScreen (FRAME_X_SCREEN (f)))
+    : NO_PIXMAP);
 #endif /* !HAVE_NTGUI && !HAVE_NS */
 }
 
@@ -2717,19 +2595,16 @@ Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
    invalid (the bitmap remains unread).  */
 
 static int
-xbm_read_bitmap_data (f, contents, end, width, height, data, inhibit_image_error)
-     struct frame *f;
-     unsigned char *contents, *end;
-     int *width, *height;
-     unsigned char **data;
-     int inhibit_image_error;
+xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *end,
+                     int *width, int *height, char **data,
+                     int inhibit_image_error)
 {
   unsigned char *s = contents;
   char buffer[BUFSIZ];
   int padding_p = 0;
   int v10 = 0;
   int bytes_per_line, i, nbytes;
-  unsigned char *p;
+  char *p;
   int value;
   int LA1;
 
@@ -2762,11 +2637,11 @@ xbm_read_bitmap_data (f, contents, end, width, height, data, inhibit_image_error
 
       if (LA1 == XBM_TK_NUMBER)
        {
-          char *p = strrchr (buffer, '_');
-         p = p ? p + 1 : buffer;
-          if (strcmp (p, "width") == 0)
+         char *q = strrchr (buffer, '_');
+         q = q ? q + 1 : buffer;
+         if (strcmp (q, "width") == 0)
            *width = value;
-          else if (strcmp (p, "height") == 0)
+         else if (strcmp (q, "height") == 0)
            *height = value;
        }
       expect (XBM_TK_NUMBER);
@@ -2811,9 +2686,16 @@ xbm_read_bitmap_data (f, contents, end, width, height, data, inhibit_image_error
   expect ('=');
   expect ('{');
 
+  if (! x_check_image_size (0, *width, *height))
+    {
+      if (!inhibit_image_error)
+       image_error ("Image too large (%dx%d)",
+                    make_number (*width), make_number (*height));
+      goto failure;
+    }
   bytes_per_line = (*width + 7) / 8 + padding_p;
   nbytes = bytes_per_line * *height;
-  p = *data = (unsigned char *) xmalloc (nbytes);
+  p = *data = xmalloc (nbytes);
 
   if (v10)
     {
@@ -2871,13 +2753,11 @@ xbm_read_bitmap_data (f, contents, end, width, height, data, inhibit_image_error
    successful.  */
 
 static int
-xbm_load_image (f, img, contents, end)
-     struct frame *f;
-     struct image *img;
-     unsigned char *contents, *end;
+xbm_load_image (struct frame *f, struct image *img, unsigned char *contents,
+               unsigned char *end)
 {
   int rc;
-  unsigned char *data;
+  char *data;
   int success_p = 0;
 
   rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height,
@@ -2889,7 +2769,7 @@ xbm_load_image (f, img, contents, end)
       int non_default_colors = 0;
       Lisp_Object value;
 
-      xassert (img->width > 0 && img->height > 0);
+      eassert (img->width > 0 && img->height > 0);
 
       /* Get foreground and background colors, maybe allocate colors.  */
       value = image_spec_value (img->spec, QCforeground, NULL);
@@ -2930,8 +2810,7 @@ xbm_load_image (f, img, contents, end)
 /* Value is non-zero if DATA looks like an in-memory XBM file.  */
 
 static int
-xbm_file_p (data)
-     Lisp_Object data;
+xbm_file_p (Lisp_Object data)
 {
   int w, h;
   return (STRINGP (data)
@@ -2945,14 +2824,12 @@ xbm_file_p (data)
    non-zero if successful.  */
 
 static int
-xbm_load (f, img)
-     struct frame *f;
-     struct image *img;
+xbm_load (struct frame *f, struct image *img)
 {
   int success_p = 0;
   Lisp_Object file_name;
 
-  xassert (xbm_image_p (img->spec));
+  eassert (xbm_image_p (img->spec));
 
   /* If IMG->spec specifies a file name, create a non-file spec from it.  */
   file_name = image_spec_value (img->spec, QCfile, NULL);
@@ -2960,28 +2837,24 @@ xbm_load (f, img)
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
-      struct gcpro gcpro1;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
-      GCPRO1 (file);
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", file_name, Qnil);
-         UNGCPRO;
          return 0;
        }
 
-      contents = slurp_file (SDATA (file), &size);
+      contents = slurp_file (SSDATA (file), &size);
       if (contents == NULL)
        {
          image_error ("Error loading XBM image `%s'", img->spec, Qnil);
-         UNGCPRO;
          return 0;
        }
 
       success_p = xbm_load_image (f, img, contents, contents + size);
-      UNGCPRO;
+      xfree (contents);
     }
   else
     {
@@ -2999,16 +2872,23 @@ xbm_load (f, img)
       in_memory_file_p = xbm_file_p (data);
 
       /* Parse the image specification.  */
-      bcopy (xbm_format, fmt, sizeof fmt);
+      memcpy (fmt, xbm_format, sizeof fmt);
       parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
-      xassert (parsed_p);
+      (void) parsed_p;
+      eassert (parsed_p);
 
       /* Get specified width, and height.  */
       if (!in_memory_file_p)
        {
          img->width = XFASTINT (fmt[XBM_WIDTH].value);
          img->height = XFASTINT (fmt[XBM_HEIGHT].value);
-         xassert (img->width > 0 && img->height > 0);
+         eassert (img->width > 0 && img->height > 0);
+         if (!check_image_size (f, img->width, img->height))
+           {
+             image_error ("Invalid image size (see `max-image-size')",
+                          Qnil, Qnil);
+             return 0;
+           }
        }
 
       /* Get foreground and background colors, maybe allocate colors.  */
@@ -3040,20 +2920,20 @@ xbm_load (f, img)
              char *p;
              int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
 
-             p = bits = (char *) alloca (nbytes * img->height);
+             p = bits = alloca (nbytes * img->height);
              for (i = 0; i < img->height; ++i, p += nbytes)
                {
-                 Lisp_Object line = XVECTOR (data)->contents[i];
+                 Lisp_Object line = AREF (data, i);
                  if (STRINGP (line))
-                   bcopy (SDATA (line), p, nbytes);
+                   memcpy (p, SDATA (line), nbytes);
                  else
-                   bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+                   memcpy (p, XBOOL_VECTOR (line)->data, nbytes);
                }
            }
          else if (STRINGP (data))
-           bits = SDATA (data);
+           bits = SSDATA (data);
          else
-           bits = XBOOL_VECTOR (data)->data;
+           bits = (char *) XBOOL_VECTOR (data)->data;
 
 #ifdef WINDOWSNT
           {
@@ -3063,16 +2943,20 @@ xbm_load (f, img)
             invertedBits = bits;
             nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
               * img->height;
-            bits = (char *) alloca(nbytes);
+            bits = alloca (nbytes);
             for (i = 0; i < nbytes; i++)
               bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
           }
 #endif
          /* Create the pixmap.  */
 
-         Create_Pixmap_From_Bitmap_Data (f, img, bits,
-                                         foreground, background,
-                                         non_default_colors);
+         if (x_check_image_size (0, img->width, img->height))
+           Create_Pixmap_From_Bitmap_Data (f, img, bits,
+                                           foreground, background,
+                                           non_default_colors);
+         else
+           img->pixmap = NO_PIXMAP;
+
          if (img->pixmap)
            success_p = 1;
          else
@@ -3095,9 +2979,9 @@ xbm_load (f, img)
 
 #if defined (HAVE_XPM) || defined (HAVE_NS)
 
-static int xpm_image_p P_ ((Lisp_Object object));
-static int xpm_load P_ ((struct frame *f, struct image *img));
-static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
+static int xpm_image_p (Lisp_Object object);
+static int xpm_load (struct frame *f, struct image *img);
+static int xpm_valid_color_symbols_p (Lisp_Object);
 
 #endif /* HAVE_XPM || HAVE_NS */
 
@@ -3125,7 +3009,7 @@ static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
 #if defined (HAVE_XPM) || defined (HAVE_NS)
 /* The symbol `xpm' identifying XPM-format images.  */
 
-Lisp_Object Qxpm;
+static Lisp_Object Qxpm;
 
 /* Indices of image specification fields in xpm_format, below.  */
 
@@ -3154,7 +3038,7 @@ static const struct image_keyword xpm_format[XPM_LAST] =
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -3163,6 +3047,12 @@ static const struct image_keyword xpm_format[XPM_LAST] =
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
+#ifdef HAVE_NTGUI
+static int init_xpm_functions (void);
+#else
+#define init_xpm_functions NULL
+#endif
+
 /* Structure describing the image type XPM.  */
 
 static struct image_type xpm_type =
@@ -3171,6 +3061,7 @@ static struct image_type xpm_type =
   xpm_image_p,
   xpm_load,
   x_clear_image,
+  init_xpm_functions,
   NULL
 };
 
@@ -3188,12 +3079,12 @@ static struct image_type xpm_type =
 
 #ifdef ALLOC_XPM_COLORS
 
-static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
-static void xpm_free_color_cache P_ ((void));
-static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
-static int xpm_color_bucket P_ ((char *));
-static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
-                                                    XColor *, int));
+static void xpm_init_color_cache (struct frame *, XpmAttributes *);
+static void xpm_free_color_cache (void);
+static int xpm_lookup_color (struct frame *, char *, XColor *);
+static int xpm_color_bucket (char *);
+static struct xpm_cached_color *xpm_cache_color (struct frame *, char *,
+                                                 XColor *, int);
 
 /* An entry in a hash table used to cache color definitions of named
    colors.  This cache is necessary to speed up XPM image loading in
@@ -3216,18 +3107,15 @@ struct xpm_cached_color
    size.  */
 
 #define XPM_COLOR_CACHE_BUCKETS        1001
-struct xpm_cached_color **xpm_color_cache;
+static struct xpm_cached_color **xpm_color_cache;
 
 /* Initialize the color cache.  */
 
 static void
-xpm_init_color_cache (f, attrs)
-     struct frame *f;
-     XpmAttributes *attrs;
+xpm_init_color_cache (struct frame *f, XpmAttributes *attrs)
 {
   size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
-  xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
-  memset (xpm_color_cache, 0, nbytes);
+  xpm_color_cache = xzalloc (nbytes);
   init_color_table ();
 
   if (attrs->valuemask & XpmColorSymbols)
@@ -3249,7 +3137,7 @@ xpm_init_color_cache (f, attrs)
 /* Free the color cache.  */
 
 static void
-xpm_free_color_cache ()
+xpm_free_color_cache (void)
 {
   struct xpm_cached_color *p, *next;
   int i;
@@ -3270,15 +3158,10 @@ xpm_free_color_cache ()
    cache.  */
 
 static int
-xpm_color_bucket (color_name)
-     char *color_name;
+xpm_color_bucket (char *color_name)
 {
-  unsigned h = 0;
-  char *s;
-
-  for (s = color_name; *s; ++s)
-    h = (h << 2) ^ *s;
-  return h %= XPM_COLOR_CACHE_BUCKETS;
+  EMACS_UINT hash = hash_string (color_name, strlen (color_name));
+  return hash % XPM_COLOR_CACHE_BUCKETS;
 }
 
 
@@ -3287,11 +3170,7 @@ xpm_color_bucket (color_name)
    entry added.  */
 
 static struct xpm_cached_color *
-xpm_cache_color (f, color_name, color, bucket)
-     struct frame *f;
-     char *color_name;
-     XColor *color;
-     int bucket;
+xpm_cache_color (struct frame *f, char *color_name, XColor *color, int bucket)
 {
   size_t nbytes;
   struct xpm_cached_color *p;
@@ -3299,8 +3178,8 @@ xpm_cache_color (f, color_name, color, bucket)
   if (bucket < 0)
     bucket = xpm_color_bucket (color_name);
 
-  nbytes = sizeof *p + strlen (color_name);
-  p = (struct xpm_cached_color *) xmalloc (nbytes);
+  nbytes = offsetof (struct xpm_cached_color, name) + strlen (color_name) + 1;
+  p = xmalloc (nbytes);
   strcpy (p->name, color_name);
   p->color = *color;
   p->next = xpm_color_cache[bucket];
@@ -3314,10 +3193,7 @@ xpm_cache_color (f, color_name, color, bucket)
    allocation failed.  */
 
 static int
-xpm_lookup_color (f, color_name, color)
-     struct frame *f;
-     char *color_name;
-     XColor *color;
+xpm_lookup_color (struct frame *f, char *color_name, XColor *color)
 {
   struct xpm_cached_color *p;
   int h = xpm_color_bucket (color_name);
@@ -3339,7 +3215,7 @@ xpm_lookup_color (f, color_name, color)
      with transparency, and it's useful.  */
   else if (strcmp ("opaque", color_name) == 0)
     {
-      bzero (color, sizeof (XColor));  /* Is this necessary/correct?  */
+      memset (color, 0, sizeof (XColor));  /* Is this necessary/correct?  */
       color->pixel = FRAME_FOREGROUND_PIXEL (f);
       p = xpm_cache_color (f, color_name, color, h);
     }
@@ -3354,12 +3230,8 @@ xpm_lookup_color (f, color_name, color)
    if successful.  */
 
 static int
-xpm_alloc_color (dpy, cmap, color_name, color, closure)
-     Display *dpy;
-     Colormap cmap;
-     char *color_name;
-     XColor *color;
-     void *closure;
+xpm_alloc_color (Display *dpy, Colormap cmap, char *color_name, XColor *color,
+                void *closure)
 {
   return xpm_lookup_color ((struct frame *) closure, color_name, color);
 }
@@ -3370,12 +3242,7 @@ xpm_alloc_color (dpy, cmap, color_name, color, closure)
    non-zero if successful.  */
 
 static int
-xpm_free_colors (dpy, cmap, pixels, npixels, closure)
-     Display *dpy;
-     Colormap cmap;
-     Pixel *pixels;
-     int npixels;
-     void *closure;
+xpm_free_colors (Display *dpy, Colormap cmap, Pixel *pixels, int npixels, void *closure)
 {
   return 1;
 }
@@ -3387,17 +3254,19 @@ xpm_free_colors (dpy, cmap, pixels, npixels, closure)
 
 /* XPM library details.  */
 
-DEF_IMGLIB_FN (void, XpmFreeAttributes);
-DEF_IMGLIB_FN (int, XpmCreateImageFromBuffer);
-DEF_IMGLIB_FN (int, XpmReadFileToImage);
-DEF_IMGLIB_FN (void, XImageFree);
+DEF_IMGLIB_FN (void, XpmFreeAttributes, (XpmAttributes *));
+DEF_IMGLIB_FN (int, XpmCreateImageFromBuffer, (Display *, char *, xpm_XImage **,
+                                         xpm_XImage **, XpmAttributes *));
+DEF_IMGLIB_FN (int, XpmReadFileToImage, (Display *, char *, xpm_XImage **,
+                                   xpm_XImage **, XpmAttributes *));
+DEF_IMGLIB_FN (void, XImageFree, (xpm_XImage *));
 
 static int
-init_xpm_functions (Lisp_Object libraries)
+init_xpm_functions (void)
 {
   HMODULE library;
 
-  if (!(library = w32_delayed_load (libraries, Qxpm)))
+  if (!(library = w32_delayed_load (Qxpm)))
     return 0;
 
   LOAD_IMGLIB_FN (library, XpmFreeAttributes);
@@ -3415,8 +3284,7 @@ init_xpm_functions (Lisp_Object libraries)
    cdr are strings.  */
 
 static int
-xpm_valid_color_symbols_p (color_symbols)
-     Lisp_Object color_symbols;
+xpm_valid_color_symbols_p (Lisp_Object color_symbols)
 {
   while (CONSP (color_symbols))
     {
@@ -3435,11 +3303,10 @@ xpm_valid_color_symbols_p (color_symbols)
 /* Value is non-zero if OBJECT is a valid XPM image specification.  */
 
 static int
-xpm_image_p (object)
-     Lisp_Object object;
+xpm_image_p (Lisp_Object object)
 {
   struct image_keyword fmt[XPM_LAST];
-  bcopy (xpm_format, fmt, sizeof fmt);
+  memcpy (fmt, xpm_format, sizeof fmt);
   return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
          /* Either `:file' or `:data' must be present.  */
          && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
@@ -3451,18 +3318,17 @@ xpm_image_p (object)
 
 #endif /* HAVE_XPM || HAVE_NS */
 
-#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
-int
-x_create_bitmap_from_xpm_data (f, bits)
-     struct frame *f;
-     char **bits;
+#if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK
+ptrdiff_t
+x_create_bitmap_from_xpm_data (struct frame *f, const char **bits)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int id, rc;
+  ptrdiff_t id;
+  int rc;
   XpmAttributes attrs;
   Pixmap bitmap, mask;
 
-  bzero (&attrs, sizeof attrs);
+  memset (&attrs, 0, sizeof attrs);
 
   attrs.visual = FRAME_X_VISUAL (f);
   attrs.colormap = FRAME_X_COLORMAP (f);
@@ -3470,7 +3336,7 @@ x_create_bitmap_from_xpm_data (f, bits)
   attrs.valuemask |= XpmColormap;
 
   rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                               bits, &bitmap, &mask, &attrs);
+                               (char **) bits, &bitmap, &mask, &attrs);
   if (rc != XpmSuccess)
     {
       XpmFreeAttributes (&attrs);
@@ -3498,9 +3364,7 @@ x_create_bitmap_from_xpm_data (f, bits)
 #ifdef HAVE_XPM
 
 static int
-xpm_load (f, img)
-     struct frame *f;
-     struct image *img;
+xpm_load (struct frame *f, struct image *img)
 {
   int rc;
   XpmAttributes attrs;
@@ -3512,7 +3376,7 @@ xpm_load (f, img)
 
   /* Configure the XPM lib.  Use the visual of frame F.  Allocate
      close colors.  Return colors allocated.  */
-  bzero (&attrs, sizeof attrs);
+  memset (&attrs, 0, sizeof attrs);
 
 #ifndef HAVE_NTGUI
   attrs.visual = FRAME_X_VISUAL (f);
@@ -3558,8 +3422,8 @@ xpm_load (f, img)
 
       /* Allocate an XpmColorSymbol array.  */
       size = attrs.numsymbols * sizeof *xpm_syms;
-      xpm_syms = (XpmColorSymbol *) alloca (size);
-      bzero (xpm_syms, size);
+      xpm_syms = alloca (size);
+      memset (xpm_syms, 0, size);
       attrs.colorsymbols = xpm_syms;
 
       /* Fill the color symbol array.  */
@@ -3567,12 +3431,32 @@ xpm_load (f, img)
           CONSP (tail);
           ++i, tail = XCDR (tail))
        {
-         Lisp_Object name = XCAR (XCAR (tail));
-         Lisp_Object color = XCDR (XCAR (tail));
-         xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
-         strcpy (xpm_syms[i].name, SDATA (name));
-         xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
-         strcpy (xpm_syms[i].value, SDATA (color));
+         Lisp_Object name;
+         Lisp_Object color;
+         char *empty_string = (char *) "";
+
+         if (!CONSP (XCAR (tail)))
+           {
+             xpm_syms[i].name = empty_string;
+             xpm_syms[i].value = empty_string;
+             continue;
+           }
+         name = XCAR (XCAR (tail));
+         color = XCDR (XCAR (tail));
+         if (STRINGP (name))
+           {
+             xpm_syms[i].name = alloca (SCHARS (name) + 1);
+             strcpy (xpm_syms[i].name, SSDATA (name));
+           }
+         else
+           xpm_syms[i].name = empty_string;
+         if (STRINGP (color))
+           {
+             xpm_syms[i].value = alloca (SCHARS (color) + 1);
+             strcpy (xpm_syms[i].value, SSDATA (color));
+           }
+         else
+           xpm_syms[i].value = empty_string;
        }
     }
 
@@ -3598,6 +3482,9 @@ xpm_load (f, img)
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", specified_file, Qnil);
+#ifdef ALLOC_XPM_COLORS
+         xpm_free_color_cache ();
+#endif
          return 0;
        }
 
@@ -3609,13 +3496,21 @@ xpm_load (f, img)
                                  &attrs);
 #else
       rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                               SDATA (file), &img->pixmap, &img->mask,
+                               SSDATA (file), &img->pixmap, &img->mask,
                                &attrs);
 #endif /* HAVE_NTGUI */
     }
   else
     {
       Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
+      if (!STRINGP (buffer))
+       {
+         image_error ("Invalid image data `%s'", buffer, Qnil);
+#ifdef ALLOC_XPM_COLORS
+         xpm_free_color_cache ();
+#endif
+         return 0;
+       }
 #ifdef HAVE_NTGUI
       /* XpmCreatePixmapFromBuffer is not available in the Windows port
         of libxpm.  But XpmCreateImageFromBuffer almost does what we want.  */
@@ -3624,7 +3519,7 @@ xpm_load (f, img)
                                        &attrs);
 #else
       rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                                     SDATA (buffer),
+                                     SSDATA (buffer),
                                      &img->pixmap, &img->mask,
                                      &attrs);
 #endif /* HAVE_NTGUI */
@@ -3667,9 +3562,8 @@ xpm_load (f, img)
 #endif /* HAVE_NTGUI */
 
       /* Remember allocated colors.  */
+      img->colors = xnmalloc (attrs.nalloc_pixels, sizeof *img->colors);
       img->ncolors = attrs.nalloc_pixels;
-      img->colors = (unsigned long *) xmalloc (img->ncolors
-                                              * sizeof *img->colors);
       for (i = 0; i < attrs.nalloc_pixels; ++i)
        {
          img->colors[i] = attrs.alloc_pixels[i];
@@ -3681,7 +3575,7 @@ xpm_load (f, img)
 
       img->width = attrs.width;
       img->height = attrs.height;
-      xassert (img->width > 0 && img->height > 0);
+      eassert (img->width > 0 && img->height > 0);
 
       /* The call to XpmFreeAttributes below frees attrs.alloc_pixels.  */
 #ifdef HAVE_NTGUI
@@ -3733,25 +3627,14 @@ xpm_load (f, img)
 /* XPM support functions for NS where libxpm is not available.
    Only XPM version 3 (without any extensions) is supported.  */
 
-static int xpm_scan P_ ((const unsigned char **, const unsigned char *,
-                        const unsigned char **, int *));
-static Lisp_Object xpm_make_color_table_v
-  P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
-       Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
-static void xpm_put_color_table_v P_ ((Lisp_Object, const unsigned char *,
-                                      int, Lisp_Object));
-static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
-                                             const unsigned char *, int));
-static Lisp_Object xpm_make_color_table_h
-  P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
-       Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
-static void xpm_put_color_table_h P_ ((Lisp_Object, const unsigned char *,
-                                      int, Lisp_Object));
-static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
-                                             const unsigned char *, int));
-static int xpm_str_to_color_key P_ ((const char *));
-static int xpm_load_image P_ ((struct frame *, struct image *,
-                              const unsigned char *, const unsigned char *));
+static void xpm_put_color_table_v (Lisp_Object, const unsigned char *,
+                                   int, Lisp_Object);
+static Lisp_Object xpm_get_color_table_v (Lisp_Object,
+                                          const unsigned char *, int);
+static void xpm_put_color_table_h (Lisp_Object, const unsigned char *,
+                                   int, Lisp_Object);
+static Lisp_Object xpm_get_color_table_h (Lisp_Object,
+                                          const unsigned char *, int);
 
 /* Tokens returned from xpm_scan.  */
 
@@ -3770,25 +3653,27 @@ enum xpm_token
    length of the corresponding token, respectively.  */
 
 static int
-xpm_scan (s, end, beg, len)
-     const unsigned char **s, *end, **beg;
-     int *len;
+xpm_scan (const unsigned char **s,
+          const unsigned char *end,
+          const unsigned char **beg,
+          ptrdiff_t *len)
 {
   int c;
 
   while (*s < end)
     {
       /* Skip white-space.  */
-      while (*s < end && (c = *(*s)++, isspace (c)))
+      while (*s < end && (c = *(*s)++, c_isspace (c)))
        ;
 
       /* gnus-pointer.xpm uses '-' in its identifier.
         sb-dir-plus.xpm uses '+' in its identifier.  */
-      if (isalpha (c) || c == '_' || c == '-' || c == '+')
+      if (c_isalpha (c) || c == '_' || c == '-' || c == '+')
        {
          *beg = *s - 1;
          while (*s < end
-                && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
+                && (c = **s, c_isalnum (c)
+                    || c == '_' || c == '-' || c == '+'))
              ++*s;
          *len = *s - *beg;
          return XPM_TK_IDENT;
@@ -3836,9 +3721,13 @@ xpm_scan (s, end, beg, len)
    hash table is used.  */
 
 static Lisp_Object
-xpm_make_color_table_v (put_func, get_func)
-     void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
-     Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
+xpm_make_color_table_v (void (**put_func) (Lisp_Object,
+                                           const unsigned char *,
+                                           int,
+                                           Lisp_Object),
+                        Lisp_Object (**get_func) (Lisp_Object,
+                                                  const unsigned char *,
+                                                  int))
 {
   *put_func = xpm_put_color_table_v;
   *get_func = xpm_get_color_table_v;
@@ -3846,28 +3735,30 @@ xpm_make_color_table_v (put_func, get_func)
 }
 
 static void
-xpm_put_color_table_v (color_table, chars_start, chars_len, color)
-     Lisp_Object color_table;
-     const unsigned char *chars_start;
-     int chars_len;
-     Lisp_Object color;
+xpm_put_color_table_v (Lisp_Object color_table,
+                       const unsigned char *chars_start,
+                       int chars_len,
+                       Lisp_Object color)
 {
-  XVECTOR (color_table)->contents[*chars_start] = color;
+  ASET (color_table, *chars_start, color);
 }
 
 static Lisp_Object
-xpm_get_color_table_v (color_table, chars_start, chars_len)
-     Lisp_Object color_table;
-     const unsigned char *chars_start;
-     int chars_len;
+xpm_get_color_table_v (Lisp_Object color_table,
+                       const unsigned char *chars_start,
+                       int chars_len)
 {
-  return XVECTOR (color_table)->contents[*chars_start];
+  return AREF (color_table, *chars_start);
 }
 
 static Lisp_Object
-xpm_make_color_table_h (put_func, get_func)
-     void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
-     Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
+xpm_make_color_table_h (void (**put_func) (Lisp_Object,
+                                           const unsigned char *,
+                                           int,
+                                           Lisp_Object),
+                        Lisp_Object (**get_func) (Lisp_Object,
+                                                  const unsigned char *,
+                                                  int))
 {
   *put_func = xpm_put_color_table_h;
   *get_func = xpm_get_color_table_h;
@@ -3878,14 +3769,13 @@ xpm_make_color_table_h (put_func, get_func)
 }
 
 static void
-xpm_put_color_table_h (color_table, chars_start, chars_len, color)
-     Lisp_Object color_table;
-     const unsigned char *chars_start;
-     int chars_len;
-     Lisp_Object color;
+xpm_put_color_table_h (Lisp_Object color_table,
+                       const unsigned char *chars_start,
+                       int chars_len,
+                       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);
@@ -3893,14 +3783,13 @@ xpm_put_color_table_h (color_table, chars_start, chars_len, color)
 }
 
 static Lisp_Object
-xpm_get_color_table_h (color_table, chars_start, chars_len)
-     Lisp_Object color_table;
-     const unsigned char *chars_start;
-     int chars_len;
+xpm_get_color_table_h (Lisp_Object color_table,
+                       const unsigned char *chars_start,
+                       int chars_len)
 {
   struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
-  int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
-                      NULL);
+  ptrdiff_t i =
+    hash_lookup (table, make_unibyte_string (chars_start, chars_len), NULL);
 
   return i >= 0 ? HASH_VALUE (table, i) : Qnil;
 }
@@ -3916,8 +3805,7 @@ enum xpm_color_key {
 static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
 
 static int
-xpm_str_to_color_key (s)
-     const char *s;
+xpm_str_to_color_key (const char *s)
 {
   int i;
 
@@ -3930,16 +3818,17 @@ xpm_str_to_color_key (s)
 }
 
 static int
-xpm_load_image (f, img, contents, end)
-     struct frame *f;
-     struct image *img;
-     const unsigned char *contents, *end;
+xpm_load_image (struct frame *f,
+                struct image *img,
+                const unsigned char *contents,
+                const unsigned char *end)
 {
   const unsigned char *s = contents, *beg, *str;
   unsigned char buffer[BUFSIZ];
   int width, height, x, y;
   int num_colors, chars_per_pixel;
-  int len, LA1;
+  ptrdiff_t len;
+  int LA1;
   void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
   Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
   Lisp_Object frame, color_symbols, color_table;
@@ -3965,7 +3854,7 @@ xpm_load_image (f, img, contents, end)
   if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
     goto failure;
   s += 9;
-  match();
+  match ();
   expect_ident ("static");
   expect_ident ("char");
   expect ('*');
@@ -3991,6 +3880,18 @@ xpm_load_image (f, img, contents, end)
       goto failure;
     }
 
+  if (!x_create_x_image_and_pixmap (f, width, height, 0,
+                                   &ximg, &img->pixmap)
+#ifndef HAVE_NS
+      || !x_create_x_image_and_pixmap (f, width, height, 1,
+                                      &mask_img, &img->mask)
+#endif
+      )
+    {
+      image_error ("Image too large", Qnil, Qnil);
+      goto failure;
+    }
+
   expect (',');
 
   XSETFRAME (frame, f);
@@ -4012,7 +3913,7 @@ xpm_load_image (f, img, contents, end)
 
   while (num_colors-- > 0)
     {
-      unsigned char *color, *max_color;
+      char *color, *max_color;
       int key, next_key, max_key = 0;
       Lisp_Object symbol_color = Qnil, color_val;
       XColor cdef;
@@ -4064,9 +3965,9 @@ xpm_load_image (f, img, contents, end)
 
          if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
            {
-             if (xstrcasecmp (SDATA (XCDR (specified_color)), "None") == 0)
+             if (xstrcasecmp (SSDATA (XCDR (specified_color)), "None") == 0)
                color_val = Qt;
-             else if (x_defined_color (f, SDATA (XCDR (specified_color)),
+             else if (x_defined_color (f, SSDATA (XCDR (specified_color)),
                                        &cdef, 0))
                color_val = make_number (cdef.pixel);
            }
@@ -4084,18 +3985,6 @@ xpm_load_image (f, img, contents, end)
       expect (',');
     }
 
-  if (!x_create_x_image_and_pixmap (f, width, height, 0,
-                                   &ximg, &img->pixmap)
-#ifndef HAVE_NS
-      || !x_create_x_image_and_pixmap (f, width, height, 1,
-                                      &mask_img, &img->mask)
-#endif
-      )
-    {
-      image_error ("Out of memory (%s)", img->spec, Qnil);
-      goto error;
-    }
-
   for (y = 0; y < height; y++)
     {
       expect (XPM_TK_STRING);
@@ -4115,8 +4004,8 @@ xpm_load_image (f, img, contents, end)
                     (!EQ (color_val, Qt) ? PIX_MASK_DRAW
                      : (have_mask = 1, PIX_MASK_RETAIN)));
 #else
-          if (EQ(color_val, Qt))
-            ns_set_alpha(ximg, x, y, 0);
+          if (EQ (color_val, Qt))
+            ns_set_alpha (ximg, x, y, 0);
 #endif
        }
       if (y + 1 < height)
@@ -4153,7 +4042,6 @@ xpm_load_image (f, img, contents, end)
 
  failure:
   image_error ("Invalid XPM file (%s)", img->spec, Qnil);
- error:
   x_destroy_x_image (ximg);
   x_destroy_x_image (mask_img);
   x_clear_image (f, img);
@@ -4165,9 +4053,8 @@ xpm_load_image (f, img, contents, end)
 }
 
 static int
-xpm_load (f, img)
-     struct frame *f;
-     struct image *img;
+xpm_load (struct frame *f,
+          struct image *img)
 {
   int success_p = 0;
   Lisp_Object file_name;
@@ -4178,35 +4065,35 @@ xpm_load (f, img)
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
-      struct gcpro gcpro1;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
-      GCPRO1 (file);
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", file_name, Qnil);
-         UNGCPRO;
          return 0;
        }
 
-      contents = slurp_file (SDATA (file), &size);
+      contents = slurp_file (SSDATA (file), &size);
       if (contents == NULL)
        {
          image_error ("Error loading XPM image `%s'", img->spec, Qnil);
-         UNGCPRO;
          return 0;
        }
 
       success_p = xpm_load_image (f, img, contents, contents + size);
       xfree (contents);
-      UNGCPRO;
     }
   else
     {
       Lisp_Object data;
 
       data = image_spec_value (img->spec, QCdata, NULL);
+      if (!STRINGP (data))
+       {
+         image_error ("Invalid image data `%s'", data, Qnil);
+         return 0;
+       }
       success_p = xpm_load_image (f, img, SDATA (data),
                                  SDATA (data) + SBYTES (data));
     }
@@ -4245,20 +4132,25 @@ struct ct_color
 
 /* The color hash table.  */
 
-struct ct_color **ct_table;
+static struct ct_color **ct_table;
 
 /* Number of entries in the color table.  */
 
-int ct_colors_allocated;
+static int ct_colors_allocated;
+enum
+{
+  ct_colors_allocated_max =
+    min (INT_MAX,
+        min (PTRDIFF_MAX, SIZE_MAX) / sizeof (unsigned long))
+};
 
 /* Initialize the color table.  */
 
 static void
-init_color_table ()
+init_color_table (void)
 {
   int size = CT_SIZE * sizeof (*ct_table);
-  ct_table = (struct ct_color **) xmalloc (size);
-  bzero (ct_table, size);
+  ct_table = xzalloc (size);
   ct_colors_allocated = 0;
 }
 
@@ -4266,7 +4158,7 @@ init_color_table ()
 /* Free memory associated with the color table.  */
 
 static void
-free_color_table ()
+free_color_table (void)
 {
   int i;
   struct ct_color *p, *next;
@@ -4289,9 +4181,7 @@ free_color_table ()
    G, B, and make an entry in the color table.  */
 
 static unsigned long
-lookup_rgb_color (f, r, g, b)
-     struct frame *f;
-     int r, g, b;
+lookup_rgb_color (struct frame *f, int r, int g, int b)
 {
   unsigned hash = CT_HASH_RGB (r, g, b);
   int i = hash % CT_SIZE;
@@ -4338,7 +4228,14 @@ lookup_rgb_color (f, r, g, b)
       XColor color;
       Colormap cmap;
       int rc;
+#else
+      COLORREF color;
+#endif
+
+      if (ct_colors_allocated_max <= ct_colors_allocated)
+       return FRAME_FOREGROUND_PIXEL (f);
 
+#ifdef HAVE_X_WINDOWS
       color.red = r;
       color.green = g;
       color.blue = b;
@@ -4348,7 +4245,7 @@ lookup_rgb_color (f, r, g, b)
       if (rc)
        {
          ++ct_colors_allocated;
-         p = (struct ct_color *) xmalloc (sizeof *p);
+         p = xmalloc (sizeof *p);
          p->r = r;
          p->g = g;
          p->b = b;
@@ -4360,14 +4257,13 @@ lookup_rgb_color (f, r, g, b)
        return FRAME_FOREGROUND_PIXEL (f);
 
 #else
-      COLORREF color;
 #ifdef HAVE_NTGUI
       color = PALETTERGB (r, g, b);
 #else
       color = RGB_TO_ULONG (r, g, b);
 #endif /* HAVE_NTGUI */
       ++ct_colors_allocated;
-      p = (struct ct_color *) xmalloc (sizeof *p);
+      p = xmalloc (sizeof *p);
       p->r = r;
       p->g = g;
       p->b = b;
@@ -4386,9 +4282,7 @@ lookup_rgb_color (f, r, g, b)
    table.  If not already present, allocate it.  Value is PIXEL.  */
 
 static unsigned long
-lookup_pixel_color (f, pixel)
-     struct frame *f;
-     unsigned long pixel;
+lookup_pixel_color (struct frame *f, unsigned long pixel)
 {
   int i = pixel % CT_SIZE;
   struct ct_color *p;
@@ -4403,25 +4297,28 @@ lookup_pixel_color (f, pixel)
       Colormap cmap;
       int rc;
 
+      if (ct_colors_allocated_max <= ct_colors_allocated)
+       return FRAME_FOREGROUND_PIXEL (f);
+
 #ifdef HAVE_X_WINDOWS
       cmap = FRAME_X_COLORMAP (f);
       color.pixel = pixel;
       x_query_color (f, &color);
       rc = x_alloc_nearest_color (f, cmap, &color);
 #else
-      BLOCK_INPUT;
+      block_input ();
       cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
       color.pixel = pixel;
       XQueryColor (NULL, cmap, &color);
       rc = x_alloc_nearest_color (f, cmap, &color);
-      UNBLOCK_INPUT;
+      unblock_input ();
 #endif /* HAVE_X_WINDOWS */
 
       if (rc)
        {
          ++ct_colors_allocated;
 
-         p = (struct ct_color *) xmalloc (sizeof *p);
+         p = xmalloc (sizeof *p);
          p->r = color.red;
          p->g = color.green;
          p->b = color.blue;
@@ -4440,8 +4337,7 @@ lookup_pixel_color (f, pixel)
    allocated via xmalloc.  Set *N to the number of colors.  */
 
 static unsigned long *
-colors_in_color_table (n)
-     int *n;
+colors_in_color_table (int *n)
 {
   int i, j;
   struct ct_color *p;
@@ -4454,8 +4350,7 @@ colors_in_color_table (n)
     }
   else
     {
-      colors = (unsigned long *) xmalloc (ct_colors_allocated
-                                         * sizeof *colors);
+      colors = xmalloc (ct_colors_allocated * sizeof *colors);
       *n = ct_colors_allocated;
 
       for (i = j = 0; i < CT_SIZE; ++i)
@@ -4469,9 +4364,7 @@ colors_in_color_table (n)
 #else /* COLOR_TABLE_SUPPORT */
 
 static unsigned long
-lookup_rgb_color (f, r, g, b)
-     struct frame *f;
-     int r, g, b;
+lookup_rgb_color (struct frame *f, int r, int g, int b)
 {
   unsigned long pixel;
 
@@ -4486,7 +4379,7 @@ lookup_rgb_color (f, r, g, b)
 }
 
 static void
-init_color_table ()
+init_color_table (void)
 {
 }
 #endif /* COLOR_TABLE_SUPPORT */
@@ -4496,19 +4389,14 @@ init_color_table ()
                              Algorithms
  ***********************************************************************/
 
-static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
-static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
-static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
+static XColor *x_to_xcolors (struct frame *, struct image *, int);
+static void x_from_xcolors (struct frame *, struct image *, XColor *);
+static void x_detect_edges (struct frame *, struct image *, int[9], int);
 
 #ifdef HAVE_NTGUI
 static void XPutPixel (XImagePtr , int, int, COLORREF);
 #endif /* HAVE_NTGUI */
 
-/* Non-zero means draw a cross on images having `:conversion
-   disabled'.  */
-
-int cross_disabled_images;
-
 /* Edge detection matrices for different edge-detection
    strategies.  */
 
@@ -4539,10 +4427,7 @@ static int laplace_matrix[9] = {
    allocated with xmalloc; it must be freed by the caller.  */
 
 static XColor *
-x_to_xcolors (f, img, rgb_p)
-     struct frame *f;
-     struct image *img;
-     int rgb_p;
+x_to_xcolors (struct frame *f, struct image *img, int rgb_p)
 {
   int x, y;
   XColor *colors, *p;
@@ -4552,7 +4437,9 @@ x_to_xcolors (f, img, rgb_p)
   HGDIOBJ prev;
 #endif /* HAVE_NTGUI */
 
-  colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
+  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height)
+    memory_full (SIZE_MAX);
+  colors = xmalloc (sizeof *colors * img->width * img->height);
 
 #ifndef HAVE_NTGUI
   /* Get the X image IMG->pixmap.  */
@@ -4571,9 +4458,8 @@ x_to_xcolors (f, img, rgb_p)
   p = colors;
   for (y = 0; y < img->height; ++y)
     {
-      XColor *row = p;
-
 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
+      XColor *row = p;
       for (x = 0; x < img->width; ++x, ++p)
        p->pixel = GET_PIXEL (ximg, x, y);
       if (rgb_p)
@@ -4607,13 +4493,9 @@ x_to_xcolors (f, img, rgb_p)
    stored in ximg->data.  */
 
 static void
-XPutPixel (ximg, x, y, color)
-     XImagePtr  ximg;
-     int x, y;
-     COLORREF color;
+XPutPixel (XImagePtr ximg, int x, int y, COLORREF color)
 {
   int width = ximg->info.bmiHeader.biWidth;
-  int height = ximg->info.bmiHeader.biHeight;
   unsigned char * pixel;
 
   /* True color images.  */
@@ -4655,10 +4537,7 @@ XPutPixel (ximg, x, y, color)
    COLORS will be freed; an existing IMG->pixmap will be freed, too.  */
 
 static void
-x_from_xcolors (f, img, colors)
-     struct frame *f;
-     struct image *img;
-     XColor *colors;
+x_from_xcolors (struct frame *f, struct image *img, XColor *colors)
 {
   int x, y;
   XImagePtr oimg = NULL;
@@ -4700,10 +4579,7 @@ x_from_xcolors (f, img, colors)
    outgoing image.  */
 
 static void
-x_detect_edges (f, img, matrix, color_adjust)
-     struct frame *f;
-     struct image *img;
-     int matrix[9], color_adjust;
+x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjust)
 {
   XColor *colors = x_to_xcolors (f, img, 1);
   XColor *new, *p;
@@ -4714,7 +4590,9 @@ x_detect_edges (f, img, matrix, color_adjust)
 
 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
 
-  new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
+  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height)
+    memory_full (SIZE_MAX);
+  new = xmalloc (sizeof *new * img->width * img->height);
 
   for (y = 0; y < img->height; ++y)
     {
@@ -4738,14 +4616,14 @@ x_detect_edges (f, img, matrix, color_adjust)
 
       for (x = 1; x < img->width - 1; ++x, ++p)
        {
-         int r, g, b, y1, x1;
+         int r, g, b, yy, xx;
 
          r = g = b = i = 0;
-         for (y1 = y - 1; y1 < y + 2; ++y1)
-           for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
+         for (yy = y - 1; yy < y + 2; ++yy)
+           for (xx = x - 1; xx < x + 2; ++xx, ++i)
              if (matrix[i])
                {
-                 XColor *t = COLOR (colors, x1, y1);
+                 XColor *t = COLOR (colors, xx, yy);
                  r += matrix[i] * t->red;
                  g += matrix[i] * t->green;
                  b += matrix[i] * t->blue;
@@ -4769,9 +4647,7 @@ x_detect_edges (f, img, matrix, color_adjust)
    on frame F.  */
 
 static void
-x_emboss (f, img)
-     struct frame *f;
-     struct image *img;
+x_emboss (struct frame *f, struct image *img)
 {
   x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
 }
@@ -4782,9 +4658,7 @@ x_emboss (f, img)
    to draw disabled buttons, for example.  */
 
 static void
-x_laplace (f, img)
-     struct frame *f;
-     struct image *img;
+x_laplace (struct frame *f, struct image *img)
 {
   x_detect_edges (f, img, laplace_matrix, 45000);
 }
@@ -4802,10 +4676,8 @@ x_laplace (f, img)
    number.  */
 
 static void
-x_edge_detection (f, img, matrix, color_adjust)
-     struct frame *f;
-     struct image *img;
-     Lisp_Object matrix, color_adjust;
+x_edge_detection (struct frame *f, struct image *img, Lisp_Object matrix,
+                 Lisp_Object color_adjust)
 {
   int i = 0;
   int trans[9];
@@ -4827,16 +4699,14 @@ x_edge_detection (f, img, matrix, color_adjust)
     color_adjust = make_number (0xffff / 2);
 
   if (i == 9 && NUMBERP (color_adjust))
-    x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
+    x_detect_edges (f, img, trans, XFLOATINT (color_adjust));
 }
 
 
 /* Transform image IMG on frame F so that it looks disabled.  */
 
 static void
-x_disable_image (f, img)
-     struct frame *f;
-     struct image *img;
+x_disable_image (struct frame *f, struct image *img)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 #ifdef HAVE_NTGUI
@@ -4872,14 +4742,12 @@ x_disable_image (f, img)
   if (n_planes < 2 || cross_disabled_images)
     {
 #ifndef HAVE_NTGUI
-      Display *dpy = FRAME_X_DISPLAY (f);
-      GC gc;
-
 #ifndef HAVE_NS  /* TODO: NS support, however this not needed for toolbars */
 
 #define MaskForeground(f)  WHITE_PIX_DEFAULT (f)
 
-      gc = XCreateGC (dpy, img->pixmap, 0, NULL);
+      Display *dpy = FRAME_X_DISPLAY (f);
+      GC gc = XCreateGC (dpy, img->pixmap, 0, NULL);
       XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
       XDrawLine (dpy, img->pixmap, gc, 0, 0,
                 img->width - 1, img->height - 1);
@@ -4938,10 +4806,7 @@ x_disable_image (f, img)
    heuristically.  Value is non-zero if successful. */
 
 static int
-x_build_heuristic_mask (f, img, how)
-     struct frame *f;
-     struct image *img;
-     Lisp_Object how;
+x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
 {
   XImagePtr_or_DC ximg;
 #ifndef HAVE_NTGUI
@@ -4978,8 +4843,7 @@ x_build_heuristic_mask (f, img, how)
 #else
   /* Create the bit array serving as mask.  */
   row_width = (img->width + 7) / 8;
-  mask_img = xmalloc (row_width * img->height);
-  bzero (mask_img, row_width * img->height);
+  mask_img = xzalloc (row_width * img->height);
 
   /* Create a memory device context for IMG->pixmap.  */
   frame_dc = get_frame_dc (f);
@@ -5028,7 +4892,7 @@ x_build_heuristic_mask (f, img, how)
                                  ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
 #else
       if (XGetPixel (ximg, x, y) == bg)
-        ns_set_alpha(ximg, x, y, 0);
+        ns_set_alpha (ximg, x, y, 0);
 #endif /* HAVE_NS */
 #ifndef HAVE_NS
   /* Fill in the background_transparent field while we have the mask handy. */
@@ -5068,13 +4932,13 @@ x_build_heuristic_mask (f, img, how)
                       PBM (mono, gray, color)
  ***********************************************************************/
 
-static int pbm_image_p P_ ((Lisp_Object object));
-static int pbm_load P_ ((struct frame *f, struct image *img));
-static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
+static int pbm_image_p (Lisp_Object object);
+static int pbm_load (struct frame *f, struct image *img);
+static int pbm_scan_number (unsigned char **, unsigned char *);
 
 /* The symbol `pbm' identifying images of this type.  */
 
-Lisp_Object Qpbm;
+static Lisp_Object Qpbm;
 
 /* Indices of image specification fields in gs_format, below.  */
 
@@ -5103,7 +4967,7 @@ static const struct image_keyword pbm_format[PBM_LAST] =
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -5120,6 +4984,7 @@ static struct image_type pbm_type =
   pbm_image_p,
   pbm_load,
   x_clear_image,
+  NULL,
   NULL
 };
 
@@ -5127,12 +4992,11 @@ static struct image_type pbm_type =
 /* Return non-zero if OBJECT is a valid PBM image specification.  */
 
 static int
-pbm_image_p (object)
-     Lisp_Object object;
+pbm_image_p (Lisp_Object object)
 {
   struct image_keyword fmt[PBM_LAST];
 
-  bcopy (pbm_format, fmt, sizeof fmt);
+  memcpy (fmt, pbm_format, sizeof fmt);
 
   if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
     return 0;
@@ -5147,15 +5011,14 @@ pbm_image_p (object)
    end of input.  */
 
 static int
-pbm_scan_number (s, end)
-     unsigned char **s, *end;
+pbm_scan_number (unsigned char **s, unsigned char *end)
 {
   int c = 0, val = -1;
 
   while (*s < end)
     {
       /* Skip white-space.  */
-      while (*s < end && (c = *(*s)++, isspace (c)))
+      while (*s < end && (c = *(*s)++, c_isspace (c)))
        ;
 
       if (c == '#')
@@ -5164,11 +5027,11 @@ pbm_scan_number (s, end)
          while (*s < end && (c = *(*s)++, c != '\n'))
            ;
        }
-      else if (isdigit (c))
+      else if (c_isdigit (c))
        {
          /* Read decimal number.  */
          val = c - '0';
-         while (*s < end && (c = *(*s)++, isdigit (c)))
+         while (*s < end && (c = *(*s)++, c_isdigit (c)))
            val = 10 * val + c - '0';
          break;
        }
@@ -5188,9 +5051,7 @@ pbm_scan_number (s, end)
    occurred.  *SIZE is set to the size of the file.  */
 
 static char *
-pbm_read_file (file, size)
-     Lisp_Object file;
-     int *size;
+pbm_read_file (Lisp_Object file, int *size)
 {
   FILE *fp = NULL;
   char *buf = NULL;
@@ -5198,7 +5059,8 @@ pbm_read_file (file, size)
 
   if (stat (SDATA (file), &st) == 0
       && (fp = fopen (SDATA (file), "rb")) != NULL
-      && (buf = (char *) xmalloc (st.st_size),
+      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
+      && (buf = xmalloc (st.st_size),
          fread (buf, 1, st.st_size, fp) == st.st_size))
     {
       *size = st.st_size;
@@ -5223,23 +5085,18 @@ pbm_read_file (file, size)
 /* Load PBM image IMG for use on frame F.  */
 
 static int
-pbm_load (f, img)
-     struct frame *f;
-     struct image *img;
+pbm_load (struct frame *f, struct image *img)
 {
   int raw_p, x, y;
   int width, height, max_color_idx = 0;
   XImagePtr ximg;
   Lisp_Object file, specified_file;
   enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
-  struct gcpro gcpro1;
   unsigned char *contents = NULL;
   unsigned char *end, *p;
-  int size;
+  ptrdiff_t size;
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
-  file = Qnil;
-  GCPRO1 (file);
 
   if (STRINGP (specified_file))
     {
@@ -5247,15 +5104,13 @@ pbm_load (f, img)
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-         UNGCPRO;
          return 0;
        }
 
-      contents = slurp_file (SDATA (file), &size);
+      contents = slurp_file (SSDATA (file), &size);
       if (contents == NULL)
        {
          image_error ("Error reading `%s'", file, Qnil);
-         UNGCPRO;
          return 0;
        }
 
@@ -5266,6 +5121,11 @@ pbm_load (f, img)
     {
       Lisp_Object data;
       data = image_spec_value (img->spec, QCdata, NULL);
+      if (!STRINGP (data))
+       {
+         image_error ("Invalid image data `%s'", data, Qnil);
+         return 0;
+       }
       p = SDATA (data);
       end = p + SBYTES (data);
     }
@@ -5276,7 +5136,6 @@ pbm_load (f, img)
       image_error ("Not a PBM image: `%s'", img->spec, Qnil);
     error:
       xfree (contents);
-      UNGCPRO;
       return 0;
     }
 
@@ -5347,7 +5206,7 @@ pbm_load (f, img)
       unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
 
       /* Parse the image specification.  */
-      bcopy (pbm_format, fmt, sizeof fmt);
+      memcpy (fmt, pbm_format, sizeof fmt);
       parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
 
       /* Get foreground and background colors, maybe allocate colors.  */
@@ -5478,7 +5337,6 @@ pbm_load (f, img)
      img->width = width;
      img->height = height; */
 
-  UNGCPRO;
   xfree (contents);
   return 1;
 }
@@ -5492,12 +5350,12 @@ pbm_load (f, img)
 
 /* Function prototypes.  */
 
-static int png_image_p P_ ((Lisp_Object object));
-static int png_load P_ ((struct frame *f, struct image *img));
+static int png_image_p (Lisp_Object object);
+static int png_load (struct frame *f, struct image *img);
 
 /* The symbol `png' identifying images of this type.  */
 
-Lisp_Object Qpng;
+static Lisp_Object Qpng;
 
 /* Indices of image specification fields in png_format, below.  */
 
@@ -5525,7 +5383,7 @@ static const struct image_keyword png_format[PNG_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -5533,6 +5391,12 @@ static const struct image_keyword png_format[PNG_LAST] =
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
+#ifdef HAVE_NTGUI
+static int init_png_functions (void);
+#else
+#define init_png_functions NULL
+#endif
+
 /* Structure describing the image type `png'.  */
 
 static struct image_type png_type =
@@ -5541,17 +5405,17 @@ static struct image_type png_type =
   png_image_p,
   png_load,
   x_clear_image,
+  init_png_functions,
   NULL
 };
 
 /* Return non-zero if OBJECT is a valid PNG image specification.  */
 
 static int
-png_image_p (object)
-     Lisp_Object object;
+png_image_p (Lisp_Object object)
 {
   struct image_keyword fmt[PNG_LAST];
-  bcopy (png_format, fmt, sizeof fmt);
+  memcpy (fmt, png_format, sizeof fmt);
 
   if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
     return 0;
@@ -5568,40 +5432,43 @@ png_image_p (object)
 #ifdef HAVE_NTGUI
 /* PNG library details.  */
 
-DEF_IMGLIB_FN (png_voidp, png_get_io_ptr);
-DEF_IMGLIB_FN (int, png_sig_cmp);
-DEF_IMGLIB_FN (png_structp, png_create_read_struct);
-DEF_IMGLIB_FN (png_infop, png_create_info_struct);
-DEF_IMGLIB_FN (void, png_destroy_read_struct);
-DEF_IMGLIB_FN (void, png_set_read_fn);
-DEF_IMGLIB_FN (void, png_set_sig_bytes);
-DEF_IMGLIB_FN (void, png_read_info);
-DEF_IMGLIB_FN (png_uint_32, png_get_IHDR);
-DEF_IMGLIB_FN (png_uint_32, png_get_valid);
-DEF_IMGLIB_FN (void, png_set_strip_16);
-DEF_IMGLIB_FN (void, png_set_expand);
-DEF_IMGLIB_FN (void, png_set_gray_to_rgb);
-DEF_IMGLIB_FN (void, png_set_background);
-DEF_IMGLIB_FN (png_uint_32, png_get_bKGD);
-DEF_IMGLIB_FN (void, png_read_update_info);
-DEF_IMGLIB_FN (png_byte, png_get_channels);
-DEF_IMGLIB_FN (png_size_t, png_get_rowbytes);
-DEF_IMGLIB_FN (void, png_read_image);
-DEF_IMGLIB_FN (void, png_read_end);
-DEF_IMGLIB_FN (void, png_error);
+DEF_IMGLIB_FN (png_voidp, png_get_io_ptr, (png_structp));
+DEF_IMGLIB_FN (int, png_sig_cmp, (png_bytep, png_size_t, png_size_t));
+DEF_IMGLIB_FN (png_structp, png_create_read_struct, (png_const_charp, png_voidp,
+                                                    png_error_ptr, png_error_ptr));
+DEF_IMGLIB_FN (png_infop, png_create_info_struct, (png_structp));
+DEF_IMGLIB_FN (void, png_destroy_read_struct, (png_structpp, png_infopp, png_infopp));
+DEF_IMGLIB_FN (void, png_set_read_fn, (png_structp, png_voidp, png_rw_ptr));
+DEF_IMGLIB_FN (void, png_set_sig_bytes, (png_structp, int));
+DEF_IMGLIB_FN (void, png_read_info, (png_structp, png_infop));
+DEF_IMGLIB_FN (png_uint_32, png_get_IHDR, (png_structp, png_infop,
+                             png_uint_32 *, png_uint_32 *,
+                             int *, int *, int *, int *, int *));
+DEF_IMGLIB_FN (png_uint_32, png_get_valid, (png_structp, png_infop, png_uint_32));
+DEF_IMGLIB_FN (void, png_set_strip_16, (png_structp));
+DEF_IMGLIB_FN (void, png_set_expand, (png_structp));
+DEF_IMGLIB_FN (void, png_set_gray_to_rgb, (png_structp));
+DEF_IMGLIB_FN (void, png_set_background, (png_structp, png_color_16p,
+                                   int, int, double));
+DEF_IMGLIB_FN (png_uint_32, png_get_bKGD, (png_structp, png_infop, png_color_16p *));
+DEF_IMGLIB_FN (void, png_read_update_info, (png_structp, png_infop));
+DEF_IMGLIB_FN (png_byte, png_get_channels, (png_structp, png_infop));
+DEF_IMGLIB_FN (png_size_t, png_get_rowbytes, (png_structp, png_infop));
+DEF_IMGLIB_FN (void, png_read_image, (png_structp, png_bytepp));
+DEF_IMGLIB_FN (void, png_read_end, (png_structp, png_infop));
+DEF_IMGLIB_FN (void, png_error, (png_structp, png_const_charp));
 
 #if (PNG_LIBPNG_VER >= 10500)
-DEF_IMGLIB_FN (void, png_longjmp);
-DEF_IMGLIB_FN (jmp_buf *, png_set_longjmp_fn);
+DEF_IMGLIB_FN (void, png_longjmp, (png_structp, int));
+DEF_IMGLIB_FN (jmp_buf *, png_set_longjmp_fn, (png_structp, png_longjmp_ptr, size_t));
 #endif /* libpng version >= 1.5 */
 
 static int
-init_png_functions (Lisp_Object libraries)
+init_png_functions (void)
 {
   HMODULE library;
 
-  /* Try loading libpng under probable names.  */
-  if (!(library = w32_delayed_load (libraries, Qpng)))
+  if (!(library = w32_delayed_load (Qpng)))
     return 0;
 
   LOAD_IMGLIB_FN (library, png_get_io_ptr);
@@ -5664,26 +5531,33 @@ init_png_functions (Lisp_Object libraries)
 
 #endif /* HAVE_NTGUI */
 
+/* Possibly inefficient/inexact substitutes for _setjmp and _longjmp.
+   Do not use sys_setjmp, as PNG supports only jmp_buf.  The _longjmp
+   substitute may munge the signal mask, but that should be OK here.
+   MinGW (MS-Windows) uses _setjmp and defines setjmp to _setjmp in
+   the system header setjmp.h; don't mess up that.  */
+#ifndef HAVE__SETJMP
+# define _setjmp(j) setjmp (j)
+# define _longjmp longjmp
+#endif
 
 #if (PNG_LIBPNG_VER < 10500)
-#define PNG_LONGJMP(ptr) (longjmp ((ptr)->jmpbuf, 1))
+#define PNG_LONGJMP(ptr) (_longjmp ((ptr)->jmpbuf, 1))
 #define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
 #else
 /* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908)  */
 #define PNG_LONGJMP(ptr) (fn_png_longjmp ((ptr), 1))
 #define PNG_JMPBUF(ptr) \
-  (*fn_png_set_longjmp_fn((ptr), longjmp, sizeof (jmp_buf)))
+  (*fn_png_set_longjmp_fn ((ptr), _longjmp, sizeof (jmp_buf)))
 #endif
 
 /* Error and warning handlers installed when the PNG library
    is initialized.  */
 
-static void
-my_png_error (png_ptr, msg)
-     png_struct *png_ptr;
-     char *msg;
+static _Noreturn void
+my_png_error (png_struct *png_ptr, const char *msg)
 {
-  xassert (png_ptr != NULL);
+  eassert (png_ptr != NULL);
   /* Avoid compiler warning about deprecated direct access to
      png_ptr's fields in libpng versions 1.4.x.  */
   image_error ("PNG error: %s", build_string (msg), Qnil);
@@ -5692,11 +5566,9 @@ my_png_error (png_ptr, msg)
 
 
 static void
-my_png_warning (png_ptr, msg)
-     png_struct *png_ptr;
-     char *msg;
+my_png_warning (png_struct *png_ptr, const char *msg)
 {
-  xassert (png_ptr != NULL);
+  eassert (png_ptr != NULL);
   image_error ("PNG warning: %s", build_string (msg), Qnil);
 }
 
@@ -5705,8 +5577,8 @@ my_png_warning (png_ptr, msg)
 struct png_memory_storage
 {
   unsigned char *bytes;                /* The data       */
-  size_t len;                  /* How big is it? */
-  int index;                   /* Where are we?  */
+  ptrdiff_t len;               /* How big is it? */
+  ptrdiff_t index;             /* Where are we?  */
 };
 
 
@@ -5715,10 +5587,7 @@ struct png_memory_storage
    bytes from the input to DATA.  */
 
 static void
-png_read_from_memory (png_ptr, data, length)
-     png_structp png_ptr;
-     png_bytep data;
-     png_size_t length;
+png_read_from_memory (png_structp png_ptr, png_bytep data, png_size_t length)
 {
   struct png_memory_storage *tbr
     = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
@@ -5726,7 +5595,7 @@ png_read_from_memory (png_ptr, data, length)
   if (length > tbr->len - tbr->index)
     fn_png_error (png_ptr, "Read error");
 
-  bcopy (tbr->bytes + tbr->index, data, length);
+  memcpy (data, tbr->bytes + tbr->index, length);
   tbr->index = tbr->index + length;
 }
 
@@ -5736,10 +5605,7 @@ png_read_from_memory (png_ptr, data, length)
    bytes from the input to DATA.  */
 
 static void
-png_read_from_file (png_ptr, data, length)
-     png_structp png_ptr;
-     png_bytep data;
-     png_size_t length;
+png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
 {
   FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
 
@@ -5751,22 +5617,31 @@ png_read_from_file (png_ptr, data, length)
 /* Load PNG image IMG for use on frame F.  Value is non-zero if
    successful.  */
 
+struct png_load_context
+{
+  /* These are members so that longjmp doesn't munge local variables.  */
+  png_struct *png_ptr;
+  png_info *info_ptr;
+  png_info *end_info;
+  FILE *fp;
+  png_byte *pixels;
+  png_byte **rows;
+};
+
 static int
-png_load (f, img)
-     struct frame *f;
-     struct image *img;
+png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
 {
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
-  int x, y, i;
+  int x, y;
+  ptrdiff_t i;
   XImagePtr ximg, mask_img = NULL;
-  struct gcpro gcpro1;
-  png_struct *png_ptr = NULL;
+  png_struct *png_ptr;
   png_info *info_ptr = NULL, *end_info = NULL;
-  FILE *volatile fp = NULL;
+  FILE *fp = NULL;
   png_byte sig[8];
-  png_byte * volatile pixels = NULL;
-  png_byte ** volatile rows = NULL;
+  png_byte *pixels = NULL;
+  png_byte **rows = NULL;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
   png_byte channels;
@@ -5777,8 +5652,6 @@ png_load (f, img)
   /* Find out what file to load.  */
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
-  file = Qnil;
-  GCPRO1 (file);
 
   if (NILP (specified_data))
     {
@@ -5786,16 +5659,14 @@ png_load (f, img)
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-         UNGCPRO;
          return 0;
        }
 
       /* Open the image file.  */
-      fp = fopen (SDATA (file), "rb");
+      fp = fopen (SSDATA (file), "rb");
       if (!fp)
        {
          image_error ("Cannot open image file `%s'", file, Qnil);
-         UNGCPRO;
          return 0;
        }
 
@@ -5804,13 +5675,18 @@ png_load (f, img)
          || fn_png_sig_cmp (sig, 0, sizeof sig))
        {
          image_error ("Not a PNG file: `%s'", file, Qnil);
-         UNGCPRO;
          fclose (fp);
          return 0;
        }
     }
   else
     {
+      if (!STRINGP (specified_data))
+       {
+         image_error ("Invalid image data `%s'", specified_data, Qnil);
+         return 0;
+       }
+
       /* Read from memory.  */
       tbr.bytes = SDATA (specified_data);
       tbr.len = SBYTES (specified_data);
@@ -5821,7 +5697,6 @@ png_load (f, img)
          || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig))
        {
          image_error ("Not a PNG image: `%s'", img->spec, Qnil);
-         UNGCPRO;
          return 0;
        }
 
@@ -5833,45 +5708,47 @@ png_load (f, img)
   png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
                                       NULL, my_png_error,
                                       my_png_warning);
-  if (!png_ptr)
+  if (png_ptr)
     {
-      if (fp) fclose (fp);
-      UNGCPRO;
-      return 0;
+      info_ptr = fn_png_create_info_struct (png_ptr);
+      end_info = fn_png_create_info_struct (png_ptr);
     }
 
-  info_ptr = fn_png_create_info_struct (png_ptr);
-  if (!info_ptr)
+  c->png_ptr = png_ptr;
+  c->info_ptr = info_ptr;
+  c->end_info = end_info;
+  c->fp = fp;
+  c->pixels = pixels;
+  c->rows = rows;
+
+  if (! (info_ptr && end_info))
     {
-      fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
-      if (fp) fclose (fp);
-      UNGCPRO;
-      return 0;
+      fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
+      png_ptr = 0;
     }
-
-  end_info = fn_png_create_info_struct (png_ptr);
-  if (!end_info)
+  if (! png_ptr)
     {
-      fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
       if (fp) fclose (fp);
-      UNGCPRO;
       return 0;
     }
 
   /* Set error jump-back.  We come back here when the PNG library
      detects an error.  */
-  if (setjmp (PNG_JMPBUF (png_ptr)))
+  if (_setjmp (PNG_JMPBUF (png_ptr)))
     {
     error:
-      if (png_ptr)
-        fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
-      xfree (pixels);
-      xfree (rows);
-      if (fp) fclose (fp);
-      UNGCPRO;
+      if (c->png_ptr)
+       fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
+      xfree (c->pixels);
+      xfree (c->rows);
+      if (c->fp)
+       fclose (c->fp);
       return 0;
     }
 
+  /* Silence a bogus diagnostic; see GCC bug 54561.  */
+  IF_LINT (fp = c->fp);
+
   /* Read image info.  */
   if (!NILP (specified_data))
     fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
@@ -5883,11 +5760,19 @@ png_load (f, img)
   fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                   &interlace_type, NULL, NULL);
 
-  if (!check_image_size (f, width, height))
+  if (! (width <= INT_MAX && height <= INT_MAX
+        && check_image_size (f, width, height)))
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       goto error;
     }
+
+  /* Create the X image and pixmap now, so that the work below can be
+     omitted if the image is too large for X.  */
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
+                                   &img->pixmap))
+    goto error;
+
   /* If image contains simply transparency data, we prefer to
      construct a clipping mask.  */
   if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
@@ -5926,11 +5811,11 @@ png_load (f, img)
        /* The user specified `:background', use that.  */
        {
          XColor color;
-         if (x_defined_color (f, SDATA (specified_bg), &color, 0))
+         if (x_defined_color (f, SSDATA (specified_bg), &color, 0))
            {
              png_color_16 user_bg;
 
-             bzero (&user_bg, sizeof user_bg);
+             memset (&user_bg, 0, sizeof user_bg);
              user_bg.red = color.red >> shift;
              user_bg.green = color.green >> shift;
              user_bg.blue = color.blue >> shift;
@@ -5950,7 +5835,7 @@ png_load (f, img)
          color.pixel = FRAME_BACKGROUND_PIXEL (f);
          x_query_color (f, &color);
 
-         bzero (&frame_background, sizeof frame_background);
+         memset (&frame_background, 0, sizeof frame_background);
          frame_background.red = color.red >> shift;
          frame_background.green = color.green >> shift;
          frame_background.blue = color.blue >> shift;
@@ -5970,14 +5855,17 @@ png_load (f, img)
      images with alpha channel, i.e. RGBA.  If conversions above were
      sufficient we should only have 3 or 4 channels here.  */
   channels = fn_png_get_channels (png_ptr, info_ptr);
-  xassert (channels == 3 || channels == 4);
+  eassert (channels == 3 || channels == 4);
 
   /* Number of bytes needed for one row of the image.  */
   row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
 
   /* Allocate memory for the image.  */
-  pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
-  rows = (png_byte **) xmalloc (height * sizeof *rows);
+  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height
+      || min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes)
+    memory_full (SIZE_MAX);
+  c->pixels = pixels = xmalloc (sizeof *pixels * row_bytes * height);
+  c->rows = rows = xmalloc (height * sizeof *rows);
   for (i = 0; i < height; ++i)
     rows[i] = pixels + i * row_bytes;
 
@@ -5987,14 +5875,9 @@ png_load (f, img)
   if (fp)
     {
       fclose (fp);
-      fp = NULL;
+      c->fp = NULL;
     }
 
-  /* Create the X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
-                                   &img->pixmap))
-    goto error;
-
   /* Create an image and pixmap serving as mask if the PNG image
      contains an alpha channel.  */
   if (channels == 4
@@ -6017,7 +5900,7 @@ png_load (f, img)
 
       for (x = 0; x < width; ++x)
        {
-         unsigned r, g, b;
+         int r, g, b;
 
          r = *p++ << 8;
          g = *p++ << 8;
@@ -6067,7 +5950,7 @@ png_load (f, img)
 #endif /* COLOR_TABLE_SUPPORT */
 
   /* Clean up.  */
-  fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
+  fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
   xfree (rows);
   xfree (pixels);
 
@@ -6093,19 +5976,25 @@ png_load (f, img)
       x_destroy_x_image (mask_img);
     }
 
-  UNGCPRO;
   return 1;
 }
 
+static int
+png_load (struct frame *f, struct image *img)
+{
+  struct png_load_context c;
+  return png_load_body (f, img, &c);
+}
+
 #else /* HAVE_PNG */
 
 #ifdef HAVE_NS
 static int
 png_load (struct frame *f, struct image *img)
 {
-  return ns_load_image(f, img,
-                       image_spec_value (img->spec, QCfile, NULL),
-                       image_spec_value (img->spec, QCdata, NULL));
+  return ns_load_image (f, img,
+                        image_spec_value (img->spec, QCfile, NULL),
+                        image_spec_value (img->spec, QCdata, NULL));
 }
 #endif  /* HAVE_NS */
 
@@ -6120,12 +6009,12 @@ png_load (struct frame *f, struct image *img)
 
 #if defined (HAVE_JPEG) || defined (HAVE_NS)
 
-static int jpeg_image_p P_ ((Lisp_Object object));
-static int jpeg_load P_ ((struct frame *f, struct image *img));
+static int jpeg_image_p (Lisp_Object object);
+static int jpeg_load (struct frame *f, struct image *img);
 
 /* The symbol `jpeg' identifying images of this type.  */
 
-Lisp_Object Qjpeg;
+static Lisp_Object Qjpeg;
 
 /* Indices of image specification fields in gs_format, below.  */
 
@@ -6153,7 +6042,7 @@ static const struct image_keyword jpeg_format[JPEG_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -6161,6 +6050,12 @@ static const struct image_keyword jpeg_format[JPEG_LAST] =
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
+#ifdef HAVE_NTGUI
+static int init_jpeg_functions (void);
+#else
+#define init_jpeg_functions NULL
+#endif
+
 /* Structure describing the image type `jpeg'.  */
 
 static struct image_type jpeg_type =
@@ -6169,18 +6064,18 @@ static struct image_type jpeg_type =
   jpeg_image_p,
   jpeg_load,
   x_clear_image,
+  init_jpeg_functions,
   NULL
 };
 
 /* Return non-zero if OBJECT is a valid JPEG image specification.  */
 
 static int
-jpeg_image_p (object)
-     Lisp_Object object;
+jpeg_image_p (Lisp_Object object)
 {
   struct image_keyword fmt[JPEG_LAST];
 
-  bcopy (jpeg_format, fmt, sizeof fmt);
+  memcpy (fmt, jpeg_format, sizeof fmt);
 
   if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
     return 0;
@@ -6196,7 +6091,6 @@ jpeg_image_p (object)
 /* Work around a warning about HAVE_STDLIB_H being redefined in
    jconfig.h.  */
 #ifdef HAVE_STDLIB_H
-#define HAVE_STDLIB_H_1
 #undef HAVE_STDLIB_H
 #endif /* HAVE_STLIB_H */
 
@@ -6216,21 +6110,21 @@ jpeg_image_p (object)
 #ifdef HAVE_NTGUI
 
 /* JPEG library details.  */
-DEF_IMGLIB_FN (void, jpeg_CreateDecompress);
-DEF_IMGLIB_FN (boolean, jpeg_start_decompress);
-DEF_IMGLIB_FN (boolean, jpeg_finish_decompress);
-DEF_IMGLIB_FN (void, jpeg_destroy_decompress);
-DEF_IMGLIB_FN (int, jpeg_read_header);
-DEF_IMGLIB_FN (JDIMENSION, jpeg_read_scanlines);
-DEF_IMGLIB_FN (struct jpeg_error_mgr *, jpeg_std_error);
-DEF_IMGLIB_FN (boolean, jpeg_resync_to_restart);
+DEF_IMGLIB_FN (void, jpeg_CreateDecompress, (j_decompress_ptr, int, size_t));
+DEF_IMGLIB_FN (boolean, jpeg_start_decompress, (j_decompress_ptr));
+DEF_IMGLIB_FN (boolean, jpeg_finish_decompress, (j_decompress_ptr));
+DEF_IMGLIB_FN (void, jpeg_destroy_decompress, (j_decompress_ptr));
+DEF_IMGLIB_FN (int, jpeg_read_header, (j_decompress_ptr, boolean));
+DEF_IMGLIB_FN (JDIMENSION, jpeg_read_scanlines, (j_decompress_ptr, JSAMPARRAY, JDIMENSION));
+DEF_IMGLIB_FN (struct jpeg_error_mgr *, jpeg_std_error, (struct jpeg_error_mgr *));
+DEF_IMGLIB_FN (boolean, jpeg_resync_to_restart, (j_decompress_ptr, int));
 
 static int
-init_jpeg_functions (Lisp_Object libraries)
+init_jpeg_functions (void)
 {
   HMODULE library;
 
-  if (!(library = w32_delayed_load (libraries, Qjpeg)))
+  if (!(library = w32_delayed_load (Qjpeg)))
     return 0;
 
   LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
@@ -6247,16 +6141,14 @@ init_jpeg_functions (Lisp_Object libraries)
 /* Wrapper since we can't directly assign the function pointer
    to another function pointer that was declared more completely easily.  */
 static boolean
-jpeg_resync_to_restart_wrapper (cinfo, desired)
-     j_decompress_ptr cinfo;
-     int desired;
+jpeg_resync_to_restart_wrapper (j_decompress_ptr cinfo, int desired)
 {
   return fn_jpeg_resync_to_restart (cinfo, desired);
 }
 
 #else
 
-#define fn_jpeg_CreateDecompress(a,b,c)        jpeg_create_decompress(a)
+#define fn_jpeg_CreateDecompress(a,b,c)        jpeg_create_decompress (a)
 #define fn_jpeg_start_decompress       jpeg_start_decompress
 #define fn_jpeg_finish_decompress      jpeg_finish_decompress
 #define fn_jpeg_destroy_decompress     jpeg_destroy_decompress
@@ -6270,16 +6162,29 @@ jpeg_resync_to_restart_wrapper (cinfo, desired)
 struct my_jpeg_error_mgr
 {
   struct jpeg_error_mgr pub;
-  jmp_buf setjmp_buffer;
+  sys_jmp_buf setjmp_buffer;
+
+  /* The remaining members are so that longjmp doesn't munge local
+     variables.  */
+  struct jpeg_decompress_struct cinfo;
+  enum
+    {
+      MY_JPEG_ERROR_EXIT,
+      MY_JPEG_INVALID_IMAGE_SIZE,
+      MY_JPEG_CANNOT_CREATE_X
+    } failure_code;
+#ifdef lint
+  FILE *fp;
+#endif
 };
 
 
-static void
-my_error_exit (cinfo)
-     j_common_ptr cinfo;
+static _Noreturn void
+my_error_exit (j_common_ptr cinfo)
 {
   struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
-  longjmp (mgr->setjmp_buffer, 1);
+  mgr->failure_code = MY_JPEG_ERROR_EXIT;
+  sys_longjmp (mgr->setjmp_buffer, 1);
 }
 
 
@@ -6288,8 +6193,7 @@ my_error_exit (cinfo)
    libjpeg.doc from the JPEG lib distribution.  */
 
 static void
-our_common_init_source (cinfo)
-     j_decompress_ptr cinfo;
+our_common_init_source (j_decompress_ptr cinfo)
 {
 }
 
@@ -6298,8 +6202,7 @@ our_common_init_source (cinfo)
    jpeg_finish_decompress() after all data has been processed.  */
 
 static void
-our_common_term_source (cinfo)
-     j_decompress_ptr cinfo;
+our_common_term_source (j_decompress_ptr cinfo)
 {
 }
 
@@ -6311,8 +6214,7 @@ our_common_term_source (cinfo)
 static JOCTET our_memory_buffer[2];
 
 static boolean
-our_memory_fill_input_buffer (cinfo)
-     j_decompress_ptr cinfo;
+our_memory_fill_input_buffer (j_decompress_ptr cinfo)
 {
   /* Insert a fake EOI marker.  */
   struct jpeg_source_mgr *src = cinfo->src;
@@ -6330,9 +6232,7 @@ our_memory_fill_input_buffer (cinfo)
    is the JPEG data source manager.  */
 
 static void
-our_memory_skip_input_data (cinfo, num_bytes)
-     j_decompress_ptr cinfo;
-     long num_bytes;
+our_memory_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
 {
   struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
 
@@ -6352,10 +6252,7 @@ our_memory_skip_input_data (cinfo, num_bytes)
    reading the image.  */
 
 static void
-jpeg_memory_src (cinfo, data, len)
-     j_decompress_ptr cinfo;
-     JOCTET *data;
-     unsigned int len;
+jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, ptrdiff_t len)
 {
   struct jpeg_source_mgr *src;
 
@@ -6398,15 +6295,14 @@ struct jpeg_stdio_mgr
    whenever more data is needed.  The data is read from a FILE *.  */
 
 static boolean
-our_stdio_fill_input_buffer (cinfo)
-     j_decompress_ptr cinfo;
+our_stdio_fill_input_buffer (j_decompress_ptr cinfo)
 {
   struct jpeg_stdio_mgr *src;
 
   src = (struct jpeg_stdio_mgr *) cinfo->src;
   if (!src->finished)
     {
-      size_t bytes;
+      ptrdiff_t bytes;
 
       bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
       if (bytes > 0)
@@ -6430,9 +6326,7 @@ our_stdio_fill_input_buffer (cinfo)
    is the JPEG data source manager.  */
 
 static void
-our_stdio_skip_input_data (cinfo, num_bytes)
-     j_decompress_ptr cinfo;
-     long num_bytes;
+our_stdio_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
 {
   struct jpeg_stdio_mgr *src;
   src = (struct jpeg_stdio_mgr *) cinfo->src;
@@ -6462,9 +6356,7 @@ our_stdio_skip_input_data (cinfo, num_bytes)
    reading the image.  */
 
 static void
-jpeg_file_src (cinfo, fp)
-     j_decompress_ptr cinfo;
-     FILE *fp;
+jpeg_file_src (j_decompress_ptr cinfo, FILE *fp)
 {
   struct jpeg_stdio_mgr *src;
 
@@ -6498,28 +6390,21 @@ jpeg_file_src (cinfo, fp)
    from the JPEG lib.  */
 
 static int
-jpeg_load (f, img)
-     struct frame *f;
-     struct image *img;
+jpeg_load_body (struct frame *f, struct image *img,
+               struct my_jpeg_error_mgr *mgr)
 {
-  struct jpeg_decompress_struct cinfo;
-  struct my_jpeg_error_mgr mgr;
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
-  FILE * volatile fp = NULL;
+  FILE *fp = NULL;
   JSAMPARRAY buffer;
   int row_stride, x, y;
   XImagePtr ximg = NULL;
-  int rc;
   unsigned long *colors;
   int width, height;
-  struct gcpro gcpro1;
 
   /* Open the JPEG file.  */
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
-  file = Qnil;
-  GCPRO1 (file);
 
   if (NILP (specified_data))
     {
@@ -6527,90 +6412,108 @@ jpeg_load (f, img)
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-         UNGCPRO;
          return 0;
        }
 
-      fp = fopen (SDATA (file), "rb");
+      fp = fopen (SSDATA (file), "rb");
       if (fp == NULL)
        {
          image_error ("Cannot open `%s'", file, Qnil);
-         UNGCPRO;
          return 0;
        }
     }
+  else if (!STRINGP (specified_data))
+    {
+      image_error ("Invalid image data `%s'", specified_data, Qnil);
+      return 0;
+    }
+
+  IF_LINT (mgr->fp = fp);
 
   /* Customize libjpeg's error handling to call my_error_exit when an
      error is detected.  This function will perform a longjmp.  */
-  cinfo.err = fn_jpeg_std_error (&mgr.pub);
-  mgr.pub.error_exit = my_error_exit;
-
-  if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
+  mgr->cinfo.err = fn_jpeg_std_error (&mgr->pub);
+  mgr->pub.error_exit = my_error_exit;
+  if (sys_setjmp (mgr->setjmp_buffer))
     {
-      if (rc == 1)
+      switch (mgr->failure_code)
        {
-         /* Called from my_error_exit.  Display a JPEG error.  */
-         char buffer[JMSG_LENGTH_MAX];
-         cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
-         image_error ("Error reading JPEG image `%s': %s", img->spec,
-                      build_string (buffer));
+       case MY_JPEG_ERROR_EXIT:
+         {
+           char buf[JMSG_LENGTH_MAX];
+           mgr->cinfo.err->format_message ((j_common_ptr) &mgr->cinfo, buf);
+           image_error ("Error reading JPEG image `%s': %s", img->spec,
+                        build_string (buf));
+           break;
+         }
+
+       case MY_JPEG_INVALID_IMAGE_SIZE:
+         image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+         break;
+
+       case MY_JPEG_CANNOT_CREATE_X:
+         break;
        }
 
       /* Close the input file and destroy the JPEG object.  */
       if (fp)
-       fclose ((FILE *) fp);
-      fn_jpeg_destroy_decompress (&cinfo);
+       fclose (fp);
+      fn_jpeg_destroy_decompress (&mgr->cinfo);
 
       /* If we already have an XImage, free that.  */
       x_destroy_x_image (ximg);
 
       /* Free pixmap and colors.  */
       x_clear_image (f, img);
-
-      UNGCPRO;
       return 0;
     }
 
+  /* Silence a bogus diagnostic; see GCC bug 54561.  */
+  IF_LINT (fp = mgr->fp);
+
   /* Create the JPEG decompression object.  Let it read from fp.
         Read the JPEG image header.  */
-  fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
+  fn_jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
 
   if (NILP (specified_data))
-    jpeg_file_src (&cinfo, (FILE *) fp);
+    jpeg_file_src (&mgr->cinfo, fp);
   else
-    jpeg_memory_src (&cinfo, SDATA (specified_data),
+    jpeg_memory_src (&mgr->cinfo, SDATA (specified_data),
                     SBYTES (specified_data));
 
-  fn_jpeg_read_header (&cinfo, 1);
+  fn_jpeg_read_header (&mgr->cinfo, 1);
 
   /* Customize decompression so that color quantization will be used.
         Start decompression.  */
-  cinfo.quantize_colors = 1;
-  fn_jpeg_start_decompress (&cinfo);
-  width = img->width = cinfo.output_width;
-  height = img->height = cinfo.output_height;
+  mgr->cinfo.quantize_colors = 1;
+  fn_jpeg_start_decompress (&mgr->cinfo);
+  width = img->width = mgr->cinfo.output_width;
+  height = img->height = mgr->cinfo.output_height;
 
   if (!check_image_size (f, width, height))
     {
-      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
-      longjmp (mgr.setjmp_buffer, 2);
+      mgr->failure_code = MY_JPEG_INVALID_IMAGE_SIZE;
+      sys_longjmp (mgr->setjmp_buffer, 1);
     }
 
   /* Create X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
-    longjmp (mgr.setjmp_buffer, 2);
+    {
+      mgr->failure_code = MY_JPEG_CANNOT_CREATE_X;
+      sys_longjmp (mgr->setjmp_buffer, 1);
+    }
 
   /* Allocate colors.  When color quantization is used,
-     cinfo.actual_number_of_colors has been set with the number of
-     colors generated, and cinfo.colormap is a two-dimensional array
-     of color indices in the range 0..cinfo.actual_number_of_colors.
+     mgr->cinfo.actual_number_of_colors has been set with the number of
+     colors generated, and mgr->cinfo.colormap is a two-dimensional array
+     of color indices in the range 0..mgr->cinfo.actual_number_of_colors.
      No more than 255 colors will be generated.  */
   {
     int i, ir, ig, ib;
 
-    if (cinfo.out_color_components > 2)
+    if (mgr->cinfo.out_color_components > 2)
       ir = 0, ig = 1, ib = 2;
-    else if (cinfo.out_color_components > 1)
+    else if (mgr->cinfo.out_color_components > 1)
       ir = 0, ig = 1, ib = 0;
     else
       ir = 0, ig = 0, ib = 0;
@@ -6620,16 +6523,15 @@ jpeg_load (f, img)
        a default color, and we don't have to care about which colors
        can be freed safely, and which can't.  */
     init_color_table ();
-    colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
-                                      * sizeof *colors);
+    colors = alloca (mgr->cinfo.actual_number_of_colors * sizeof *colors);
 
-    for (i = 0; i < cinfo.actual_number_of_colors; ++i)
+    for (i = 0; i < mgr->cinfo.actual_number_of_colors; ++i)
       {
        /* Multiply RGB values with 255 because X expects RGB values
           in the range 0..0xffff.  */
-       int r = cinfo.colormap[ir][i] << 8;
-       int g = cinfo.colormap[ig][i] << 8;
-       int b = cinfo.colormap[ib][i] << 8;
+       int r = mgr->cinfo.colormap[ir][i] << 8;
+       int g = mgr->cinfo.colormap[ig][i] << 8;
+       int b = mgr->cinfo.colormap[ib][i] << 8;
        colors[i] = lookup_rgb_color (f, r, g, b);
       }
 
@@ -6641,21 +6543,21 @@ jpeg_load (f, img)
   }
 
   /* Read pixels.  */
-  row_stride = width * cinfo.output_components;
-  buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
-                                   row_stride, 1);
+  row_stride = width * mgr->cinfo.output_components;
+  buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo,
+                                        JPOOL_IMAGE, row_stride, 1);
   for (y = 0; y < height; ++y)
     {
-      fn_jpeg_read_scanlines (&cinfo, buffer, 1);
-      for (x = 0; x < cinfo.output_width; ++x)
+      fn_jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
+      for (x = 0; x < mgr->cinfo.output_width; ++x)
        XPutPixel (ximg, x, y, colors[buffer[0][x]]);
     }
 
   /* Clean up.  */
-  fn_jpeg_finish_decompress (&cinfo);
-  fn_jpeg_destroy_decompress (&cinfo);
+  fn_jpeg_finish_decompress (&mgr->cinfo);
+  fn_jpeg_destroy_decompress (&mgr->cinfo);
   if (fp)
-    fclose ((FILE *) fp);
+    fclose (fp);
 
   /* Maybe fill in the background field while we have ximg handy. */
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
@@ -6665,19 +6567,25 @@ jpeg_load (f, img)
   /* Put the image into the pixmap.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
-  UNGCPRO;
   return 1;
 }
 
+static int
+jpeg_load (struct frame *f, struct image *img)
+{
+  struct my_jpeg_error_mgr mgr;
+  return jpeg_load_body (f, img, &mgr);
+}
+
 #else /* HAVE_JPEG */
 
 #ifdef HAVE_NS
 static int
 jpeg_load (struct frame *f, struct image *img)
 {
-  return ns_load_image(f, img,
-                       image_spec_value (img->spec, QCfile, NULL),
-                       image_spec_value (img->spec, QCdata, NULL));
+  return ns_load_image (f, img,
+                       image_spec_value (img->spec, QCfile, NULL),
+                       image_spec_value (img->spec, QCdata, NULL));
 }
 #endif  /* HAVE_NS */
 
@@ -6691,12 +6599,12 @@ jpeg_load (struct frame *f, struct image *img)
 
 #if defined (HAVE_TIFF) || defined (HAVE_NS)
 
-static int tiff_image_p P_ ((Lisp_Object object));
-static int tiff_load P_ ((struct frame *f, struct image *img));
+static int tiff_image_p (Lisp_Object object);
+static int tiff_load (struct frame *f, struct image *img);
 
 /* The symbol `tiff' identifying images of this type.  */
 
-Lisp_Object Qtiff;
+static Lisp_Object Qtiff;
 
 /* Indices of image specification fields in tiff_format, below.  */
 
@@ -6725,7 +6633,7 @@ static const struct image_keyword tiff_format[TIFF_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -6734,6 +6642,12 @@ static const struct image_keyword tiff_format[TIFF_LAST] =
   {":index",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0}
 };
 
+#ifdef HAVE_NTGUI
+static int init_tiff_functions (void);
+#else
+#define init_tiff_functions NULL
+#endif
+
 /* Structure describing the image type `tiff'.  */
 
 static struct image_type tiff_type =
@@ -6742,17 +6656,17 @@ static struct image_type tiff_type =
   tiff_image_p,
   tiff_load,
   x_clear_image,
+  init_tiff_functions,
   NULL
 };
 
 /* Return non-zero if OBJECT is a valid TIFF image specification.  */
 
 static int
-tiff_image_p (object)
-     Lisp_Object object;
+tiff_image_p (Lisp_Object object)
 {
   struct image_keyword fmt[TIFF_LAST];
-  bcopy (tiff_format, fmt, sizeof fmt);
+  memcpy (fmt, tiff_format, sizeof fmt);
 
   if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
     return 0;
@@ -6770,21 +6684,24 @@ tiff_image_p (object)
 #ifdef HAVE_NTGUI
 
 /* TIFF library details.  */
-DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetErrorHandler);
-DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetWarningHandler);
-DEF_IMGLIB_FN (TIFF *, TIFFOpen);
-DEF_IMGLIB_FN (TIFF *, TIFFClientOpen);
-DEF_IMGLIB_FN (int, TIFFGetField);
-DEF_IMGLIB_FN (int, TIFFReadRGBAImage);
-DEF_IMGLIB_FN (void, TIFFClose);
-DEF_IMGLIB_FN (int, TIFFSetDirectory);
+DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetErrorHandler, (TIFFErrorHandler));
+DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetWarningHandler, (TIFFErrorHandler));
+DEF_IMGLIB_FN (TIFF *, TIFFOpen, (const char *, const char *));
+DEF_IMGLIB_FN (TIFF *, TIFFClientOpen, (const char *, const char *, thandle_t,
+                               TIFFReadWriteProc, TIFFReadWriteProc,
+                               TIFFSeekProc, TIFFCloseProc, TIFFSizeProc,
+                               TIFFMapFileProc, TIFFUnmapFileProc));
+DEF_IMGLIB_FN (int, TIFFGetField, (TIFF *, ttag_t, ...));
+DEF_IMGLIB_FN (int, TIFFReadRGBAImage, (TIFF *, uint32, uint32, uint32 *, int));
+DEF_IMGLIB_FN (void, TIFFClose, (TIFF *));
+DEF_IMGLIB_FN (int, TIFFSetDirectory, (TIFF *, tdir_t));
 
 static int
-init_tiff_functions (Lisp_Object libraries)
+init_tiff_functions (void)
 {
   HMODULE library;
 
-  if (!(library = w32_delayed_load (libraries, Qtiff)))
+  if (!(library = w32_delayed_load (Qtiff)))
     return 0;
 
   LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
@@ -6823,43 +6740,33 @@ init_tiff_functions (Lisp_Object libraries)
 typedef struct
 {
   unsigned char *bytes;
-  size_t len;
-  int index;
+  ptrdiff_t len;
+  ptrdiff_t index;
 }
 tiff_memory_source;
 
-static size_t
-tiff_read_from_memory (data, buf, size)
-     thandle_t data;
-     tdata_t buf;
-     tsize_t size;
+static tsize_t
+tiff_read_from_memory (thandle_t data, tdata_t buf, tsize_t size)
 {
   tiff_memory_source *src = (tiff_memory_source *) data;
 
-  if (size > src->len - src->index)
-    return (size_t) -1;
-  bcopy (src->bytes + src->index, buf, size);
+  size = min (size, src->len - src->index);
+  memcpy (buf, src->bytes + src->index, size);
   src->index += size;
   return size;
 }
 
-static size_t
-tiff_write_from_memory (data, buf, size)
-     thandle_t data;
-     tdata_t buf;
-     tsize_t size;
+static tsize_t
+tiff_write_from_memory (thandle_t data, tdata_t buf, tsize_t size)
 {
-  return (size_t) -1;
+  return -1;
 }
 
 static toff_t
-tiff_seek_in_memory (data, off, whence)
-     thandle_t data;
-     toff_t off;
-     int whence;
+tiff_seek_in_memory (thandle_t data, toff_t off, int whence)
 {
   tiff_memory_source *src = (tiff_memory_source *) data;
-  int idx;
+  ptrdiff_t idx;
 
   switch (whence)
     {
@@ -6887,65 +6794,75 @@ tiff_seek_in_memory (data, off, whence)
 }
 
 static int
-tiff_close_memory (data)
-     thandle_t data;
+tiff_close_memory (thandle_t data)
 {
   /* NOOP */
   return 0;
 }
 
 static int
-tiff_mmap_memory (data, pbase, psize)
-     thandle_t data;
-     tdata_t *pbase;
-     toff_t *psize;
+tiff_mmap_memory (thandle_t data, tdata_t *pbase, toff_t *psize)
 {
   /* It is already _IN_ memory. */
   return 0;
 }
 
 static void
-tiff_unmap_memory (data, base, size)
-     thandle_t data;
-     tdata_t base;
-     toff_t size;
+tiff_unmap_memory (thandle_t data, tdata_t base, toff_t size)
 {
   /* We don't need to do this. */
 }
 
 static toff_t
-tiff_size_of_memory (data)
-     thandle_t data;
+tiff_size_of_memory (thandle_t data)
 {
   return ((tiff_memory_source *) data)->len;
 }
 
+/* GCC 3.x on x86 Windows targets has a bug that triggers an internal
+   compiler error compiling tiff_handler, see Bugzilla bug #17406
+   (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17406).  Declaring
+   this function as external works around that problem.  */
+#if defined (__MINGW32__) && __GNUC__ == 3
+# define MINGW_STATIC
+#else
+# define MINGW_STATIC static
+#endif
 
+MINGW_STATIC void
+tiff_handler (const char *, const char *, const char *, va_list)
+  ATTRIBUTE_FORMAT_PRINTF (3, 0);
+MINGW_STATIC void
+tiff_handler (const char *log_format, const char *title,
+             const char *format, va_list ap)
+{
+  /* doprnt is not suitable here, as TIFF handlers are called from
+     libtiff and are passed arbitrary printf directives.  Instead, use
+     vsnprintf, taking care to be portable to nonstandard environments
+     where vsnprintf returns -1 on buffer overflow.  Since it's just a
+     log entry, it's OK to truncate it.  */
+  char buf[4000];
+  int len = vsnprintf (buf, sizeof buf, format, ap);
+  add_to_log (log_format, build_string (title),
+             make_string (buf, max (0, min (len, sizeof buf - 1))));
+}
+#undef MINGW_STATIC
+
+static void tiff_error_handler (const char *, const char *, va_list)
+  ATTRIBUTE_FORMAT_PRINTF (2, 0);
 static void
-tiff_error_handler (title, format, ap)
-     const char *title, *format;
-     va_list ap;
+tiff_error_handler (const char *title, const char *format, va_list ap)
 {
-  char buf[512];
-  int len;
-
-  len = sprintf (buf, "TIFF error: %s ", title);
-  vsprintf (buf + len, format, ap);
-  add_to_log (buf, Qnil, Qnil);
+  tiff_handler ("TIFF error: %s %s", title, format, ap);
 }
 
 
+static void tiff_warning_handler (const char *, const char *, va_list)
+  ATTRIBUTE_FORMAT_PRINTF (2, 0);
 static void
-tiff_warning_handler (title, format, ap)
-     const char *title, *format;
-     va_list ap;
+tiff_warning_handler (const char *title, const char *format, va_list ap)
 {
-  char buf[512];
-  int len;
-
-  len = sprintf (buf, "TIFF warning: %s ", title);
-  vsprintf (buf + len, format, ap);
-  add_to_log (buf, Qnil, Qnil);
+  tiff_handler ("TIFF warning: %s %s", title, format, ap);
 }
 
 
@@ -6953,28 +6870,23 @@ tiff_warning_handler (title, format, ap)
    successful.  */
 
 static int
-tiff_load (f, img)
-     struct frame *f;
-     struct image *img;
+tiff_load (struct frame *f, struct image *img)
 {
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
   TIFF *tiff;
   int width, height, x, y, count;
   uint32 *buf;
-  int rc, rc2;
+  int rc;
   XImagePtr ximg;
-  struct gcpro gcpro1;
   tiff_memory_source memsrc;
   Lisp_Object image;
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
-  file = Qnil;
-  GCPRO1 (file);
 
-  fn_TIFFSetErrorHandler (tiff_error_handler);
-  fn_TIFFSetWarningHandler (tiff_warning_handler);
+  fn_TIFFSetErrorHandler ((TIFFErrorHandler) tiff_error_handler);
+  fn_TIFFSetWarningHandler ((TIFFErrorHandler) tiff_warning_handler);
 
   if (NILP (specified_data))
     {
@@ -6983,29 +6895,33 @@ tiff_load (f, img)
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-         UNGCPRO;
          return 0;
        }
 
       /* Try to open the image file.  */
-      tiff = fn_TIFFOpen (SDATA (file), "r");
+      tiff = fn_TIFFOpen (SSDATA (file), "r");
       if (tiff == NULL)
        {
          image_error ("Cannot open `%s'", file, Qnil);
-         UNGCPRO;
          return 0;
        }
     }
   else
     {
+      if (!STRINGP (specified_data))
+       {
+         image_error ("Invalid image data `%s'", specified_data, Qnil);
+         return 0;
+       }
+
       /* Memory source! */
       memsrc.bytes = SDATA (specified_data);
       memsrc.len = SBYTES (specified_data);
       memsrc.index = 0;
 
-      tiff = fn_TIFFClientOpen ("memory_source", "r", &memsrc,
-                               (TIFFReadWriteProc) tiff_read_from_memory,
-                               (TIFFReadWriteProc) tiff_write_from_memory,
+      tiff = fn_TIFFClientOpen ("memory_source", "r", (thandle_t)&memsrc,
+                               tiff_read_from_memory,
+                               tiff_write_from_memory,
                                tiff_seek_in_memory,
                                tiff_close_memory,
                                tiff_size_of_memory,
@@ -7015,7 +6931,6 @@ tiff_load (f, img)
       if (!tiff)
        {
          image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
-         UNGCPRO;
          return 0;
        }
     }
@@ -7023,13 +6938,13 @@ tiff_load (f, img)
   image = image_spec_value (img->spec, QCindex, NULL);
   if (INTEGERP (image))
     {
-      int ino = XFASTINT (image);
-      if (!fn_TIFFSetDirectory (tiff, ino))
+      EMACS_INT ino = XFASTINT (image);
+      if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t)
+            && fn_TIFFSetDirectory (tiff, ino)))
        {
          image_error ("Invalid image number `%s' in image `%s'",
                       image, img->spec);
          fn_TIFFClose (tiff);
-         UNGCPRO;
          return 0;
        }
     }
@@ -7043,37 +6958,36 @@ tiff_load (f, img)
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       fn_TIFFClose (tiff);
-      UNGCPRO;
       return 0;
     }
 
-  buf = (uint32 *) xmalloc (width * height * sizeof *buf);
+  /* Create the X image and pixmap.  */
+  if (! (height <= min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width
+        && x_create_x_image_and_pixmap (f, width, height, 0,
+                                        &ximg, &img->pixmap)))
+    {
+      fn_TIFFClose (tiff);
+      return 0;
+    }
+
+  buf = xmalloc (sizeof *buf * width * height);
 
   rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
 
   /* Count the number of images in the file.  */
-  for (count = 1, rc2 = 1; rc2; count++)
-    rc2 = fn_TIFFSetDirectory (tiff, count);
+  for (count = 1; fn_TIFFSetDirectory (tiff, count); count++)
+    continue;
 
   if (count > 1)
-    img->data.lisp_val = Fcons (Qcount,
-                               Fcons (make_number (count),
-                                      img->data.lisp_val));
+    img->lisp_data = Fcons (Qcount,
+                           Fcons (make_number (count),
+                                  img->lisp_data));
 
   fn_TIFFClose (tiff);
   if (!rc)
     {
       image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
       xfree (buf);
-      UNGCPRO;
-      return 0;
-    }
-
-  /* Create the X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
-    {
-      xfree (buf);
-      UNGCPRO;
       return 0;
     }
 
@@ -7114,7 +7028,6 @@ tiff_load (f, img)
   x_destroy_x_image (ximg);
   xfree (buf);
 
-  UNGCPRO;
   return 1;
 }
 
@@ -7124,9 +7037,9 @@ tiff_load (f, img)
 static int
 tiff_load (struct frame *f, struct image *img)
 {
-  return ns_load_image(f, img,
-                       image_spec_value (img->spec, QCfile, NULL),
-                       image_spec_value (img->spec, QCdata, NULL));
+  return ns_load_image (f, img,
+                        image_spec_value (img->spec, QCfile, NULL),
+                        image_spec_value (img->spec, QCdata, NULL));
 }
 #endif  /* HAVE_NS */
 
@@ -7140,13 +7053,13 @@ tiff_load (struct frame *f, struct image *img)
 
 #if defined (HAVE_GIF) || defined (HAVE_NS)
 
-static int gif_image_p P_ ((Lisp_Object object));
-static int gif_load P_ ((struct frame *f, struct image *img));
-static void gif_clear_image P_ ((struct frame *f, struct image *img));
+static int gif_image_p (Lisp_Object object);
+static int gif_load (struct frame *f, struct image *img);
+static void gif_clear_image (struct frame *f, struct image *img);
 
 /* The symbol `gif' identifying images of this type.  */
 
-Lisp_Object Qgif;
+static Lisp_Object Qgif;
 
 /* Indices of image specification fields in gif_format, below.  */
 
@@ -7175,7 +7088,7 @@ static const struct image_keyword gif_format[GIF_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -7184,6 +7097,12 @@ static const struct image_keyword gif_format[GIF_LAST] =
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
+#ifdef HAVE_NTGUI
+static int init_gif_functions (void);
+#else
+#define init_gif_functions NULL
+#endif
+
 /* Structure describing the image type `gif'.  */
 
 static struct image_type gif_type =
@@ -7192,29 +7111,26 @@ static struct image_type gif_type =
   gif_image_p,
   gif_load,
   gif_clear_image,
+  init_gif_functions,
   NULL
 };
 
 /* Free X resources of GIF image IMG which is used on frame F.  */
 
 static void
-gif_clear_image (f, img)
-     struct frame *f;
-     struct image *img;
+gif_clear_image (struct frame *f, struct image *img)
 {
-  /* IMG->data.ptr_val may contain extension data.  */
-  img->data.lisp_val = Qnil;
+  img->lisp_data = Qnil;
   x_clear_image (f, img);
 }
 
 /* Return non-zero if OBJECT is a valid GIF image specification.  */
 
 static int
-gif_image_p (object)
-     Lisp_Object object;
+gif_image_p (Lisp_Object object)
 {
   struct image_keyword fmt[GIF_LAST];
-  bcopy (gif_format, fmt, sizeof fmt);
+  memcpy (fmt, gif_format, sizeof fmt);
 
   if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
     return 0;
@@ -7248,17 +7164,17 @@ gif_image_p (object)
 #ifdef HAVE_NTGUI
 
 /* GIF library details.  */
-DEF_IMGLIB_FN (int, DGifCloseFile);
-DEF_IMGLIB_FN (int, DGifSlurp);
-DEF_IMGLIB_FN (GifFileType *, DGifOpen);
-DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName);
+DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *));
+DEF_IMGLIB_FN (int, DGifSlurp, (GifFileType *));
+DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc));
+DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *));
 
 static int
-init_gif_functions (Lisp_Object libraries)
+init_gif_functions (void)
 {
   HMODULE library;
 
-  if (!(library = w32_delayed_load (libraries, Qgif)))
+  if (!(library = w32_delayed_load (Qgif)))
     return 0;
 
   LOAD_IMGLIB_FN (library, DGifCloseFile);
@@ -7283,8 +7199,8 @@ init_gif_functions (Lisp_Object libraries)
 typedef struct
 {
   unsigned char *bytes;
-  size_t len;
-  int index;
+  ptrdiff_t len;
+  ptrdiff_t index;
 }
 gif_memory_source;
 
@@ -7294,17 +7210,14 @@ gif_memory_source;
 static gif_memory_source *current_gif_memory_src;
 
 static int
-gif_read_from_memory (file, buf, len)
-     GifFileType *file;
-     GifByteType *buf;
-     int len;
+gif_read_from_memory (GifFileType *file, GifByteType *buf, int len)
 {
   gif_memory_source *src = current_gif_memory_src;
 
   if (len > src->len - src->index)
     return -1;
 
-  bcopy (src->bytes + src->index, buf, len);
+  memcpy (buf, src->bytes + src->index, len);
   src->index += len;
   return len;
 }
@@ -7316,28 +7229,23 @@ gif_read_from_memory (file, buf, len)
 static const int interlace_start[] = {0, 4, 2, 1};
 static const int interlace_increment[] = {8, 8, 4, 2};
 
+#define GIF_LOCAL_DESCRIPTOR_EXTENSION 249
+
 static int
-gif_load (f, img)
-     struct frame *f;
-     struct image *img;
+gif_load (struct frame *f, struct image *img)
 {
-  Lisp_Object file, specified_file;
-  Lisp_Object specified_data;
-  int rc, width, height, x, y, i;
+  Lisp_Object file;
+  int rc, width, height, x, y, i, j;
   XImagePtr ximg;
   ColorMapObject *gif_color_map;
   unsigned long pixel_colors[256];
   GifFileType *gif;
-  struct gcpro gcpro1;
-  Lisp_Object image;
-  int ino, image_height, image_width;
   gif_memory_source memsrc;
-  unsigned char *raster;
-
-  specified_file = image_spec_value (img->spec, QCfile, NULL);
-  specified_data = image_spec_value (img->spec, QCdata, NULL);
-  file = Qnil;
-  GCPRO1 (file);
+  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;
+  EMACS_INT idx;
 
   if (NILP (specified_data))
     {
@@ -7345,21 +7253,25 @@ gif_load (f, img)
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-         UNGCPRO;
          return 0;
        }
 
       /* Open the GIF file.  */
-      gif = fn_DGifOpenFileName (SDATA (file));
+      gif = fn_DGifOpenFileName (SSDATA (file));
       if (gif == NULL)
        {
          image_error ("Cannot open `%s'", file, Qnil);
-         UNGCPRO;
          return 0;
        }
     }
   else
     {
+      if (!STRINGP (specified_data))
+       {
+         image_error ("Invalid image data `%s'", specified_data, Qnil);
+         return 0;
+       }
+
       /* Read from memory! */
       current_gif_memory_src = &memsrc;
       memsrc.bytes = SDATA (specified_data);
@@ -7370,7 +7282,6 @@ gif_load (f, img)
       if (!gif)
        {
          image_error ("Cannot open memory source `%s'", img->spec, Qnil);
-         UNGCPRO;
          return 0;
        }
     }
@@ -7380,50 +7291,45 @@ gif_load (f, img)
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       fn_DGifCloseFile (gif);
-      UNGCPRO;
       return 0;
     }
 
   /* 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);
-      UNGCPRO;
       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);
-      UNGCPRO;
-      return 0;
-    }
+  /* 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)
+      {
+       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[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
-  image_width = gif->SavedImages[ino].ImageDesc.Width;
-  img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
+  width = img->width = gif->SWidth;
+  height = img->height = gif->SHeight;
 
-  width = img->width = max (gif->SWidth,
-                           max (gif->Image.Left + gif->Image.Width,
-                                img->corners[RIGHT_CORNER]));
-  height = img->height = max (gif->SHeight,
-                             max (gif->Image.Top + gif->Image.Height,
-                                  img->corners[BOT_CORNER]));
+  img->corners[TOP_CORNER] = gif->SavedImages[0].ImageDesc.Top;
+  img->corners[LEFT_CORNER] = gif->SavedImages[0].ImageDesc.Left;
+  img->corners[BOT_CORNER]
+    = img->corners[TOP_CORNER] + gif->SavedImages[0].ImageDesc.Height;
+  img->corners[RIGHT_CORNER]
+    = img->corners[LEFT_CORNER] + gif->SavedImages[0].ImageDesc.Width;
 
   if (!check_image_size (f, width, height))
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       fn_DGifCloseFile (gif);
-      UNGCPRO;
       return 0;
     }
 
@@ -7431,36 +7337,13 @@ gif_load (f, img)
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     {
       fn_DGifCloseFile (gif);
-      UNGCPRO;
       return 0;
     }
 
-  /* Allocate colors.  */
-  gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
-  if (!gif_color_map)
-    gif_color_map = gif->SColorMap;
-  init_color_table ();
-  bzero (pixel_colors, sizeof pixel_colors);
-
-  if (gif_color_map)
-    for (i = 0; i < gif_color_map->ColorCount; ++i)
-      {
-        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));
@@ -7477,65 +7360,157 @@ gif_load (f, 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;
+      int subimg_width = subimage->ImageDesc.Width;
+      int subimg_height = subimage->ImageDesc.Height;
+      int subimg_top = subimage->ImageDesc.Top;
+      int subimg_left = subimage->ImageDesc.Left;
+
+      /* 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 i = raster[(y * image_width) + x];
-             XPutPixel (ximg, x + img->corners[LEFT_CORNER],
-                        row + img->corners[TOP_CORNER], pixel_colors[i]);
+             /* 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;
+
+      /* For disposal == 0, the spec says "No disposal specified. The
+        decoder is not required to take any action."  In practice, it
+        seems we need to treat this like "keep in place", see e.g.
+        http://upload.wikimedia.org/wikipedia/commons/3/37/Clock.gif */
+      if (disposal == 0)
+       disposal = 1;
+
+      /* 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 i = raster[y * image_width + x];
-           XPutPixel (ximg, x + img->corners[LEFT_CORNER],
-                      y + img->corners[TOP_CORNER], pixel_colors[i]);
+           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 < subimg_height;
+              y++, row += interlace_increment[pass])
+           {
+             if (row >= subimg_height)
+               {
+                 row = interlace_start[++pass];
+                 while (row >= subimg_height)
+                   row = interlace_start[++pass];
+               }
+
+             for (x = 0; x < subimg_width; x++)
+               {
+                 int c = raster[y * subimg_width + x];
+                 if (transparency_color_index != c || disposal != 1)
+                   XPutPixel (ximg, x + subimg_left, row + subimg_top,
+                              pixel_colors[c]);
+               }
+           }
+       }
+      else
+       {
+         for (y = 0; y < subimg_height; ++y)
+           for (x = 0; x < subimg_width; ++x)
+             {
+               int c = raster[y * subimg_width + x];
+               if (transparency_color_index != c || disposal != 1)
+                 XPutPixel (ximg, x + subimg_left, y + subimg_top,
+                            pixel_colors[c]);
+             }
+       }
     }
 
-  /* Save GIF image extension data for `image-extension-data'.
-     Format is (count IMAGES FUNCTION "BYTES" ...).  */
-  img->data.lisp_val = Qnil;
-  if (gif->SavedImages[ino].ExtensionBlockCount > 0)
+#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->lisp_data = Qnil;
+  if (gif->SavedImages[idx].ExtensionBlockCount > 0)
     {
-      ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
-      for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
+      int delay = 0;
+      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),
-                                          img->data.lisp_val));
-      img->data.lisp_val = Fnreverse (img->data.lisp_val);
+       {
+         img->lisp_data
+           = Fcons (make_number (ext->Function),
+                    Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
+                           img->lisp_data));
+         if (ext->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION
+             && ext->ByteCount == 4)
+           {
+             delay = ext->Bytes[2] << CHAR_BIT;
+             delay |= ext->Bytes[1];
+           }
+       }
+      img->lisp_data = Fcons (Qextension_data,
+                             Fcons (img->lisp_data, Qnil));
+      if (delay)
+       img->lisp_data
+         = Fcons (Qdelay,
+                  Fcons (make_float (delay / 100.0),
+                         img->lisp_data));
     }
+
   if (gif->ImageCount > 1)
-    img->data.lisp_val = Fcons (Qcount,
-                               Fcons (make_number (gif->ImageCount),
-                                      img->data.lisp_val));
+    img->lisp_data = Fcons (Qcount,
+                           Fcons (make_number (gif->ImageCount),
+                                  img->lisp_data));
 
   fn_DGifCloseFile (gif);
 
@@ -7548,7 +7523,6 @@ gif_load (f, img)
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
 
-  UNGCPRO;
   return 1;
 }
 
@@ -7558,15 +7532,569 @@ gif_load (f, img)
 static int
 gif_load (struct frame *f, struct image *img)
 {
-  return ns_load_image(f, img,
-                       image_spec_value (img->spec, QCfile, NULL),
-                       image_spec_value (img->spec, QCdata, NULL));
+  return ns_load_image (f, img,
+                        image_spec_value (img->spec, QCfile, NULL),
+                       image_spec_value (img->spec, QCdata, NULL));
 }
 #endif /* HAVE_NS */
 
 #endif /* HAVE_GIF */
 
 
+/***********************************************************************
+                                ImageMagick
+***********************************************************************/
+#if defined (HAVE_IMAGEMAGICK)
+
+static 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
+  {
+    IMAGEMAGICK_TYPE,
+    IMAGEMAGICK_DATA,
+    IMAGEMAGICK_FILE,
+    IMAGEMAGICK_ASCENT,
+    IMAGEMAGICK_MARGIN,
+    IMAGEMAGICK_RELIEF,
+    IMAGEMAGICK_ALGORITHM,
+    IMAGEMAGICK_HEURISTIC_MASK,
+    IMAGEMAGICK_MASK,
+    IMAGEMAGICK_BACKGROUND,
+    IMAGEMAGICK_HEIGHT,
+    IMAGEMAGICK_WIDTH,
+    IMAGEMAGICK_ROTATION,
+    IMAGEMAGICK_CROP,
+    IMAGEMAGICK_LAST
+  };
+
+/* Vector of image_keyword structures describing the format
+   of valid user-defined image specifications.  */
+
+static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
+  {
+    {":type",          IMAGE_SYMBOL_VALUE,                     1},
+    {":data",          IMAGE_STRING_VALUE,                     0},
+    {":file",          IMAGE_STRING_VALUE,                     0},
+    {":ascent",                IMAGE_ASCENT_VALUE,                     0},
+    {":margin",                IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
+    {":relief",                IMAGE_INTEGER_VALUE,                    0},
+    {":conversion",    IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+    {":heuristic-mask",        IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+    {":mask",          IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+    {":background",    IMAGE_STRING_OR_NIL_VALUE,              0},
+    {":height",                IMAGE_INTEGER_VALUE,                    0},
+    {":width",         IMAGE_INTEGER_VALUE,                    0},
+    {":rotation",      IMAGE_NUMBER_VALUE,                     0},
+    {":crop",          IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  };
+
+#ifdef HAVE_NTGUI
+static int init_imagemagick_functions (void);
+#else
+#define init_imagemagick_functions NULL
+#endif
+
+/* 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,
+    init_imagemagick_functions,
+    NULL
+  };
+
+/* Free X resources of imagemagick image IMG which is used on frame F.  */
+
+static void
+imagemagick_clear_image (struct frame *f,
+                         struct image *img)
+{
+  x_clear_image (f, img);
+}
+
+/* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification.  Do
+   this by calling parse_image_spec and supplying the keywords that
+   identify the IMAGEMAGICK format.   */
+
+static int
+imagemagick_image_p (Lisp_Object object)
+{
+  struct image_keyword fmt[IMAGEMAGICK_LAST];
+  memcpy (fmt, imagemagick_format, sizeof fmt);
+
+  if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick))
+    return 0;
+
+  /* Must specify either the :data or :file keyword.  */
+  return fmt[IMAGEMAGICK_FILE].count + fmt[IMAGEMAGICK_DATA].count == 1;
+}
+
+/* The GIF library also defines DrawRectangle, but its never used in Emacs.
+   Therefore rename the function so it doesn't collide with ImageMagick.  */
+#define DrawRectangle DrawRectangleGif
+#include <wand/MagickWand.h>
+
+/* ImageMagick 6.5.3 through 6.6.5 hid PixelGetMagickColor for some reason.
+   Emacs seems to work fine with the hidden version, so unhide it.  */
+#include <magick/version.h>
+#if 0x653 <= MagickLibVersion && MagickLibVersion <= 0x665
+extern WandExport void PixelGetMagickColor (const PixelWand *,
+                                           MagickPixelPacket *);
+#endif
+
+/* Log ImageMagick error message.
+   Useful when a ImageMagick function returns the status `MagickFalse'.  */
+
+static void
+imagemagick_error (MagickWand *wand)
+{
+  char *description;
+  ExceptionType severity;
+
+  description = MagickGetException (wand, &severity);
+  image_error ("ImageMagick error: %s",
+              build_string (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
+   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.  */
+
+static int
+imagemagick_load_image (struct frame *f, struct image *img,
+                       unsigned char *contents, unsigned int size,
+                       char *filename)
+{
+  size_t width, height;
+  MagickBooleanType status;
+  XImagePtr ximg;
+  int x, y;
+  MagickWand *image_wand;
+  MagickWand *ping_wand;
+  PixelIterator *iterator;
+  PixelWand **pixels, *bg_wand = NULL;
+  MagickPixelPacket  pixel;
+  Lisp_Object image;
+  Lisp_Object value;
+  Lisp_Object crop;
+  EMACS_INT ino;
+  int desired_width, desired_height;
+  double rotation;
+  int pixelwidth;
+
+  /* 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
+     many sub-images it contains.  Pinging is faster than loading the image to
+     find out things about it.  */
+
+  /* Initialize the imagemagick environment.  */
+  MagickWandGenesis ();
+  image = image_spec_value (img->spec, QCindex, NULL);
+  ino = INTEGERP (image) ? XFASTINT (image) : 0;
+  ping_wand = NewMagickWand ();
+  /* MagickSetResolution (ping_wand, 2, 2);   (Bug#10112)  */
+
+  status = filename
+    ? MagickPingImage (ping_wand, filename)
+    : MagickPingImageBlob (ping_wand, contents, size);
+
+  if (status == MagickFalse)
+    {
+      imagemagick_error (ping_wand);
+      DestroyMagickWand (ping_wand);
+      return 0;
+    }
+
+  if (ino < 0 || ino >= MagickGetNumberImages (ping_wand))
+    {
+      image_error ("Invalid image number `%s' in image `%s'",
+                  image, img->spec);
+      DestroyMagickWand (ping_wand);
+      return 0;
+    }
+
+  if (MagickGetNumberImages (ping_wand) > 1)
+    img->lisp_data =
+      Fcons (Qcount,
+             Fcons (make_number (MagickGetNumberImages (ping_wand)),
+                    img->lisp_data));
+
+  DestroyMagickWand (ping_wand);
+
+  /* Now we know how many images are inside the file.  If it's not a
+     bundle, the number is one.  Load the image data.  */
+
+  image_wand = NewMagickWand ();
+
+  if ((filename
+       ? MagickReadImage (image_wand, filename)
+       : MagickReadImageBlob (image_wand, contents, size))
+      == MagickFalse)
+    {
+      imagemagick_error (image_wand);
+      goto imagemagick_error;
+    }
+
+  /* Retrieve the frame's background color, for use later.  */
+  {
+    XColor bgcolor;
+    Lisp_Object specified_bg;
+
+    specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+    if (!STRINGP (specified_bg)
+       || !x_defined_color (f, SSDATA (specified_bg), &bgcolor, 0))
+      {
+#ifndef HAVE_NS
+       bgcolor.pixel = FRAME_BACKGROUND_PIXEL (f);
+       x_query_color (f, &bgcolor);
+#else
+       ns_query_color (FRAME_BACKGROUND_COLOR (f), &bgcolor, 1);
+#endif
+      }
+
+    bg_wand = NewPixelWand ();
+    PixelSetRed   (bg_wand, (double) bgcolor.red   / 65535);
+    PixelSetGreen (bg_wand, (double) bgcolor.green / 65535);
+    PixelSetBlue  (bg_wand, (double) bgcolor.blue  / 65535);
+  }
+
+  /* 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
+     aspect ratio.  */
+  value = image_spec_value (img->spec, QCwidth, NULL);
+  desired_width = (INTEGERP (value)  ? XFASTINT (value) : -1);
+  value = image_spec_value (img->spec, QCheight, NULL);
+  desired_height = (INTEGERP (value) ? XFASTINT (value) : -1);
+
+  height = MagickGetImageHeight (image_wand);
+  width = MagickGetImageWidth (image_wand);
+
+  if (desired_width != -1 && desired_height == -1)
+    /* w known, calculate h.  */
+    desired_height = (double) desired_width / width * height;
+  if (desired_width == -1 && desired_height != -1)
+    /* h known, calculate w.  */
+    desired_width = (double) desired_height / height * width;
+  if (desired_width != -1 && desired_height != -1)
+    {
+      status = MagickScaleImage (image_wand, desired_width, desired_height);
+      if (status == MagickFalse)
+       {
+         image_error ("Imagemagick scale failed", Qnil, Qnil);
+         imagemagick_error (image_wand);
+         goto imagemagick_error;
+       }
+    }
+
+  /* crop behaves similar to image slicing in Emacs but is more memory
+     efficient.  */
+  crop = image_spec_value (img->spec, QCcrop, NULL);
+
+  if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
+    {
+      /* After some testing, it seems MagickCropImage is the fastest crop
+         function in ImageMagick.  This crop function seems to do less copying
+         than the alternatives, but it still reads the entire image into memory
+         before cropping, which is apparently difficult to avoid when using
+         imagemagick.  */
+      size_t crop_width = XINT (XCAR (crop));
+      crop = XCDR (crop);
+      if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
+       {
+         size_t crop_height = XINT (XCAR (crop));
+         crop = XCDR (crop);
+         if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
+           {
+             ssize_t crop_x = XINT (XCAR (crop));
+             crop = XCDR (crop);
+             if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
+               {
+                 ssize_t crop_y = XINT (XCAR (crop));
+                 MagickCropImage (image_wand, crop_width, crop_height,
+                                  crop_x, crop_y);
+               }
+           }
+       }
+    }
+
+  /* Furthermore :rotation. we need background color and angle for
+     rotation.  */
+  /*
+    TODO background handling for rotation specified_bg =
+    image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP
+    (specified_bg).  */
+  value = image_spec_value (img->spec, QCrotation, NULL);
+  if (FLOATP (value))
+    {
+      rotation = extract_float (value);
+      status = MagickRotateImage (image_wand, bg_wand, rotation);
+      if (status == MagickFalse)
+        {
+          image_error ("Imagemagick image rotate failed", Qnil, Qnil);
+         imagemagick_error (image_wand);
+          goto imagemagick_error;
+        }
+    }
+
+  /* Finally we are done manipulating the image.  Figure out the
+     resulting width/height and transfer ownership to Emacs.  */
+  height = MagickGetImageHeight (image_wand);
+  width = MagickGetImageWidth (image_wand);
+
+  /* Set the canvas background color to the frame or specified
+     background, and flatten the image.  Note: as of ImageMagick
+     6.6.0, SVG image transparency is not handled properly
+     (e.g. etc/images/splash.svg shows a white background always).  */
+  {
+    MagickWand *new_wand;
+    MagickSetImageBackgroundColor (image_wand, bg_wand);
+#ifdef HAVE_MAGICKMERGEIMAGELAYERS
+    new_wand = MagickMergeImageLayers (image_wand, MergeLayer);
+#else
+    new_wand = MagickFlattenImages (image_wand);
+#endif
+    DestroyMagickWand (image_wand);
+    image_wand = new_wand;
+  }
+
+  if (! (width <= INT_MAX && height <= INT_MAX
+        && check_image_size (f, width, height)))
+    {
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      goto imagemagick_error;
+    }
+
+  /* We can now get a valid pixel buffer from the imagemagick file, if all
+     went ok.  */
+
+  init_color_table ();
+
+#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
+  if (imagemagick_render_type != 0)
+    {
+      /* Magicexportimage is normally faster than pixelpushing.  This
+         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);*/
+      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))
+       {
+#ifdef COLOR_TABLE_SUPPORT
+         free_color_table ();
+#endif
+         image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil);
+         goto imagemagick_error;
+       }
+
+      /* Oddly, the below code doesn't seem to work:*/
+      /* switch(ximg->bitmap_unit){ */
+      /* case 8: */
+      /*   pixelwidth=CharPixel; */
+      /*   break; */
+      /* case   16: */
+      /*   pixelwidth=ShortPixel; */
+      /*   break; */
+      /* case   32: */
+      /*   pixelwidth=LongPixel; */
+      /*   break; */
+      /* } */
+      /*
+        Here im just guessing the format of the bitmap.
+        happens to work fine for:
+        - bw djvu images
+        on rgb display.
+        seems about 3 times as fast as pixel pushing(not carefully measured)
+      */
+      pixelwidth = CharPixel; /*??? TODO figure out*/
+      MagickExportImagePixels (image_wand, 0, 0, width, height,
+                              exportdepth, pixelwidth, ximg->data);
+    }
+  else
+#endif /* HAVE_MAGICKEXPORTIMAGEPIXELS */
+    {
+      size_t image_height;
+
+      /* Try to create a x pixmap to hold the imagemagick pixmap.  */
+      if (!x_create_x_image_and_pixmap (f, width, height, 0,
+                                        &ximg, &img->pixmap))
+        {
+#ifdef COLOR_TABLE_SUPPORT
+         free_color_table ();
+#endif
+          image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil);
+          goto imagemagick_error;
+        }
+
+      /* Copy imagemagick image to x with primitive yet robust pixel
+         pusher loop.  This has been tested a lot with many different
+         images.  */
+
+      /* Copy pixels from the imagemagick image structure to the x image map. */
+      iterator = NewPixelIterator (image_wand);
+      if (iterator == (PixelIterator *) NULL)
+        {
+#ifdef COLOR_TABLE_SUPPORT
+         free_color_table ();
+#endif
+         x_destroy_x_image (ximg);
+          image_error ("Imagemagick pixel iterator creation failed",
+                       Qnil, Qnil);
+          goto imagemagick_error;
+        }
+
+      image_height = MagickGetImageHeight (image_wand);
+      for (y = 0; y < image_height; y++)
+        {
+          pixels = PixelGetNextIteratorRow (iterator, &width);
+          if (pixels == (PixelWand **) NULL)
+            break;
+          for (x = 0; x < (long) width; x++)
+            {
+              PixelGetMagickColor (pixels[x], &pixel);
+              XPutPixel (ximg, x, y,
+                         lookup_rgb_color (f,
+                                           pixel.red,
+                                           pixel.green,
+                                           pixel.blue));
+            }
+        }
+      DestroyPixelIterator (iterator);
+    }
+
+#ifdef COLOR_TABLE_SUPPORT
+  /* Remember colors allocated for this image.  */
+  img->colors = colors_in_color_table (&img->ncolors);
+  free_color_table ();
+#endif /* COLOR_TABLE_SUPPORT */
+
+  img->width  = width;
+  img->height = height;
+
+  /* Put the image into the pixmap, then free the X image and its
+     buffer.  */
+  x_put_x_image (f, ximg, img->pixmap, width, height);
+  x_destroy_x_image (ximg);
+
+  /* Final cleanup. image_wand should be the only resource left. */
+  DestroyMagickWand (image_wand);
+  if (bg_wand) DestroyPixelWand (bg_wand);
+
+  /* `MagickWandTerminus' terminates the imagemagick environment.  */
+  MagickWandTerminus ();
+
+  return 1;
+
+ imagemagick_error:
+  DestroyMagickWand (image_wand);
+  if (bg_wand) DestroyPixelWand (bg_wand);
+
+  MagickWandTerminus ();
+  /* TODO more cleanup.  */
+  image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
+  return 0;
+}
+
+
+/* Load IMAGEMAGICK image IMG for use on frame F.  Value is non-zero if
+   successful. this function will go into the imagemagick_type structure, and
+   the prototype thus needs to be compatible with that structure.  */
+
+static int
+imagemagick_load (struct frame *f, struct image *img)
+{
+  int success_p = 0;
+  Lisp_Object file_name;
+
+  /* If IMG->spec specifies a file name, create a non-file spec from it.  */
+  file_name = image_spec_value (img->spec, QCfile, NULL);
+  if (STRINGP (file_name))
+    {
+      Lisp_Object file;
+
+      file = x_find_image_file (file_name);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", file_name, Qnil);
+         return 0;
+       }
+      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.  */
+  else
+    {
+      Lisp_Object data;
+
+      data = image_spec_value (img->spec, QCdata, NULL);
+      if (!STRINGP (data))
+       {
+         image_error ("Invalid image data `%s'", data, Qnil);
+         return 0;
+       }
+      success_p = imagemagick_load_image (f, img, SDATA (data),
+                                          SBYTES (data), NULL);
+    }
+
+  return success_p;
+}
+
+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).
+You can also try the shell command: `identify -list format'.
+
+Note that ImageMagick recognizes many file-types that Emacs does not
+recognize as images, such as C.  See `imagemagick-types-enable'
+and `imagemagick-types-inhibit'.  */)
+  (void)
+{
+  Lisp_Object typelist = Qnil;
+  size_t numf = 0;
+  ExceptionInfo ex;
+  char **imtypes;
+  size_t i;
+  Lisp_Object Qimagemagicktype;
+
+  GetExceptionInfo(&ex);
+  imtypes = GetMagickList ("*", &numf, &ex);
+  DestroyExceptionInfo(&ex);
+
+  for (i = 0; i < numf; i++)
+    {
+      Qimagemagicktype = intern (imtypes[i]);
+      typelist = Fcons (Qimagemagicktype, typelist);
+    }
+  return Fnreverse (typelist);
+}
+
+#endif /* defined (HAVE_IMAGEMAGICK) */
+
+
 \f
 /***********************************************************************
                                 SVG
@@ -7576,15 +8104,15 @@ gif_load (struct frame *f, struct image *img)
 
 /* Function prototypes.  */
 
-static int svg_image_p P_ ((Lisp_Object object));
-static int svg_load P_ ((struct frame *f, struct image *img));
+static int svg_image_p (Lisp_Object object);
+static int svg_load (struct frame *f, struct image *img);
 
-static int svg_load_image P_ ((struct frame *, struct image *,
-                              unsigned char *, unsigned int));
+static int svg_load_image (struct frame *, struct image *,
+                           unsigned char *, ptrdiff_t);
 
 /* The symbol `svg' identifying images of this type. */
 
-Lisp_Object Qsvg;
+static Lisp_Object Qsvg;
 
 /* Indices of image specification fields in svg_format, below.  */
 
@@ -7612,7 +8140,7 @@ static const struct image_keyword svg_format[SVG_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -7620,22 +8148,23 @@ static const struct image_keyword svg_format[SVG_LAST] =
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
+#ifdef HAVE_NTGUI
+static int init_svg_functions (void);
+#else
+#define init_svg_functions NULL
+#endif
+
 /* Structure describing the image type `svg'.  Its the same type of
    structure defined for all image formats, handled by emacs image
    functions.  See struct image_type in dispextern.h.  */
 
 static struct image_type svg_type =
 {
-  /* An identifier showing that this is an image structure for the SVG format.  */
   &Qsvg,
-  /* Handle to a function that can be used to identify a SVG file.  */
   svg_image_p,
-  /* Handle to function used to load a SVG file.  */
   svg_load,
-  /* Handle to function to free sresources for SVG.  */
   x_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.  */
+  init_svg_functions,
   NULL
 };
 
@@ -7645,11 +8174,10 @@ static struct image_type svg_type =
    identify the SVG format.   */
 
 static int
-svg_image_p (object)
-     Lisp_Object object;
+svg_image_p (Lisp_Object object)
 {
   struct image_keyword fmt[SVG_LAST];
-  bcopy (svg_format, fmt, sizeof fmt);
+  memcpy (fmt, svg_format, sizeof fmt);
 
   if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
     return 0;
@@ -7668,7 +8196,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);
@@ -7686,14 +8213,14 @@ DEF_IMGLIB_FN (void, g_error_free);
 Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
 
 static int
-init_svg_functions (Lisp_Object libraries)
+init_svg_functions (void)
 {
   HMODULE library, gdklib, glib, gobject;
 
-  if (!(glib = w32_delayed_load (libraries, Qglib))
-      || !(gobject = w32_delayed_load (libraries, Qgobject))
-      || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
-      || !(library = w32_delayed_load (libraries, Qsvg)))
+  if (!(glib = w32_delayed_load (Qglib))
+      || !(gobject = w32_delayed_load (Qgobject))
+      || !(gdklib = w32_delayed_load (Qgdk_pixbuf))
+      || !(library = w32_delayed_load (Qsvg)))
     return 0;
 
   LOAD_IMGLIB_FN (library, rsvg_handle_new);
@@ -7701,7 +8228,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);
@@ -7727,7 +8253,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
@@ -7748,9 +8273,7 @@ init_svg_functions (Lisp_Object libraries)
    the prototype thus needs to be compatible with that structure.  */
 
 static int
-svg_load (f, img)
-     struct frame *f;
-     struct image *img;
+svg_load (struct frame *f, struct image *img)
 {
   int success_p = 0;
   Lisp_Object file_name;
@@ -7761,30 +8284,25 @@ svg_load (f, img)
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
-      struct gcpro gcpro1;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
-      GCPRO1 (file);
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", file_name, Qnil);
-         UNGCPRO;
          return 0;
        }
 
       /* 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);
-         UNGCPRO;
          return 0;
        }
       /* If the file was slurped into memory properly, parse it.  */
       success_p = svg_load_image (f, img, contents, size);
       xfree (contents);
-      UNGCPRO;
     }
   /* Else its not a file, its a lisp object.  Load the image from a
      lisp object rather than a file.  */
@@ -7793,6 +8311,11 @@ svg_load (f, img)
       Lisp_Object data;
 
       data = image_spec_value (img->spec, QCdata, NULL);
+      if (!STRINGP (data))
+       {
+         image_error ("Invalid image data `%s'", data, Qnil);
+         return 0;
+       }
       success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
     }
 
@@ -7807,19 +8330,14 @@ svg_load (f, img)
 
    Returns non-zero when successful.  */
 static int
-svg_load_image (f, img, contents, size)
-    /* Pointer to emacs frame structure.  */
-     struct frame *f;
-     /* Pointer to emacs image structure.  */
-     struct image *img;
-     /* String containing the SVG XML data to be parsed.  */
-     unsigned char *contents;
-     /* Size of data in bytes.  */
-     unsigned int size;
+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.  */
+               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;
@@ -7838,13 +8356,13 @@ svg_load_image (f, img, contents, size)
   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))
@@ -7884,13 +8402,13 @@ svg_load_image (f, img, contents, size)
      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);
       x_query_color (f, &background);
 #else
-      ns_query_color(FRAME_BACKGROUND_COLOR (f), &background, 1);
+      ns_query_color (FRAME_BACKGROUND_COLOR (f), &background, 1);
 #endif
     }
 
@@ -7909,10 +8427,10 @@ svg_load_image (f, img, contents, size)
     {
       for (x = 0; x < width; ++x)
        {
-         unsigned red;
-         unsigned green;
-         unsigned blue;
-         unsigned opacity;
+         int red;
+         int green;
+         int blue;
+         int opacity;
 
          red     = *pixels++;
          green   = *pixels++;
@@ -7959,7 +8477,7 @@ svg_load_image (f, img, contents, size)
   /* 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;
 }
 
@@ -7976,19 +8494,15 @@ svg_load_image (f, img, contents, size)
 #define HAVE_GHOSTSCRIPT 1
 #endif /* HAVE_X_WINDOWS */
 
-/* The symbol `postscript' identifying images of this type.  */
-
-Lisp_Object Qpostscript;
-
 #ifdef HAVE_GHOSTSCRIPT
 
-static int gs_image_p P_ ((Lisp_Object object));
-static int gs_load P_ ((struct frame *f, struct image *img));
-static void gs_clear_image P_ ((struct frame *f, struct image *img));
+static int gs_image_p (Lisp_Object object);
+static int gs_load (struct frame *f, struct image *img);
+static void gs_clear_image (struct frame *f, struct image *img);
 
 /* Keyword symbols.  */
 
-Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
+static Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
 
 /* Indices of image specification fields in gs_format, below.  */
 
@@ -8022,7 +8536,7 @@ static const struct image_keyword gs_format[GS_LAST] =
   {":loader",          IMAGE_FUNCTION_VALUE,                   0},
   {":bounding-box",    IMAGE_DONT_CHECK_VALUE_TYPE,            1},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -8038,6 +8552,7 @@ static struct image_type gs_type =
   gs_image_p,
   gs_load,
   gs_clear_image,
+  NULL,
   NULL
 };
 
@@ -8045,12 +8560,8 @@ static struct image_type gs_type =
 /* Free X resources of Ghostscript image IMG which is used on frame F.  */
 
 static void
-gs_clear_image (f, img)
-     struct frame *f;
-     struct image *img;
+gs_clear_image (struct frame *f, struct image *img)
 {
-  /* IMG->data.ptr_val may contain a recorded colormap.  */
-  xfree (img->data.ptr_val);
   x_clear_image (f, img);
 }
 
@@ -8059,14 +8570,13 @@ gs_clear_image (f, img)
    specification.  */
 
 static int
-gs_image_p (object)
-     Lisp_Object object;
+gs_image_p (Lisp_Object object)
 {
   struct image_keyword fmt[GS_LAST];
   Lisp_Object tem;
   int i;
 
-  bcopy (gs_format, fmt, sizeof fmt);
+  memcpy (fmt, gs_format, sizeof fmt);
 
   if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
     return 0;
@@ -8083,10 +8593,10 @@ gs_image_p (object)
     }
   else if (VECTORP (tem))
     {
-      if (XVECTOR_SIZE (tem) != 4)
+      if (ASIZE (tem) != 4)
        return 0;
       for (i = 0; i < 4; ++i)
-       if (!INTEGERP (XVECTOR (tem)->contents[i]))
+       if (!INTEGERP (AREF (tem, i)))
          return 0;
     }
   else
@@ -8100,13 +8610,11 @@ gs_image_p (object)
    if successful.  */
 
 static int
-gs_load (f, img)
-     struct frame *f;
-     struct image *img;
+gs_load (struct frame *f, struct image *img)
 {
-  char buffer[100];
+  uprintmax_t printnum1, printnum2;
+  char buffer[sizeof " " + INT_STRLEN_BOUND (printmax_t)];
   Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
-  struct gcpro gcpro1, gcpro2;
   Lisp_Object frame;
   double in_width, in_height;
   Lisp_Object pixel_colors = Qnil;
@@ -8116,27 +8624,33 @@ gs_load (f, img)
      = 1/72 in, xdpi and ydpi are stored in the frame's X display
      info.  */
   pt_width = image_spec_value (img->spec, QCpt_width, NULL);
-  in_width = XFASTINT (pt_width) / 72.0;
-  img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
+  in_width = INTEGERP (pt_width) ? XFASTINT (pt_width) / 72.0 : 0;
+  in_width *= FRAME_X_DISPLAY_INFO (f)->resx;
   pt_height = image_spec_value (img->spec, QCpt_height, NULL);
-  in_height = XFASTINT (pt_height) / 72.0;
-  img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
+  in_height = INTEGERP (pt_height) ? XFASTINT (pt_height) / 72.0 : 0;
+  in_height *= FRAME_X_DISPLAY_INFO (f)->resy;
 
-  if (!check_image_size (f, img->width, img->height))
+  if (! (in_width <= INT_MAX && in_height <= INT_MAX
+        && check_image_size (f, in_width, in_height)))
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       return 0;
     }
+  img->width = in_width;
+  img->height = in_height;
 
   /* Create the pixmap.  */
-  xassert (img->pixmap == NO_PIXMAP);
+  eassert (img->pixmap == NO_PIXMAP);
 
-  /* Only W32 version did BLOCK_INPUT here.  ++kfs */
-  BLOCK_INPUT;
-  img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                              img->width, img->height,
-                              DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
-  UNBLOCK_INPUT;
+  if (x_check_image_size (0, img->width, img->height))
+    {
+      /* Only W32 version did BLOCK_INPUT here.  ++kfs */
+      block_input ();
+      img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                                  img->width, img->height,
+                                  DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
+      unblock_input ();
+    }
 
   if (!img->pixmap)
     {
@@ -8148,30 +8662,27 @@ gs_load (f, img)
      if successful.  We do not record_unwind_protect here because
      other places in redisplay like calling window scroll functions
      don't either.  Let the Lisp loader use `unwind-protect' instead.  */
-  GCPRO2 (window_and_pixmap_id, pixel_colors);
+  printnum1 = FRAME_X_WINDOW (f);
+  printnum2 = img->pixmap;
+  window_and_pixmap_id
+    = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2);
 
-  sprintf (buffer, "%lu %lu",
-          (unsigned long) FRAME_X_WINDOW (f),
-          (unsigned long) img->pixmap);
-  window_and_pixmap_id = build_string (buffer);
-
-  sprintf (buffer, "%lu %lu",
-          FRAME_FOREGROUND_PIXEL (f),
-          FRAME_BACKGROUND_PIXEL (f));
-  pixel_colors = build_string (buffer);
+  printnum1 = FRAME_FOREGROUND_PIXEL (f);
+  printnum2 = FRAME_BACKGROUND_PIXEL (f);
+  pixel_colors
+    = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2);
 
   XSETFRAME (frame, f);
   loader = image_spec_value (img->spec, QCloader, NULL);
   if (NILP (loader))
     loader = intern ("gs-load-image");
 
-  img->data.lisp_val = call6 (loader, frame, img->spec,
-                             make_number (img->width),
-                             make_number (img->height),
-                             window_and_pixmap_id,
-                             pixel_colors);
-  UNGCPRO;
-  return PROCESSP (img->data.lisp_val);
+  img->lisp_data = call6 (loader, frame, img->spec,
+                         make_number (img->width),
+                         make_number (img->height),
+                         window_and_pixmap_id,
+                         pixel_colors);
+  return PROCESSP (img->lisp_data);
 }
 
 
@@ -8180,12 +8691,11 @@ gs_load (f, img)
    telling Emacs that Ghostscript has finished drawing.  */
 
 void
-x_kill_gs_process (pixmap, f)
-     Pixmap pixmap;
-     struct frame *f;
+x_kill_gs_process (Pixmap pixmap, struct frame *f)
 {
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
-  int class, i;
+  int class;
+  ptrdiff_t i;
   struct image *img;
 
   /* Find the image containing PIXMAP.  */
@@ -8201,9 +8711,9 @@ x_kill_gs_process (pixmap, f)
   /* Kill the GS process.  We should have found PIXMAP in the image
      cache and its image should contain a process object.  */
   img = c->images[i];
-  xassert (PROCESSP (img->data.lisp_val));
-  Fkill_process (img->data.lisp_val, Qnil);
-  img->data.lisp_val = Qnil;
+  eassert (PROCESSP (img->lisp_data));
+  Fkill_process (img->lisp_data, Qnil);
+  img->lisp_data = Qnil;
 
 #if defined (HAVE_X_WINDOWS)
 
@@ -8215,7 +8725,7 @@ x_kill_gs_process (pixmap, f)
     {
       XImagePtr ximg;
 
-      BLOCK_INPUT;
+      block_input ();
 
       /* Try to get an XImage for img->pixmep.  */
       ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
@@ -8258,15 +8768,15 @@ x_kill_gs_process (pixmap, f)
        image_error ("Cannot get X image of `%s'; colors will not be freed",
                     img->spec, Qnil);
 
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 #endif /* HAVE_X_WINDOWS */
 
   /* Now that we have the pixmap, compute mask and transform the
      image if requested.  */
-  BLOCK_INPUT;
+  block_input ();
   postprocess_image (f, img);
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 #endif /* HAVE_GHOSTSCRIPT */
@@ -8276,22 +8786,20 @@ x_kill_gs_process (pixmap, f)
                                Tests
  ***********************************************************************/
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
 
 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
        doc: /* Value is non-nil if SPEC is a valid image specification.  */)
-  (spec)
-     Lisp_Object spec;
+  (Lisp_Object spec)
 {
   return valid_image_p (spec) ? Qt : Qnil;
 }
 
 
 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
-  (spec)
-     Lisp_Object spec;
+  (Lisp_Object spec)
 {
-  int id = -1;
+  ptrdiff_t id = -1;
 
   if (valid_image_p (spec))
     id = lookup_image (SELECTED_FRAME (), spec);
@@ -8300,113 +8808,98 @@ DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
   return make_number (id);
 }
 
-#endif /* GLYPH_DEBUG != 0 */
+#endif /* GLYPH_DEBUG */
 
 
 /***********************************************************************
                            Initialization
  ***********************************************************************/
 
-#ifdef HAVE_NTGUI
-/* Image types that rely on external libraries are loaded dynamically
-   if the library is available.  */
-#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
-  define_image_type (image_type, init_lib_fn (libraries))
-#else
-#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
-  define_image_type (image_type, 1)
-#endif /* HAVE_NTGUI */
-
-DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
+DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 1, 1, 0,
        doc: /* Initialize image library implementing image type TYPE.
 Return non-nil if TYPE is a supported image type.
 
-Image types pbm and xbm are prebuilt; other types are loaded here.
-Libraries to load are specified in alist LIBRARIES (usually, the value
-of `image-library-alist', which see).  */)
-  (type, libraries)
-  Lisp_Object type, libraries;
+If image libraries are loaded dynamically (currently only the case on
+MS-Windows), load the library for TYPE if it is not yet loaded, using
+the library file(s) specified by `dynamic-library-alist'.  */)
+  (Lisp_Object type)
+{
+  return lookup_image_type (type) ? Qt : Qnil;
+}
+
+/* Look up image type TYPE, and return a pointer to its image_type
+   structure.  Return 0 if TYPE is not a known image type.  */
+
+static struct image_type *
+lookup_image_type (Lisp_Object type)
 {
-  Lisp_Object tested;
+  /* Types pbm and xbm are built-in and always available.  */
+  if (EQ (type, Qpbm))
+    return define_image_type (&pbm_type);
 
-  /* Don't try to reload the library.  */
-  tested = Fassq (type, Vimage_type_cache);
-  if (CONSP (tested))
-    return XCDR (tested);
+  if (EQ (type, Qxbm))
+    return define_image_type (&xbm_type);
 
 #if defined (HAVE_XPM) || defined (HAVE_NS)
   if (EQ (type, Qxpm))
-    return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
+    return define_image_type (&xpm_type);
 #endif
 
 #if defined (HAVE_JPEG) || defined (HAVE_NS)
   if (EQ (type, Qjpeg))
-    return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
+    return define_image_type (&jpeg_type);
 #endif
 
 #if defined (HAVE_TIFF) || defined (HAVE_NS)
   if (EQ (type, Qtiff))
-    return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
+    return define_image_type (&tiff_type);
 #endif
 
 #if defined (HAVE_GIF) || defined (HAVE_NS)
   if (EQ (type, Qgif))
-    return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
+    return define_image_type (&gif_type);
 #endif
 
 #if defined (HAVE_PNG) || defined (HAVE_NS)
   if (EQ (type, Qpng))
-    return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
+    return define_image_type (&png_type);
 #endif
 
 #if defined (HAVE_RSVG)
   if (EQ (type, Qsvg))
-    return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
+    return define_image_type (&svg_type);
+#endif
+
+#if defined (HAVE_IMAGEMAGICK)
+  if (EQ (type, Qimagemagick))
+    return define_image_type (&imagemagick_type);
 #endif
 
 #ifdef HAVE_GHOSTSCRIPT
   if (EQ (type, Qpostscript))
-    return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
+    return define_image_type (&gs_type);
 #endif
 
-  /* If the type is not recognized, avoid testing it ever again.  */
-  CACHE_IMAGE_TYPE (type, Qnil);
-  return Qnil;
+  return NULL;
 }
 
 void
-syms_of_image ()
+syms_of_image (void)
 {
-  extern Lisp_Object Qrisky_local_variable;   /* Syms_of_xdisp has already run.  */
-
   /* Initialize this only once, since that's what we do with Vimage_types
      and they are supposed to be in sync.  Initializing here gives correct
      operation on GNU/Linux of calling dump-emacs after loading some images.  */
   image_types = NULL;
 
-  /* Must be defined now becase we're going to update it below, while
+  /* Must be defined now because we're going to update it below, while
      defining the supported image types.  */
-  DEFVAR_LISP ("image-types", &Vimage_types,
+  DEFVAR_LISP ("image-types", Vimage_types,
     doc: /* List of potentially supported image types.
 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
 To check whether it is really supported, use `image-type-available-p'.  */);
   Vimage_types = Qnil;
 
-  DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
-    doc: /* Alist of image types vs external libraries needed to display them.
-
-Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
-representing a supported image type, and the rest are strings giving
-alternate filenames for the corresponding external libraries.
-
-Emacs tries to load the libraries in the order they appear on the
-list; if none is loaded, the running session of Emacs won't
-support the image type.  Types 'pbm and 'xbm don't need to be
-listed; they are always supported.  */);
-  Vimage_library_alist = Qnil;
-  Fput (intern_c_string ("image-library-alist"), Qrisky_local_variable, Qt);
-
-  DEFVAR_LISP ("max-image-size", &Vmax_image_size,
+  DEFVAR_LISP ("max-image-size", Vmax_image_size,
     doc: /* Maximum size of images.
 Emacs will not load an image into memory if its pixel width or
 pixel height exceeds this limit.
@@ -8418,70 +8911,40 @@ 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);
-
-  Qxbm = intern_c_string ("xbm");
-  staticpro (&Qxbm);
-  ADD_IMAGE_TYPE (Qxbm);
-
-  define_image_type (&xbm_type, 1);
-  define_image_type (&pbm_type, 1);
-
-  Qcount = intern_c_string ("count");
-  staticpro (&Qcount);
-
-  QCascent = intern_c_string (":ascent");
-  staticpro (&QCascent);
-  QCmargin = intern_c_string (":margin");
-  staticpro (&QCmargin);
-  QCrelief = intern_c_string (":relief");
-  staticpro (&QCrelief);
-  QCconversion = intern_c_string (":conversion");
-  staticpro (&QCconversion);
-  QCcolor_symbols = intern_c_string (":color-symbols");
-  staticpro (&QCcolor_symbols);
-  QCheuristic_mask = intern_c_string (":heuristic-mask");
-  staticpro (&QCheuristic_mask);
-  QCindex = intern_c_string (":index");
-  staticpro (&QCindex);
-  QCmatrix = intern_c_string (":matrix");
-  staticpro (&QCmatrix);
-  QCcolor_adjustment = intern_c_string (":color-adjustment");
-  staticpro (&QCcolor_adjustment);
-  QCmask = intern_c_string (":mask");
-  staticpro (&QCmask);
-
-  Qlaplace = intern_c_string ("laplace");
-  staticpro (&Qlaplace);
-  Qemboss = intern_c_string ("emboss");
-  staticpro (&Qemboss);
-  Qedge_detection = intern_c_string ("edge-detection");
-  staticpro (&Qedge_detection);
-  Qheuristic = intern_c_string ("heuristic");
-  staticpro (&Qheuristic);
-
-  Qpostscript = intern_c_string ("postscript");
-  staticpro (&Qpostscript);
+  DEFSYM (Qcount, "count");
+  DEFSYM (Qextension_data, "extension-data");
+  DEFSYM (Qdelay, "delay");
+
+  DEFSYM (QCascent, ":ascent");
+  DEFSYM (QCmargin, ":margin");
+  DEFSYM (QCrelief, ":relief");
+  DEFSYM (QCconversion, ":conversion");
+  DEFSYM (QCcolor_symbols, ":color-symbols");
+  DEFSYM (QCheuristic_mask, ":heuristic-mask");
+  DEFSYM (QCindex, ":index");
+  DEFSYM (QCgeometry, ":geometry");
+  DEFSYM (QCcrop, ":crop");
+  DEFSYM (QCrotation, ":rotation");
+  DEFSYM (QCmatrix, ":matrix");
+  DEFSYM (QCcolor_adjustment, ":color-adjustment");
+  DEFSYM (QCmask, ":mask");
+
+  DEFSYM (Qlaplace, "laplace");
+  DEFSYM (Qemboss, "emboss");
+  DEFSYM (Qedge_detection, "edge-detection");
+  DEFSYM (Qheuristic, "heuristic");
+
+  DEFSYM (Qpostscript, "postscript");
 #ifdef HAVE_GHOSTSCRIPT
   ADD_IMAGE_TYPE (Qpostscript);
-  QCloader = intern_c_string (":loader");
-  staticpro (&QCloader);
-  QCbounding_box = intern_c_string (":bounding-box");
-  staticpro (&QCbounding_box);
-  QCpt_width = intern_c_string (":pt-width");
-  staticpro (&QCpt_width);
-  QCpt_height = intern_c_string (":pt-height");
-  staticpro (&QCpt_height);
+  DEFSYM (QCloader, ":loader");
+  DEFSYM (QCbounding_box, ":bounding-box");
+  DEFSYM (QCpt_width, ":pt-width");
+  DEFSYM (QCpt_height, ":pt-height");
 #endif /* HAVE_GHOSTSCRIPT */
 
 #ifdef HAVE_NTGUI
-  Qlibpng_version = intern_c_string ("libpng-version");
-  staticpro (&Qlibpng_version);
+  DEFSYM (Qlibpng_version, "libpng-version");
   Fset (Qlibpng_version,
 #if HAVE_PNG
        make_number (PNG_LIBPNG_VER)
@@ -8491,85 +8954,99 @@ non-numeric, there is no explicit limit on the size of images.  */);
        );
 #endif
 
+  DEFSYM (Qpbm, "pbm");
+  ADD_IMAGE_TYPE (Qpbm);
+
+  DEFSYM (Qxbm, "xbm");
+  ADD_IMAGE_TYPE (Qxbm);
+
 #if defined (HAVE_XPM) || defined (HAVE_NS)
-  Qxpm = intern_c_string ("xpm");
-  staticpro (&Qxpm);
+  DEFSYM (Qxpm, "xpm");
   ADD_IMAGE_TYPE (Qxpm);
 #endif
 
 #if defined (HAVE_JPEG) || defined (HAVE_NS)
-  Qjpeg = intern_c_string ("jpeg");
-  staticpro (&Qjpeg);
+  DEFSYM (Qjpeg, "jpeg");
   ADD_IMAGE_TYPE (Qjpeg);
 #endif
 
 #if defined (HAVE_TIFF) || defined (HAVE_NS)
-  Qtiff = intern_c_string ("tiff");
-  staticpro (&Qtiff);
+  DEFSYM (Qtiff, "tiff");
   ADD_IMAGE_TYPE (Qtiff);
 #endif
 
 #if defined (HAVE_GIF) || defined (HAVE_NS)
-  Qgif = intern_c_string ("gif");
-  staticpro (&Qgif);
+  DEFSYM (Qgif, "gif");
   ADD_IMAGE_TYPE (Qgif);
 #endif
 
 #if defined (HAVE_PNG) || defined (HAVE_NS)
-  Qpng = intern_c_string ("png");
-  staticpro (&Qpng);
+  DEFSYM (Qpng, "png");
   ADD_IMAGE_TYPE (Qpng);
 #endif
 
+#if defined (HAVE_IMAGEMAGICK)
+  DEFSYM (Qimagemagick, "imagemagick");
+  ADD_IMAGE_TYPE (Qimagemagick);
+#endif
+
 #if defined (HAVE_RSVG)
-  Qsvg = intern_c_string ("svg");
-  staticpro (&Qsvg);
+  DEFSYM (Qsvg, "svg");
   ADD_IMAGE_TYPE (Qsvg);
 #ifdef HAVE_NTGUI
   /* Other libraries used directly by svg code.  */
-  Qgdk_pixbuf = intern_c_string ("gdk-pixbuf");
-  staticpro (&Qgdk_pixbuf);
-  Qglib = intern_c_string ("glib");
-  staticpro (&Qglib);
-  Qgobject = intern_c_string ("gobject");
-  staticpro (&Qgobject);
+  DEFSYM (Qgdk_pixbuf, "gdk-pixbuf");
+  DEFSYM (Qglib, "glib");
+  DEFSYM (Qgobject, "gobject");
 #endif /* HAVE_NTGUI  */
 #endif /* HAVE_RSVG  */
 
   defsubr (&Sinit_image_library);
+#ifdef HAVE_IMAGEMAGICK
+  defsubr (&Simagemagick_types);
+#endif
   defsubr (&Sclear_image_cache);
-  defsubr (&Simage_refresh);
+  defsubr (&Simage_flush);
   defsubr (&Simage_size);
   defsubr (&Simage_mask_p);
-  defsubr (&Simage_extension_data);
+  defsubr (&Simage_metadata);
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
   defsubr (&Simagep);
   defsubr (&Slookup_image);
 #endif
 
-  DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
+  DEFVAR_BOOL ("cross-disabled-images", cross_disabled_images,
     doc: /* Non-nil means always draw a cross over disabled images.
 Disabled images are those having a `:conversion disabled' property.
 A cross is always drawn on black & white displays.  */);
   cross_disabled_images = 0;
 
-  DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
+  DEFVAR_LISP ("x-bitmap-file-path", Vx_bitmap_file_path,
     doc: /* List of directories to search for window system bitmap files.  */);
   Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
 
-  DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
-    doc: /* Time after which cached images are removed from the cache.
-When an image has not been displayed this many seconds, remove it
-from the image cache.  Value must be an integer or nil with nil
-meaning don't clear the cache.  */);
-  Vimage_cache_eviction_delay = make_number (30 * 60);
-}
+  DEFVAR_LISP ("image-cache-eviction-delay", Vimage_cache_eviction_delay,
+    doc: /* Maximum time after which images are removed from the cache.
+When an image has not been displayed this many seconds, Emacs
+automatically removes it from the image cache.  If the cache contains
+a large number of images, the actual eviction time may be shorter.
+The value can also be nil, meaning the cache is never cleared.
+
+The function `clear-image-cache' disregards this variable.  */);
+  Vimage_cache_eviction_delay = make_number (300);
+#ifdef HAVE_IMAGEMAGICK
+  DEFVAR_INT ("imagemagick-render-type", imagemagick_render_type,
+    doc: /* Integer indicating which ImageMagick rendering method to use.
+The options are:
+  0 -- the default method (pixel pushing)
+  1 -- a newer method ("MagickExportImagePixels") that may perform
+       better (speed etc) in some cases, but has not been as thoroughly
+       tested with Emacs as the default method.  This method requires
+       ImageMagick version 6.4.6 (approximately) or later.
+*/);
+  /* MagickExportImagePixels is in 6.4.6-9, but not 6.4.4-10.  */
+  imagemagick_render_type = 0;
+#endif
 
-void
-init_image ()
-{
 }
-
-/* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
-   (do not change this comment) */