* image.c (imagemagick_load_image): Don't use garbage pointer image_wand.
[bpt/emacs.git] / src / image.c
index e25cef5..3d17244 100644 (file)
@@ -67,6 +67,7 @@ typedef struct x_bitmap_record Bitmap_Record;
 
 
 #ifdef HAVE_NTGUI
+#include "w32.h"
 #include "w32term.h"
 
 /* W32_TODO : Color tables on W32.  */
@@ -124,7 +125,7 @@ typedef struct ns_bitmap_record Bitmap_Record;
 
 /* The symbol `postscript' identifying images of this type.  */
 
-Lisp_Object Qpostscript;
+static Lisp_Object Qpostscript;
 
 static void x_disable_image (struct frame *, struct image *);
 static void x_edge_detection (struct frame *, struct image *, Lisp_Object,
@@ -137,6 +138,7 @@ static void free_color_table (void);
 static unsigned long *colors_in_color_table (int *n);
 static unsigned long lookup_pixel_color (struct frame *f, unsigned long p);
 #endif
+static Lisp_Object Finit_image_library (Lisp_Object, Lisp_Object);
 
 /* Code to deal with bitmaps.  Bitmaps are referenced by their bitmap
    id, which is just an int that this section returns.  Bitmaps are
@@ -555,23 +557,23 @@ x_create_bitmap_mask (struct frame *f, int id)
 
 static struct image_type *image_types;
 
-/* Cache for delayed-loading image types.  */
-
-static Lisp_Object Vimage_type_cache;
-
 /* The symbol `xbm' which is used as the type symbol for XBM images.  */
 
-Lisp_Object Qxbm;
+static Lisp_Object Qxbm;
 
 /* Keywords.  */
 
-Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data;
-Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry, QCcrop, QCrotation;
+Lisp_Object QCascent, QCmargin, QCrelief;
+static Lisp_Object Qcount, Qextension_data;
+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;
+static Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
 
 /* Function prototypes.  */
 
@@ -582,9 +584,12 @@ static void x_laplace (struct frame *, struct image *);
 static void x_emboss (struct frame *, struct image *);
 static int x_build_heuristic_mask (struct frame *, struct image *,
                                    Lisp_Object);
-
+#ifdef HAVE_NTGUI
 #define CACHE_IMAGE_TYPE(type, status) \
-  do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
+  do { Vlibrary_cache = Fcons (Fcons (type, status), Vlibrary_cache); } while (0)
+#else
+#define CACHE_IMAGE_TYPE(type, status)
+#endif
 
 #define ADD_IMAGE_TYPE(type) \
   do { Vimage_types = Fcons (type, Vimage_types); } while (0)
@@ -618,7 +623,7 @@ define_image_type (struct image_type *type, int loaded)
 /* Look up image type SYMBOL, and return a pointer to its image_type
    structure.  Value is null if SYMBOL is not a known image type.  */
 
-static INLINE struct image_type *
+static inline struct image_type *
 lookup_image_type (Lisp_Object symbol)
 {
   struct image_type *type;
@@ -831,9 +836,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
 
        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;
 
@@ -979,7 +982,6 @@ or omitted means use the selected frame.  */)
                 Image type independent image structures
  ***********************************************************************/
 
-static struct image *make_image (Lisp_Object spec, unsigned hash);
 static void free_image (struct frame *f, struct image *img);
 static int check_image_size (struct frame *f, int width, int height);
 
@@ -988,7 +990,7 @@ static int check_image_size (struct frame *f, int width, int height);
    SPEC.  SPEC has a hash value of HASH.  */
 
 static struct image *
-make_image (Lisp_Object spec, unsigned int hash)
+make_image (Lisp_Object spec, EMACS_UINT hash)
 {
   struct image *img = (struct image *) xmalloc (sizeof *img);
   Lisp_Object file = image_spec_value (spec, QCfile, NULL);
@@ -1137,7 +1139,7 @@ static RGB_PIXEL_COLOR
 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)
@@ -1385,7 +1387,6 @@ x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name,
                             Image Cache
  ***********************************************************************/
 
-static struct image *search_image_cache (struct frame *, Lisp_Object, unsigned);
 static void cache_image (struct frame *f, struct image *img);
 static void postprocess_image (struct frame *, struct image *);
 
@@ -1411,7 +1412,7 @@ make_image_cache (void)
 /* Find an image matching SPEC in the cache, and return it.  If no
    image is found, return NULL.  */
 static struct image *
-search_image_cache (struct frame *f, Lisp_Object spec, unsigned int hash)
+search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash)
 {
   struct image *img;
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
@@ -1520,7 +1521,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
        {
          /* Free cache based on timestamp.  */
          EMACS_TIME t;
-         unsigned long old;
+         time_t old;
          int delay, nimages = 0;
 
          for (i = 0; i < c->used; ++i)
@@ -1557,9 +1558,9 @@ 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;
@@ -1710,9 +1711,8 @@ postprocess_image (struct frame *f, struct image *img)
 int
 lookup_image (struct frame *f, Lisp_Object spec)
 {
-  struct image_cache *c;
   struct image *img;
-  unsigned hash;
+  EMACS_UINT hash;
   EMACS_TIME now;
 
   /* F must be a window-system frame, and SPEC must be a valid image
@@ -1720,8 +1720,6 @@ lookup_image (struct frame *f, Lisp_Object spec)
   xassert (FRAME_WINDOW_P (f));
   xassert (valid_image_p (spec));
 
-  c = FRAME_IMAGE_CACHE (f);
-
   /* Look up SPEC in the hash table of the image cache.  */
   hash = sxhash (spec, 0);
   img = search_image_cache (f, spec, hash);
@@ -1892,7 +1890,7 @@ mark_image_cache (struct image_cache *c)
 #ifdef HAVE_NTGUI
 
 /* Macro for defining functions that will be loaded from image DLLs.  */
-#define DEF_IMGLIB_FN(rettype,func,args) rettype (FAR CDECL *fn_##func)args
+#define DEF_IMGLIB_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
 
 /* Macro for loading those image functions from the library.  */
 #define LOAD_IMGLIB_FN(lib,func) {                                     \
@@ -1900,34 +1898,6 @@ mark_image_cache (struct image_cache *c)
     if (!fn_##func) return 0;                                          \
   }
 
-/* Load a DLL implementing an image type.
-   The argument LIBRARIES is usually the variable
-   `dynamic-library-alist', which associates a symbol, identifying
-   an external DLL library, to a list of possible filenames.
-   The function returns NULL if no library could be loaded for
-   the given symbol, or if the library was previously loaded;
-   else the handle of the DLL.  */
-static HMODULE
-w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
-{
-  HMODULE library = NULL;
-
-  if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
-    {
-      Lisp_Object dlls = Fassq (type, libraries);
-
-      if (CONSP (dlls))
-        for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
-          {
-            CHECK_STRING_CAR (dlls);
-            if (library = LoadLibrary (SDATA (XCAR (dlls))))
-              break;
-          }
-    }
-
-  return library;
-}
-
 #endif /* HAVE_NTGUI */
 
 static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
@@ -2142,9 +2112,6 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int he
                              File Handling
  ***********************************************************************/
 
-static unsigned char *slurp_file (char *, int *);
-
-
 /* Find image file FILE.  Look in data-directory/images, then
    x-bitmap-file-path.  Value is the encoded full name of the file
    found, or nil if not found.  */
@@ -2181,7 +2148,7 @@ x_find_image_file (Lisp_Object file)
    occurred.  *SIZE is set to the size of the file.  */
 
 static unsigned char *
-slurp_file (char *file, int *size)
+slurp_file (char *file, ptrdiff_t *size)
 {
   FILE *fp = NULL;
   unsigned char *buf = NULL;
@@ -2189,6 +2156,7 @@ slurp_file (char *file, int *size)
 
   if (stat (file, &st) == 0
       && (fp = fopen (file, "rb")) != NULL
+      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
       && (buf = (unsigned char *) xmalloc (st.st_size),
          fread (buf, 1, st.st_size, fp) == st.st_size))
     {
@@ -2359,7 +2327,7 @@ xbm_image_p (Lisp_Object object)
          int i;
 
          /* Number of elements of the vector must be >= height.  */
-         if (XVECTOR (data)->size < height)
+         if (ASIZE (data) < height)
            return 0;
 
          /* Each string or bool-vector in data must be large enough
@@ -2651,11 +2619,11 @@ xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *e
 
       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);
@@ -2844,7 +2812,7 @@ xbm_load (struct frame *f, struct image *img)
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
@@ -2880,6 +2848,7 @@ xbm_load (struct frame *f, struct image *img)
       /* Parse the image specification.  */
       memcpy (fmt, xbm_format, sizeof fmt);
       parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
+      (void) parsed_p;
       xassert (parsed_p);
 
       /* Get specified width, and height.  */
@@ -3004,7 +2973,7 @@ static int xpm_valid_color_symbols_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.  */
 
@@ -3095,7 +3064,7 @@ 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.  */
 
@@ -3311,7 +3280,7 @@ xpm_image_p (Lisp_Object object)
 
 #endif /* HAVE_XPM || HAVE_NS */
 
-#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+#if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK
 int
 x_create_bitmap_from_xpm_data (struct frame *f, const char **bits)
 {
@@ -3425,11 +3394,12 @@ xpm_load (struct frame *f, struct image *img)
        {
          Lisp_Object name;
          Lisp_Object color;
+         char *empty_string = (char *) "";
 
          if (!CONSP (XCAR (tail)))
            {
-             xpm_syms[i].name = "";
-             xpm_syms[i].value = "";
+             xpm_syms[i].name = empty_string;
+             xpm_syms[i].value = empty_string;
              continue;
            }
          name = XCAR (XCAR (tail));
@@ -3440,14 +3410,14 @@ xpm_load (struct frame *f, struct image *img)
              strcpy (xpm_syms[i].name, SSDATA (name));
            }
          else
-           xpm_syms[i].name = "";
+           xpm_syms[i].name = empty_string;
          if (STRINGP (color))
            {
              xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
              strcpy (xpm_syms[i].value, SSDATA (color));
            }
          else
-           xpm_syms[i].value = "";
+           xpm_syms[i].value = empty_string;
        }
     }
 
@@ -3777,7 +3747,7 @@ xpm_put_color_table_h (Lisp_Object color_table,
                        Lisp_Object color)
 {
   struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
-  unsigned hash_code;
+  EMACS_UINT hash_code;
   Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
 
   hash_lookup (table, chars, &hash_code);
@@ -4067,7 +4037,7 @@ xpm_load (struct frame *f,
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
@@ -4134,11 +4104,11 @@ 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;
 
 /* Initialize the color table.  */
 
@@ -4484,7 +4454,6 @@ static void
 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.  */
@@ -4603,14 +4572,14 @@ x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjus
 
       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;
@@ -4686,7 +4655,7 @@ x_edge_detection (struct frame *f, struct image *img, Lisp_Object matrix,
     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));
 }
 
 
@@ -4928,7 +4897,7 @@ 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.  */
 
@@ -5050,6 +5019,7 @@ pbm_read_file (file, size)
 
   if (stat (SDATA (file), &st) == 0
       && (fp = fopen (SDATA (file), "rb")) != NULL
+      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
       && (buf = (char *) xmalloc (st.st_size),
          fread (buf, 1, st.st_size, fp) == st.st_size))
     {
@@ -5084,7 +5054,7 @@ pbm_load (struct frame *f, struct image *img)
   enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
   unsigned char *contents = NULL;
   unsigned char *end, *p;
-  int size;
+  ptrdiff_t size;
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
 
@@ -5345,7 +5315,7 @@ 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.  */
 
@@ -5451,7 +5421,6 @@ init_png_functions (Lisp_Object libraries)
 {
   HMODULE library;
 
-  /* Try loading libpng under probable names.  */
   if (!(library = w32_delayed_load (libraries, Qpng)))
     return 0;
 
@@ -5529,6 +5498,7 @@ init_png_functions (Lisp_Object libraries)
 /* Error and warning handlers installed when the PNG library
    is initialized.  */
 
+static void my_png_error (png_struct *, const char *) NO_RETURN;
 static void
 my_png_error (png_struct *png_ptr, const char *msg)
 {
@@ -5958,7 +5928,7 @@ 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.  */
 
@@ -6103,6 +6073,7 @@ struct my_jpeg_error_mgr
 };
 
 
+static void my_error_exit (j_common_ptr) NO_RETURN;
 static void
 my_error_exit (j_common_ptr cinfo)
 {
@@ -6363,10 +6334,10 @@ jpeg_load (struct frame *f, struct image *img)
       if (rc == 1)
        {
          /* Called from my_error_exit.  Display a JPEG error.  */
-         char buffer[JMSG_LENGTH_MAX];
-         cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
+         char buf[JMSG_LENGTH_MAX];
+         cinfo.err->format_message ((j_common_ptr) &cinfo, buf);
          image_error ("Error reading JPEG image `%s': %s", img->spec,
-                      build_string (buffer));
+                      build_string (buf));
        }
 
       /* Close the input file and destroy the JPEG object.  */
@@ -6506,7 +6477,7 @@ 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.  */
 
@@ -6716,6 +6687,8 @@ tiff_size_of_memory (thandle_t data)
 }
 
 
+static void tiff_error_handler (const char *, const char *, va_list)
+  ATTRIBUTE_FORMAT_PRINTF (2, 0);
 static void
 tiff_error_handler (const char *title, const char *format, va_list ap)
 {
@@ -6728,6 +6701,8 @@ tiff_error_handler (const char *title, const char *format, va_list ap)
 }
 
 
+static void tiff_warning_handler (const char *, const char *, va_list)
+  ATTRIBUTE_FORMAT_PRINTF (2, 0);
 static void
 tiff_warning_handler (const char *title, const char *format, va_list ap)
 {
@@ -6751,7 +6726,7 @@ tiff_load (struct frame *f, struct image *img)
   TIFF *tiff;
   int width, height, x, y, count;
   uint32 *buf;
-  int rc, rc2;
+  int rc;
   XImagePtr ximg;
   tiff_memory_source memsrc;
   Lisp_Object image;
@@ -6759,8 +6734,8 @@ tiff_load (struct frame *f, struct image *img)
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
 
-  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))
     {
@@ -6839,8 +6814,8 @@ tiff_load (struct frame *f, struct image *img)
   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,
@@ -6930,7 +6905,7 @@ 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.  */
 
@@ -7099,22 +7074,19 @@ static const int interlace_increment[] = {8, 8, 4, 2};
 static int
 gif_load (struct frame *f, struct image *img)
 {
-  Lisp_Object file, specified_file;
-  Lisp_Object specified_data;
-  int rc, width, height, x, y, i;
-  boolean transparent_p;
+  Lisp_Object file;
+  int rc, width, height, x, y, i, j;
   XImagePtr ximg;
   ColorMapObject *gif_color_map;
   unsigned long pixel_colors[256];
   GifFileType *gif;
-  Lisp_Object image;
-  int ino, image_height, image_width;
+  int image_height, image_width;
   gif_memory_source memsrc;
-  unsigned char *raster;
-  unsigned int transparency_color_index;
-
-  specified_file = image_spec_value (img->spec, QCfile, NULL);
-  specified_data = image_spec_value (img->spec, QCdata, NULL);
+  Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+  Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
+  Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL);
+  unsigned long bgcolor = 0;
+  int idx;
 
   if (NILP (specified_data))
     {
@@ -7126,7 +7098,7 @@ gif_load (struct frame *f, struct image *img)
        }
 
       /* Open the GIF file.  */
-      gif = fn_DGifOpenFileName (SDATA (file));
+      gif = fn_DGifOpenFileName (SSDATA (file));
       if (gif == NULL)
        {
          image_error ("Cannot open `%s'", file, Qnil);
@@ -7165,40 +7137,31 @@ gif_load (struct frame *f, struct image *img)
 
   /* Read entire contents.  */
   rc = fn_DGifSlurp (gif);
-  if (rc == GIF_ERROR)
+  if (rc == GIF_ERROR || gif->ImageCount <= 0)
     {
       image_error ("Error reading `%s'", img->spec, Qnil);
       fn_DGifCloseFile (gif);
       return 0;
     }
 
-  image = image_spec_value (img->spec, QCindex, NULL);
-  ino = INTEGERP (image) ? XFASTINT (image) : 0;
-  if (ino >= gif->ImageCount)
-    {
-      image_error ("Invalid image number `%s' in image `%s'",
-                  image, img->spec);
-      fn_DGifCloseFile (gif);
-      return 0;
-    }
-
-  for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++)
-    if ((gif->SavedImages[ino].ExtensionBlocks[i].Function
-        == GIF_LOCAL_DESCRIPTOR_EXTENSION)
-       && gif->SavedImages[ino].ExtensionBlocks[i].ByteCount == 4
-       /* Transparency enabled?  */
-       && gif->SavedImages[ino].ExtensionBlocks[i].Bytes[0] & 1)
+  /* Which sub-image are we to display?  */
+  {
+    Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL);
+    idx = INTEGERP (image_number) ? XFASTINT (image_number) : 0;
+    if (idx < 0 || idx >= gif->ImageCount)
       {
-       transparent_p = 1;
-       transparency_color_index
-         = (unsigned char) gif->SavedImages[ino].ExtensionBlocks[i].Bytes[3];
+       image_error ("Invalid image number `%s' in image `%s'",
+                    image_number, img->spec);
+       fn_DGifCloseFile (gif);
+       return 0;
       }
+  }
 
-  img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
-  img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
-  image_height = gif->SavedImages[ino].ImageDesc.Height;
+  img->corners[TOP_CORNER] = gif->SavedImages[idx].ImageDesc.Top;
+  img->corners[LEFT_CORNER] = gif->SavedImages[idx].ImageDesc.Left;
+  image_height = gif->SavedImages[idx].ImageDesc.Height;
   img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
-  image_width = gif->SavedImages[ino].ImageDesc.Width;
+  image_width = gif->SavedImages[idx].ImageDesc.Width;
   img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
 
   width = img->width = max (gif->SWidth,
@@ -7222,44 +7185,10 @@ gif_load (struct frame *f, struct image *img)
       return 0;
     }
 
-  /* Allocate colors.  */
-  gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
-  if (!gif_color_map)
-    gif_color_map = gif->SColorMap;
-  init_color_table ();
-  memset (pixel_colors, 0, sizeof pixel_colors);
-
-  if (gif_color_map)
-    for (i = 0; i < gif_color_map->ColorCount; ++i)
-      {
-       if (transparent_p && transparency_color_index == i)
-         {
-           Lisp_Object specified_bg
-             = image_spec_value (img->spec, QCbackground, NULL);
-           pixel_colors[i] = STRINGP (specified_bg)
-             ? x_alloc_image_color (f, img, specified_bg,
-                                    FRAME_BACKGROUND_PIXEL (f))
-             : FRAME_BACKGROUND_PIXEL (f);
-         }
-       else
-         {
-           int r = gif_color_map->Colors[i].Red << 8;
-           int g = gif_color_map->Colors[i].Green << 8;
-           int b = gif_color_map->Colors[i].Blue << 8;
-           pixel_colors[i] = lookup_rgb_color (f, r, g, b);
-         }
-      }
-
-#ifdef COLOR_TABLE_SUPPORT
-  img->colors = colors_in_color_table (&img->ncolors);
-  free_color_table ();
-#endif /* COLOR_TABLE_SUPPORT */
-
-  /* Clear the part of the screen image that are not covered by
-     the image from the GIF file.  Full animated GIF support
-     requires more than can be done here (see the gif89 spec,
-     disposal methods).  Let's simply assume that the part
-     not covered by a sub-image is in the frame's background color.  */
+  /* Clear the part of the screen image not covered by the image.
+     Full animated GIF support requires more here (see the gif89 spec,
+     disposal methods).  Let's simply assume that the part not covered
+     by a sub-image is in the frame's background color.  */
   for (y = 0; y < img->corners[TOP_CORNER]; ++y)
     for (x = 0; x < width; ++x)
       XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
@@ -7276,55 +7205,119 @@ gif_load (struct frame *f, struct image *img)
        XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
     }
 
-  /* Read the GIF image into the X image.  We use a local variable
-     `raster' here because RasterBits below is a char *, and invites
-     problems with bytes >= 0x80.  */
-  raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
+  /* Read the GIF image into the X image.   */
 
-  if (gif->SavedImages[ino].ImageDesc.Interlace)
-    {
-      int pass;
-      int row = interlace_start[0];
-
-      pass = 0;
+  /* FIXME: With the current implementation, loading an animated gif
+     is quadratic in the number of animation frames, since each frame
+     is a separate struct image.  We must provide a way for a single
+     gif_load call to construct and save all animation frames.  */
 
-      for (y = 0; y < image_height; y++)
+  init_color_table ();
+  if (STRINGP (specified_bg))
+    bgcolor = x_alloc_image_color (f, img, specified_bg,
+                                  FRAME_BACKGROUND_PIXEL (f));
+  for (j = 0; j <= idx; ++j)
+    {
+      /* We use a local variable `raster' here because RasterBits is a
+        char *, which invites problems with bytes >= 0x80.  */
+      struct SavedImage *subimage = gif->SavedImages + j;
+      unsigned char *raster = (unsigned char *) subimage->RasterBits;
+      int transparency_color_index = -1;
+      int disposal = 0;
+
+      /* Find the Graphic Control Extension block for this sub-image.
+        Extract the disposal method and transparency color.  */
+      for (i = 0; i < subimage->ExtensionBlockCount; i++)
        {
-         if (row >= image_height)
-           {
-             row = interlace_start[++pass];
-             while (row >= image_height)
-               row = interlace_start[++pass];
-           }
+         ExtensionBlock *extblock = subimage->ExtensionBlocks + i;
 
-         for (x = 0; x < image_width; x++)
+         if ((extblock->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION)
+             && extblock->ByteCount == 4
+             && extblock->Bytes[0] & 1)
            {
-             int 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;
+
+      /* 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 < image_height;
+              y++, row += interlace_increment[pass])
+           {
+             if (row >= image_height)
+               {
+                 row = interlace_start[++pass];
+                 while (row >= image_height)
+                   row = interlace_start[++pass];
+               }
+
+             for (x = 0; x < image_width; x++)
+               {
+                 int c = raster[y * image_width + x];
+                 if (transparency_color_index != c || disposal != 1)
+                   XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+                              row + img->corners[TOP_CORNER], pixel_colors[c]);
+               }
+           }
+       }
+      else
+       {
+         for (y = 0; y < image_height; ++y)
+           for (x = 0; x < image_width; ++x)
+             {
+               int c = raster[y * image_width + x];
+               if (transparency_color_index != c || disposal != 1)
+                 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+                            y + img->corners[TOP_CORNER], pixel_colors[c]);
+             }
+       }
     }
 
+#ifdef COLOR_TABLE_SUPPORT
+  img->colors = colors_in_color_table (&img->ncolors);
+  free_color_table ();
+#endif /* COLOR_TABLE_SUPPORT */
+
   /* Save GIF image extension data for `image-metadata'.
      Format is (count IMAGES extension-data (FUNCTION "BYTES" ...)).  */
   img->data.lisp_val = Qnil;
-  if (gif->SavedImages[ino].ExtensionBlockCount > 0)
+  if (gif->SavedImages[idx].ExtensionBlockCount > 0)
     {
-      ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
-      for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
+      ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks;
+      for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++)
        /* Append (... FUNCTION "BYTES") */
        img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
                                    Fcons (make_number (ext->Function),
@@ -7368,14 +7361,17 @@ gif_load (struct frame *f, struct image *img)
 
 
 /***********************************************************************
-                                imagemagick
+                                ImageMagick
 ***********************************************************************/
 #if defined (HAVE_IMAGEMAGICK)
 
-/* The symbol `imagemagick' identifying images of this type.  */
-
 Lisp_Object Qimagemagick;
-/* Indices of image specification fields in imagemagick_format, below.  */
+
+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
   {
@@ -7416,6 +7412,19 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
     {":rotation",      IMAGE_NUMBER_VALUE,                     0},
     {":crop",          IMAGE_DONT_CHECK_VALUE_TYPE,            0}
   };
+
+/* Structure describing the image type for any image handled via
+   ImageMagick.  */
+
+static struct image_type imagemagick_type =
+  {
+    &Qimagemagick,
+    imagemagick_image_p,
+    imagemagick_load,
+    imagemagick_clear_image,
+    NULL
+  };
+
 /* Free X resources of imagemagick image IMG which is used on frame F.  */
 
 static void
@@ -7425,8 +7434,6 @@ imagemagick_clear_image (struct frame *f,
   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.   */
@@ -7449,38 +7456,29 @@ imagemagick_image_p (Lisp_Object object)
 #define DrawRectangle DrawRectangleGif
 #include <wand/MagickWand.h>
 
-/* imagemagick_load_image is a helper function for imagemagick_load,
-   which does the actual loading given contents and size, apart from
-   frame and image structures, passed from imagemagick_load.
+/* Helper function for imagemagick_load, which does the actual loading
+   given contents and size, apart from frame and image structures,
+   passed from imagemagick_load.  Uses librimagemagick to do most of
+   the image processing.
 
-   Uses librimagemagick to do most of the image processing.
+   F is a pointer to the Emacs frame; IMG to the image structure to
+   prepare; CONTENTS is the string containing the IMAGEMAGICK data to
+   be parsed; SIZE is the number of bytes of data; and FILENAME is
+   either the file name or the image data.
 
-   non-zero when successful.
-*/
+   Return non-zero if successful.  */
 
 static int
-imagemagick_load_image (/* Pointer to emacs frame structure.  */
-                        struct frame *f,
-                        /* Pointer to emacs image structure.  */
-                        struct image *img,
-                        /* String containing the IMAGEMAGICK data to
-                           be parsed.  */
-                        unsigned char *contents,
-                        /* Size of data in bytes.  */
-                        unsigned int size,
-                        /* Filename, either pass filename or
-                           contents/size.  */
-                        unsigned char *filename)
+imagemagick_load_image (struct frame *f, struct image *img,
+                       unsigned char *contents, unsigned int size,
+                       char *filename)
 {
   unsigned long width;
   unsigned long height;
 
-  MagickBooleanType
-    status;
+  MagickBooleanType status;
 
   XImagePtr ximg;
-  Lisp_Object specified_bg;
-  XColor background;
   int x;
   int y;
 
@@ -7491,7 +7489,7 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
   MagickPixelPacket  pixel;
   Lisp_Object image;
   Lisp_Object value;
-  Lisp_Object crop, geometry;
+  Lisp_Object crop;
   long ino;
   int desired_width, desired_height;
   double rotation;
@@ -7502,12 +7500,12 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
   Image * im_image;
 
 
-  /* 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.  */
+  /* 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.  */
 
-  /* `MagickWandGenesis' initializes the imagemagick environment.  */
+  /* Initialize the imagemagick environment.  */
   MagickWandGenesis ();
   image = image_spec_value (img->spec, QCindex, NULL);
   ino = INTEGERP (image) ? XFASTINT (image) : 0;
@@ -7538,8 +7536,8 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
 
   DestroyMagickWand (ping_wand);
 
-  /* Now, after pinging, we know how many images are inside the
-     file. If its not a bundle, just one.  */
+  /* Now we know how many images are inside the file.  If it's not a
+     bundle, the number is one.  */
 
   if (filename != NULL)
     {
@@ -7552,25 +7550,20 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
       im_image = ReadImage (image_info, exception);
       DestroyExceptionInfo (exception);
 
-      if (im_image != NULL)
-       {
-         image_wand = NewMagickWandFromImage (im_image);
-          DestroyImage(im_image);
-         status = MagickTrue;
-       }
-      else
-       status = MagickFalse;
+      if (im_image == NULL)
+       goto imagemagick_no_wand;
+      image_wand = NewMagickWandFromImage (im_image);
+      DestroyImage(im_image);
     }
   else
     {
       image_wand = NewMagickWand ();
-      status = MagickReadImageBlob (image_wand, contents, size);
+      if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse)
+       goto imagemagick_error;
     }
 
-  if (status == MagickFalse) goto imagemagick_error;
-
   /* If width and/or height is set in the display spec assume we want
-     to scale to those values.  if either h or w is unspecified, the
+     to scale to those values.  If either h or w is unspecified, the
      unspecified should be calculated from the specified to preserve
      aspect ratio.  */
 
@@ -7582,17 +7575,13 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
   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)
+  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)
@@ -7602,20 +7591,18 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
        }
     }
 
-
   /* crop behaves similar to image slicing in Emacs but is more memory
      efficient.  */
   crop = image_spec_value (img->spec, QCcrop, NULL);
 
   if (CONSP (crop) && INTEGERP (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 croping, which is aparently
-         difficult to avoid when using imagemagick.  */
-
-      int w, h, x, y;
+      /* 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 croping, which is aparently difficult to avoid when using
+         imagemagick.  */
+      int w, h;
       w = XFASTINT (XCAR (crop));
       crop = XCDR (crop);
       if (CONSP (crop) && INTEGERP (XCAR (crop)))
@@ -7658,8 +7645,8 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
         }
     }
 
-  /* Finaly we are done manipulating the image, figure out resulting
-     width, height, and then transfer ownerwship to Emacs.  */
+  /* Finally we are done manipulating the image.  Figure out the
+     resulting width/height and transfer ownerwship to Emacs.  */
   height = MagickGetImageHeight (image_wand);
   width = MagickGetImageWidth (image_wand);
 
@@ -7729,7 +7716,7 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
          method is also well tested. Some aspects of this method are
          ad-hoc and needs to be more researched. */
       int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/
-      char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
+      const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
       /* Try to create a x pixmap to hold the imagemagick pixmap.  */
       if (!x_create_x_image_and_pixmap (f, width, height, imagedepth,
                                         &ximg, &img->pixmap))
@@ -7802,6 +7789,7 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
 
  imagemagick_error:
   DestroyMagickWand (image_wand);
+ imagemagick_no_wand:
   MagickWandTerminus ();
   /* TODO more cleanup.  */
   image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
@@ -7814,8 +7802,7 @@ imagemagick_load_image (/* Pointer to emacs frame structure.  */
    the prototype thus needs to be compatible with that structure.  */
 
 static int
-imagemagick_load (struct frame *f,
-                  struct image *img)
+imagemagick_load (struct frame *f, struct image *img)
 {
   int success_p = 0;
   Lisp_Object file_name;
@@ -7832,7 +7819,7 @@ imagemagick_load (struct frame *f,
          image_error ("Cannot find image file `%s'", file_name, Qnil);
          return 0;
        }
-      success_p = imagemagick_load_image (f, img, 0, 0, SDATA (file));
+      success_p = imagemagick_load_image (f, img, 0, 0, SSDATA (file));
     }
   /* Else its not a file, its a lisp object.  Load the image from a
      lisp object rather than a file.  */
@@ -7853,38 +7840,18 @@ imagemagick_load (struct frame *f,
   return success_p;
 }
 
-/* Structure describing the image type `imagemagick'.  Its the same
-   type of structure defined for all image formats, handled by Emacs
-   image functions.  See struct image_type in dispextern.h.  */
-
-static struct image_type imagemagick_type =
-  {
-    /* An identifier showing that this is an image structure for the
-       IMAGEMAGICK format.  */
-    &Qimagemagick,
-    /* Handle to a function that can be used to identify a IMAGEMAGICK
-       file.  */
-    imagemagick_image_p,
-    /* Handle to function used to load a IMAGEMAGICK file.  */
-    imagemagick_load,
-    /* Handle to function to free resources for IMAGEMAGICK.  */
-    imagemagick_clear_image,
-    /* An internal field to link to the next image type in a list of
-       image types, will be filled in when registering the format.  */
-    NULL
-  };
-
-
-
-
 DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0,
-       doc: /* Return image file types supported by ImageMagick.
-Since ImageMagick recognizes a lot of file-types that clash with Emacs,
-such as .c, we want to be able to alter the list at the lisp level.  */)
+       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).
+
+Note that ImageMagick recognizes many file-types that Emacs does not
+recognize as images, such as C.  See `imagemagick-types-inhibit'.  */)
   (void)
 {
   Lisp_Object typelist = Qnil;
-  unsigned long numf;
+  unsigned long numf = 0;
   ExceptionInfo ex;
   char **imtypes = GetMagickList ("*", &numf, &ex);
   int i;
@@ -7913,7 +7880,7 @@ static int svg_image_p (Lisp_Object object);
 static int svg_load (struct frame *f, struct image *img);
 
 static int svg_load_image (struct frame *, struct image *,
-                           unsigned char *, unsigned int);
+                           unsigned char *, ptrdiff_t);
 
 /* The symbol `svg' identifying images of this type. */
 
@@ -8000,7 +7967,6 @@ DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions);
 DEF_IMGLIB_FN (gboolean, rsvg_handle_write);
 DEF_IMGLIB_FN (gboolean, rsvg_handle_close);
 DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf);
-DEF_IMGLIB_FN (void, rsvg_handle_free);
 
 DEF_IMGLIB_FN (int, gdk_pixbuf_get_width);
 DEF_IMGLIB_FN (int, gdk_pixbuf_get_height);
@@ -8033,7 +7999,6 @@ init_svg_functions (Lisp_Object libraries)
   LOAD_IMGLIB_FN (library, rsvg_handle_write);
   LOAD_IMGLIB_FN (library, rsvg_handle_close);
   LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
-  LOAD_IMGLIB_FN (library, rsvg_handle_free);
 
   LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
   LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
@@ -8059,7 +8024,6 @@ init_svg_functions (Lisp_Object libraries)
 #define fn_rsvg_handle_write           rsvg_handle_write
 #define fn_rsvg_handle_close           rsvg_handle_close
 #define fn_rsvg_handle_get_pixbuf      rsvg_handle_get_pixbuf
-#define fn_rsvg_handle_free            rsvg_handle_free
 
 #define fn_gdk_pixbuf_get_width                  gdk_pixbuf_get_width
 #define fn_gdk_pixbuf_get_height         gdk_pixbuf_get_height
@@ -8091,7 +8055,7 @@ svg_load (struct frame *f, struct image *img)
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
@@ -8101,7 +8065,7 @@ svg_load (struct frame *f, struct image *img)
        }
 
       /* Read the entire file into memory.  */
-      contents = slurp_file (SDATA (file), &size);
+      contents = slurp_file (SSDATA (file), &size);
       if (contents == NULL)
        {
          image_error ("Error loading SVG image `%s'", img->spec, Qnil);
@@ -8140,11 +8104,11 @@ static int
 svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  */
                struct image *img,       /* Pointer to emacs image structure.  */
                unsigned char *contents, /* String containing the SVG XML data to be parsed.  */
-               unsigned int size)       /* Size of data in bytes.  */
+               ptrdiff_t size)          /* Size of data in bytes.  */
 {
   RsvgHandle *rsvg_handle;
   RsvgDimensionData dimension_data;
-  GError *error = NULL;
+  GError *err = NULL;
   GdkPixbuf *pixbuf;
   int width;
   int height;
@@ -8163,13 +8127,13 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   rsvg_handle = fn_rsvg_handle_new ();
 
   /* Parse the contents argument and fill in the rsvg_handle.  */
-  fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
-  if (error) goto rsvg_error;
+  fn_rsvg_handle_write (rsvg_handle, contents, size, &err);
+  if (err) goto rsvg_error;
 
   /* The parsing is complete, rsvg_handle is ready to used, close it
      for further writes.  */
-  fn_rsvg_handle_close (rsvg_handle, &error);
-  if (error) goto rsvg_error;
+  fn_rsvg_handle_close (rsvg_handle, &err);
+  if (err) goto rsvg_error;
 
   fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
   if (! check_image_size (f, dimension_data.width, dimension_data.height))
@@ -8209,7 +8173,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
      color.  */
   specified_bg = image_spec_value (img->spec, QCbackground, NULL);
   if (!STRINGP (specified_bg)
-      || !x_defined_color (f, SDATA (specified_bg), &background, 0))
+      || !x_defined_color (f, SSDATA (specified_bg), &background, 0))
     {
 #ifndef HAVE_NS
       background.pixel = FRAME_BACKGROUND_PIXEL (f);
@@ -8284,7 +8248,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   /* FIXME: Use error->message so the user knows what is the actual
      problem with the image.  */
   image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
-  fn_g_error_free (error);
+  fn_g_error_free (err);
   return 0;
 }
 
@@ -8309,7 +8273,7 @@ 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.  */
 
@@ -8401,7 +8365,7 @@ gs_image_p (Lisp_Object object)
     }
   else if (VECTORP (tem))
     {
-      if (XVECTOR (tem)->size != 4)
+      if (ASIZE (tem) != 4)
        return 0;
       for (i = 0; i < 4; ++i)
        if (!INTEGERP (XVECTOR (tem)->contents[i]))
@@ -8634,12 +8598,16 @@ Libraries to load are specified in alist LIBRARIES (usually, the value
 of `dynamic-library-alist', which see).  */)
   (Lisp_Object type, Lisp_Object libraries)
 {
-  Lisp_Object tested;
-
+#ifdef HAVE_NTGUI
   /* Don't try to reload the library.  */
-  tested = Fassq (type, Vimage_type_cache);
+  Lisp_Object tested = Fassq (type, Vlibrary_cache);
   if (CONSP (tested))
     return XCDR (tested);
+#endif
+
+  /* Types pbm and xbm are built-in and always available.  */
+  if (EQ (type, Qpbm) || EQ (type, Qxbm))
+    return Qt;
 
 #if defined (HAVE_XPM) || defined (HAVE_NS)
   if (EQ (type, Qxpm))
@@ -8673,10 +8641,8 @@ of `dynamic-library-alist', which see).  */)
 
 #if defined (HAVE_IMAGEMAGICK)
   if (EQ (type, Qimagemagick))
-    {
-      return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions,
-                                 libraries);
-    }
+    return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions,
+                                libraries);
 #endif
 
 #ifdef HAVE_GHOSTSCRIPT
@@ -8717,9 +8683,6 @@ as a ratio to the frame height and width.  If the value is
 non-numeric, there is no explicit limit on the size of images.  */);
   Vmax_image_size = make_float (MAX_IMAGE_SIZE);
 
-  Vimage_type_cache = Qnil;
-  staticpro (&Vimage_type_cache);
-
   Qpbm = intern_c_string ("pbm");
   staticpro (&Qpbm);
   ADD_IMAGE_TYPE (Qpbm);