diff src/glyphs-x.c @ 207:e45d5e7c476e r20-4b2

Import from CVS: tag r20-4b2
author cvs
date Mon, 13 Aug 2007 10:03:52 +0200
parents 169c0442b401
children 41ff10fd062f
line wrap: on
line diff
--- a/src/glyphs-x.c	Mon Aug 13 10:02:48 2007 +0200
+++ b/src/glyphs-x.c	Mon Aug 13 10:03:52 2007 +0200
@@ -37,8 +37,7 @@
    Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
 
    TODO:
-   TIFF Support
-   Loadable module support for images
+   ImageMagick support
    Convert images.el to C and stick it in here?
  */
 
@@ -57,16 +56,14 @@
 
 #include "sysfile.h"
 
-#ifdef HAVE_PNG
-#ifdef __cplusplus
-extern "C" {
-#endif
-#include <png.h>
-#ifdef __cplusplus
-}
-#endif
-#else
-#include <setjmp.h>
+#ifdef HAVE_IMAGEMAGICK
+#define HAVE_X11_MAGICK_IMAGE_H
+#endif /* HAVE_IMAGEMAGICK */
+
+#ifdef HAVE_X11_MAGICK_IMAGE_H
+#include <magick.h>
+/* #include <image.h> */
+#include <assert.h>
 #endif
 
 #define LISP_DEVICE_TO_X_SCREEN(dev)					\
@@ -89,24 +86,9 @@
 Lisp_Object Qxface;
 #endif
 
-#ifdef HAVE_JPEG
-DEFINE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
-Lisp_Object Qjpeg;
-#endif
-
-#ifdef HAVE_PNG
-DEFINE_IMAGE_INSTANTIATOR_FORMAT (png);
-Lisp_Object Qpng;
-#endif
-
-#ifdef HAVE_TIFF
-DEFINE_IMAGE_INSTANTIATOR_FORMAT (tiff);
-Lisp_Object Qtiff;
-#endif
-
-#ifdef HAVE_GIF
-DEFINE_IMAGE_INSTANTIATOR_FORMAT (gif);
-Lisp_Object Qgif;
+#ifdef HAVE_IMAGEMAGICK
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (imagick);
+Lisp_Object Qimagick;
 #endif
 
 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
@@ -960,7 +942,7 @@
       break;
 
     case IMAGE_POINTER:
-      {
+    {
 	XColor fg_color, bg_color;
 	Pixmap source;
 
@@ -999,7 +981,7 @@
       abort ();
     }
 }
-
+
 static int
 xbm_possible_dest_types (void)
 {
@@ -1023,7 +1005,7 @@
   CONST char *gcc_may_you_rot_in_hell;
 
   if (!NILP (mask_data))
-    {
+{
       GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (mask_data))),
 				       gcc_may_you_rot_in_hell);
       mask =
@@ -1032,7 +1014,7 @@
 				XINT (XCAR (XCDR (mask_data))),
 				(CONST unsigned char *)
 				gcc_may_you_rot_in_hell);
-    }
+}
 
   init_image_instance_from_xbm_inline (ii, width, height, bits,
 				       instantiator, pointer_fg, pointer_bg,
@@ -1043,8 +1025,8 @@
 
 static void
 xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
-		 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
-		 int dest_mask, Lisp_Object domain)
+		  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+		  int dest_mask, Lisp_Object domain)
 {
   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
   CONST char *gcc_go_home;
@@ -1060,1285 +1042,6 @@
 }
 
 
-#define USE_TEMP_FILES_FOR_PNG_IMAGES 1
-
-#ifdef HAVE_JPEG
-
-/**********************************************************************
- *                             JPEG                                   *
- **********************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#include <jpeglib.h>
-#include <jerror.h>
-#ifdef __cplusplus
-}
-#endif
-
-/* The in-core jpeg code doesn't work, so I'm avoiding it for now.  -sb  */
-/* Late-breaking update, we're going to give it a try, I think it's */
-/* fixed now -sb */
-/*#define USE_TEMP_FILES_FOR_JPEG_IMAGES 1*/
-static void
-jpeg_validate (Lisp_Object instantiator)
-{
-  file_or_data_must_be_present (instantiator);
-}
-
-static Lisp_Object
-jpeg_normalize (Lisp_Object inst, Lisp_Object console_type)
-{
-  return simple_image_type_normalize (inst, console_type, Qjpeg);
-}
-
-static int
-jpeg_possible_dest_types (void)
-{
-  return IMAGE_COLOR_PIXMAP_MASK;
-}
-
-/* To survive the otherwise baffling complexity of making sure
-   everything gets cleaned up in the presence of an error, we
-   use an unwind_protect(). */
-
-struct jpeg_unwind_data
-{
-  Display *dpy;
-  /* Stream that we need to close */
-  FILE *instream;
-  /* Object that holds state info for JPEG decoding */
-  struct jpeg_decompress_struct *cinfo_ptr;
-  /* Pixels to keep around while the image is active */
-  unsigned long *pixels;
-  int npixels;
-  /* Client-side image structure */
-  XImage *ximage;
-  /* Tempfile to remove */
-  char tempfile[50];
-  int tempfile_needs_to_be_removed;
-};
-
-static Lisp_Object
-jpeg_instantiate_unwind (Lisp_Object unwind_obj)
-{
-  struct jpeg_unwind_data *data =
-    (struct jpeg_unwind_data *) get_opaque_ptr (unwind_obj);
-
-  free_opaque_ptr (unwind_obj);
-  if (data->cinfo_ptr)
-    jpeg_destroy_decompress (data->cinfo_ptr);
-
-  if (data->instream)
-    fclose (data->instream);
-
-  if (data->tempfile_needs_to_be_removed)
-    unlink (data->tempfile);
-
-  if (data->npixels > 0)
-    {
-      Screen *scr = DefaultScreenOfDisplay (data->dpy);
-      Colormap cmap = DefaultColormapOfScreen (scr);
-      XFreeColors (data->dpy, cmap, data->pixels, data->npixels, 0L);
-      xfree (data->pixels);
-    }
-
-  if (data->ximage)
-    {
-      if (data->ximage->data)
-        {
-	  xfree (data->ximage->data);
-          data->ximage->data = 0;
-        }
-      XDestroyImage (data->ximage);
-    }
-
-  return Qnil;
-}
-
-/*
- * ERROR HANDLING:
- *
- * The JPEG library's standard error handler (jerror.c) is divided into
- * several "methods" which you can override individually.  This lets you
- * adjust the behavior without duplicating a lot of code, which you might
- * have to update with each future release.
- *
- * Our example here shows how to override the "error_exit" method so that
- * control is returned to the library's caller when a fatal error occurs,
- * rather than calling exit() as the standard error_exit method does.
- *
- * We use C's setjmp/longjmp facility to return control.  This means that the
- * routine which calls the JPEG library must first execute a setjmp() call to
- * establish the return point.  We want the replacement error_exit to do a
- * longjmp().  But we need to make the setjmp buffer accessible to the
- * error_exit routine.  To do this, we make a private extension of the
- * standard JPEG error handler object.  (If we were using C++, we'd say we
- * were making a subclass of the regular error handler.)
- *
- * Here's the extended error handler struct:
- */
-
-struct my_jpeg_error_mgr
-{
-  struct jpeg_error_mgr pub;	/* "public" fields */
-  jmp_buf setjmp_buffer;	/* for return to caller */
-};
-
-#if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
-METHODDEF(void)
-#else
-METHODDEF void
-#endif
-our_init_source (j_decompress_ptr cinfo) {
-}
-
-#if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
-METHODDEF(boolean)
-#else
-METHODDEF boolean
-#endif
-our_fill_input_buffer (j_decompress_ptr cinfo) {
-  /* Insert a fake EOI marker */
-  struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
-  static JOCTET buffer[2];
-
-  buffer[0] = (JOCTET) 0xFF;
-  buffer[1] = (JOCTET) JPEG_EOI;
-
-  src->next_input_byte = buffer;
-  src->bytes_in_buffer = 2;
-  return TRUE;
-}
-
-#if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
-METHODDEF(void)
-#else
-METHODDEF void
-#endif
-our_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
-  struct jpeg_source_mgr *src = NULL;
-
-  src = (struct jpeg_source_mgr *) cinfo->src;
-
-  if (!src) {
-    return;
-  } else if (num_bytes > src->bytes_in_buffer) {
-    ERREXIT(cinfo, JERR_INPUT_EOF);
-    /*NOTREACHED*/
-  }
-
-  src->bytes_in_buffer -= num_bytes;
-  src->next_input_byte += num_bytes;
-}
-
-#if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
-METHODDEF(void)
-#else
-METHODDEF void
-#endif
-our_term_source (j_decompress_ptr cinfo) {
-}
-
-typedef struct {
-  struct jpeg_source_mgr pub;
-} our_jpeg_source_mgr;
-
-static void
-jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, unsigned int len)
-{
-  struct jpeg_source_mgr *src = NULL;
-
-  if (cinfo->src == NULL) {	/* first time for this JPEG object? */
-    cinfo->src = (struct jpeg_source_mgr *)
-      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
-				  sizeof(our_jpeg_source_mgr));
-    src = (struct jpeg_source_mgr *) cinfo->src;
-    src->next_input_byte = data;
-  }
-  src = (struct jpeg_source_mgr *) cinfo->src;
-  src->init_source = our_init_source;
-  src->fill_input_buffer = our_fill_input_buffer;
-  src->skip_input_data = our_skip_input_data;
-  src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
-  src->term_source = our_term_source;
-  src->bytes_in_buffer = len;
-  src->next_input_byte = data;
-}
-
-#if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
-METHODDEF(void)
-#else
-METHODDEF void
-#endif
-my_jpeg_error_exit (j_common_ptr cinfo)
-{
-  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
-  struct my_jpeg_error_mgr *myerr = (struct my_jpeg_error_mgr *) cinfo->err;
-
-  /* Return control to the setjmp point */
-  longjmp (myerr->setjmp_buffer, 1);
-}
-
-/* The code in this routine is based on example.c from the JPEG library
-   source code and from gif_instantiate() */
-static void
-jpeg_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
-		  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
-		  int dest_mask, Lisp_Object domain)
-{
-  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-  Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
-  Display *dpy;
-  Screen *scr;
-  /* It is OK for the unwind data to be local to this function,
-     because the unwind-protect is always executed when this
-     stack frame is still valid. */
-  struct jpeg_unwind_data unwind;
-  int speccount = specpdl_depth ();
-
-  /* This struct contains the JPEG decompression parameters and pointers to
-   * working space (which is allocated as needed by the JPEG library).
-   */
-  struct jpeg_decompress_struct cinfo;
-  /* We use our private extension JPEG error handler.
-   * Note that this struct must live as long as the main JPEG parameter
-   * struct, to avoid dangling-pointer problems.
-   */
-  struct my_jpeg_error_mgr jerr;
-
-  if (!DEVICE_X_P (XDEVICE (device)))
-    signal_simple_error ("Not an X device", device);
-
-  dpy = DEVICE_X_DISPLAY (XDEVICE (device));
-  scr = DefaultScreenOfDisplay (dpy);
-
-  /* Step -1: First record our unwind-protect, which will clean up after
-     any exit, normal or not */
-
-  memset (&unwind, 0, sizeof (unwind));
-  unwind.dpy = dpy;
-  record_unwind_protect (jpeg_instantiate_unwind, make_opaque_ptr (&unwind));
-
-#ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES
-  /* Step 0: Write out to a temp file.
-
-     The JPEG routines require you to read from a file unless
-     you provide your own special input handlers, which I don't
-     feel like doing. */
-  {
-    Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
-
-    assert (!NILP (data));
-
-    write_lisp_string_to_temp_file (data, unwind.tempfile);
-    unwind.tempfile_needs_to_be_removed = 1;
-
-    /* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
-     * requires it in order to read binary files.
-     */
-
-    if ((unwind.instream = fopen (unwind.tempfile, "r")) == NULL)
-      report_file_error ("Opening JPEG temp file",
-			 list1 (build_string (unwind.tempfile)));
-  }
-#endif
-
-  /* Step 1: allocate and initialize JPEG decompression object */
-
-  /* We set up the normal JPEG error routines, then override error_exit. */
-  cinfo.err = jpeg_std_error (&jerr.pub);
-  jerr.pub.error_exit = my_jpeg_error_exit;
-
-  /* Establish the setjmp return context for my_error_exit to use. */
-  if (setjmp (jerr.setjmp_buffer))
-    {
-      /* If we get here, the JPEG code has signaled an error.
-       * We need to clean up the JPEG object, close the input file, and return.
-       */
-
-      {
-	Lisp_Object errstring;
-	char buffer[JMSG_LENGTH_MAX];
-
-	/* Create the message */
-	(*cinfo.err->format_message) ((j_common_ptr) &cinfo, buffer);
-	errstring = build_string (buffer);
-
-	signal_simple_error_2 ("JPEG decoding error",
-			       errstring, instantiator);
-      }
-    }
-
-  /* Now we can initialize the JPEG decompression object. */
-  jpeg_create_decompress (&cinfo);
-  unwind.cinfo_ptr = &cinfo;
-
-  /* Step 2: specify data source (eg, a file) */
-
-#ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES
-  jpeg_stdio_src (&cinfo, unwind.instream);
-#else
-  {
-    Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
-    Extbyte *bytes;
-    Extcount len;
-
-    /* #### This is a definite problem under Mule due to the amount of
-       stack data it might allocate.  Need to be able to convert and
-       write out to a file. */
-    GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
-    jpeg_memory_src (&cinfo, bytes, len);
-  }
-#endif
-
-  /* Step 3: read file parameters with jpeg_read_header() */
-
-  jpeg_read_header (&cinfo, TRUE);
-  /* We can ignore the return value from jpeg_read_header since
-   *   (a) suspension is not possible with the stdio data source, and
-   *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
-   * See libjpeg.doc for more info.
-   */
-
-  /* Step 4: set parameters for decompression.   */
-
-  /* We request that the JPEG file be automatically quantized into
-     8-bit color in case it's not already (many JPEGs are stored in
-     24-bit color).  "Two-pass quantize" means that the colormap
-     is determined on-the-fly for this particular image rather than
-     quantizing to a supplied colormap.  We can get away with this
-     because we then use allocate_nearest_color().
-
-     #### Note of course that this is not the most color-effective
-     way of doing things -- we could quantize an image that has
-     lots of very similar colors, and eat up the colormap with these
-     (useless to other images) colors.  Unfortunately I don't think
-     there's any "general" way of maximizing the overall image
-     quality of lots of images, given that we don't know the
-     colors of the images until we come across each one.  Best we
-     could do would be various sorts of heuristics, which I don't
-     feel like dealing with now.  A better scheme would be the
-     way things are done under MS Windows, where the colormap is
-     dynamically adjusted for various applications; but that kind
-     of thing would have to be provided by X, which it isn't. */
-
-  cinfo.quantize_colors = TRUE;
-  cinfo.two_pass_quantize = TRUE;
-  cinfo.colormap = NULL;
-
-  /* Step 5: Start decompressor */
-
-  jpeg_start_decompress (&cinfo);
-  /* We can ignore the return value since suspension is not possible
-   * with the stdio data source.
-   */
-
-  /* At this point we know the size of the image and the colormap. */
-
-  /* Step 5.33: Allocate the colors */
-  {
-    int i;
-
-    /* Just in case the image contains out-of-range pixels, we go
-       ahead and allocate space for all of them. */
-    unwind.pixels = xnew_array (unsigned long, 256);
-    unwind.npixels = cinfo.actual_number_of_colors;
-
-    for (i = 0; i < 256; i++)
-      unwind.pixels[i] = 0;   /* Use a reasonable color for out of range. */
-
-    /* Allocate pixels for the various colors. */
-    for (i = 0; i < unwind.npixels; i++)
-      {
-	XColor color;
-	int ri, gi, bi;
-
-	ri = 0;
-	gi = cinfo.out_color_components > 1 ? 1 : 0;
-	bi = cinfo.out_color_components > 2 ? 2 : 0;
-
-	/* Ok... apparently, an entry of cinfo.colormap can be NULL if
-	   there are no bits of that color in the image.  How incredibly
-	   gross.  Wouldn't it be nice to have exceptions!? */
-	color.red = cinfo.colormap[ri] ? cinfo.colormap[ri][i] << 8 : 0;
-	color.green = cinfo.colormap[gi] ? cinfo.colormap[gi][i] << 8 : 0;
-	color.blue = cinfo.colormap[bi] ? cinfo.colormap[bi][i] << 8 : 0;
-	color.flags = DoRed | DoGreen | DoBlue;
-
-	allocate_nearest_color (dpy, DefaultColormapOfScreen (scr), &color);
-	unwind.pixels[i] = color.pixel;
-      }
-  }
-
-  /* Step 5.66: Create the image */
-  {
-    int height = cinfo.output_height;
-    int width = cinfo.output_width;
-    int depth;
-    int bitmap_pad;
-
-    depth = DefaultDepthOfScreen (scr);
-
-    /* first get bitmap_pad (from XPM) */
-    bitmap_pad = ((depth > 16) ? 32 :
-		  (depth >  8) ? 16 :
-		  8);
-
-    unwind.ximage = XCreateImage (dpy, DefaultVisualOfScreen (scr),
-				  depth, ZPixmap, 0, 0, width, height,
-				  bitmap_pad, 0);
-
-    if (!unwind.ximage)
-      signal_simple_error ("Unable to create X image struct", instantiator);
-
-    /* now that bytes_per_line must have been set properly alloc data */
-    unwind.ximage->data =
-      (char *) xmalloc (unwind.ximage->bytes_per_line * height);
-  }
-
-  /* Step 6: Read in the data and put into image */
-  {
-    JSAMPARRAY row_buffer;	/* Output row buffer */
-    int row_stride;		/* physical row width in output buffer */
-
-    /* We may need to do some setup of our own at this point before reading
-     * the data.  After jpeg_start_decompress() we have the correct scaled
-     * output image dimensions available, as well as the output colormap
-     * if we asked for color quantization.
-     * In this example, we need to make an output work buffer of the right size.
-     */
-    /* JSAMPLEs per row in output buffer.
-       Since we asked for quantized output, cinfo.output_components
-       will always be 1. */
-    row_stride = cinfo.output_width * cinfo.output_components;
-    /* Make a one-row-high sample array that will go away when done
-       with image */
-    row_buffer = ((*cinfo.mem->alloc_sarray)
-		  ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1));
-
-    /* Here we use the library's state variable cinfo.output_scanline as the
-     * loop counter, so that we don't have to keep track ourselves.
-     */
-    while (cinfo.output_scanline < cinfo.output_height)
-      {
-	int i;
-	int scanline = cinfo.output_scanline;
-
-	/* jpeg_read_scanlines expects an array of pointers to scanlines.
-	 * Here the array is only one element long, but you could ask for
-	 * more than one scanline at a time if that's more convenient.
-	 */
-	(void) jpeg_read_scanlines (&cinfo, row_buffer, 1);
-
-	for (i = 0; i < cinfo.output_width; i++)
-	  XPutPixel (unwind.ximage, i, scanline,
-		     /* Let's make sure we avoid getting bit like
-			what happened for GIF's.  It's probably the
-			case that JSAMPLE's are unsigned chars as
-			opposed to chars, but you never know.
-
-			(They could even be shorts if the library
-			was compiled with 12-bit samples -- ####
-			We should deal with this possibility) */
-		     unwind.pixels[(unsigned char) row_buffer[0][i]]);
-      }
-  }
-
-  /* Step 6.5: Create the pixmap and set up the image instance */
-  init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
-				    unwind.pixels, unwind.npixels,
-				    instantiator);
-
-  /* Step 7: Finish decompression */
-
-  jpeg_finish_decompress (&cinfo);
-  /* We can ignore the return value since suspension is not possible
-   * with the stdio data source.
-   */
-
-  /* And we're done!
-
-     Now that we've succeeded, we don't want the pixels
-     freed right now.  They're kept around in the image instance
-     structure until it's destroyed. */
-  unwind.npixels = 0;
-
-  /* This will clean up everything else. */
-  unbind_to (speccount, Qnil);
-}
-
-#endif /* HAVE_JPEG */
-
-
-#ifdef HAVE_GIF
-
-/**********************************************************************
- *                               GIF                                  *
- **********************************************************************/
-
-#include "gif_lib.h" /* This is in our own source tree */
-
-static void
-gif_validate (Lisp_Object instantiator)
-{
-  file_or_data_must_be_present (instantiator);
-}
-
-static Lisp_Object
-gif_normalize (Lisp_Object inst, Lisp_Object console_type)
-{
-  return simple_image_type_normalize (inst, console_type, Qgif);
-}
-
-static int
-gif_possible_dest_types (void)
-{
-  return IMAGE_COLOR_PIXMAP_MASK;
-}
-
-/* To survive the otherwise baffling complexity of making sure
-   everything gets cleaned up in the presence of an error, we
-   use an unwind_protect(). */
-
-struct gif_unwind_data
-{
-  Display *dpy;
-  /* Object that holds the decoded data from a GIF file */
-  GifFileType *giffile;
-  /* Pixels to keep around while the image is active */
-  unsigned long *pixels;
-  int npixels;
-  /* Client-side image structure */
-  XImage *ximage;
-  /* Tempfile to remove */
-  char tempfile[50];
-  int tempfile_needs_to_be_removed;
-};
-
-static Lisp_Object
-gif_instantiate_unwind (Lisp_Object unwind_obj)
-{
-  struct gif_unwind_data *data =
-    (struct gif_unwind_data *) get_opaque_ptr (unwind_obj);
-
-  free_opaque_ptr (unwind_obj);
-  if (data->giffile)
-    DGifCloseFile (data->giffile);
-  if (data->tempfile_needs_to_be_removed)
-    unlink (data->tempfile);
-  if (data->npixels > 0)
-    {
-      Screen *scr = DefaultScreenOfDisplay (data->dpy);
-      Colormap cmap = DefaultColormapOfScreen (scr);
-      XFreeColors (data->dpy, cmap, data->pixels, data->npixels, 0L);
-      xfree (data->pixels);
-    }
-  if (data->ximage)
-    {
-      if (data->ximage->data)
-        {
-	  xfree (data->ximage->data);
-          data->ximage->data = 0;
-        }
-      XDestroyImage (data->ximage);
-    }
-
-  return Qnil;
-}
-
-#if 0
-/* We provide our own version of DGifSlurp() because the standardly
-   provided one doesn't handle interlaced GIFs.  This is based on
-   code in gif2x11.c. */
-
-/* Return value is GIF_ERROR, GIF_OK, or -1.
-   #### We are using "forbidden" knowledge that neither of these
-   constants is -1. */
-
-static int
-our_own_dgif_slurp_from_gif2x11_c (GifFileType *GifFile)
-{
-  int i, j, Row, Col, Width, Height;
-  int ExtCode, Count;
-  GifRecordType RecordType;
-  GifByteType *Extension;
-  SavedImage *sp = NULL;
-  static int InterlacedOffset[] = { 0, 4, 2, 1 };
-  static int InterlacedJumps[] = { 8, 8, 4, 2 };
-
-  GifPixelType *ScreenBuffer =
-    (GifPixelType *) xmalloc (GifFile->SHeight * GifFile->SWidth *
-			      sizeof (GifPixelType));
-  GifFile->SavedImages = xnew (SavedImage);
-
-  for (i = 0; i < GifFile->SHeight * GifFile->SWidth; i++)
-    ScreenBuffer[i] = GifFile->SBackGroundColor;
-
-  /* Scan the content of the GIF file and load the image(s) in: */
-  do
-    {
-      if (DGifGetRecordType (GifFile, &RecordType) == GIF_ERROR)
-	return GIF_ERROR;
-
-      switch (RecordType)
-	{
-	case IMAGE_DESC_RECORD_TYPE:
-	  if (DGifGetImageDesc (GifFile) == GIF_ERROR)
-	    return GIF_ERROR;
-
-	  sp = &GifFile->SavedImages[GifFile->ImageCount-1];
-	  Row = GifFile->Image.Top; /* Image Position relative to Screen. */
-	  Col = GifFile->Image.Left;
-	  Width = GifFile->Image.Width;
-	  Height = GifFile->Image.Height;
-	  if (GifFile->Image.Left + GifFile->Image.Width > GifFile->SWidth ||
-	      GifFile->Image.Top + GifFile->Image.Height > GifFile->SHeight)
-	    return -1;
-
-	  sp->RasterBits = (GifPixelType*) xmalloc(Width * Height *
-						   sizeof (GifPixelType));
-
-	  if (GifFile->Image.Interlace)
-	    {
-	      /* Need to perform 4 passes on the images: */
-	      for (Count = i = 0; i < 4; i++)
-		for (j = Row + InterlacedOffset[i]; j < Row + Height;
-		     j += InterlacedJumps[i])
-		  {
-		    if (DGifGetLine (GifFile, &sp->RasterBits[j * Width + Col],
-				     Width) == GIF_ERROR)
-		      return GIF_ERROR;
-		  }
-	    }
-	  else
-	    {
-	      for (i = 0; i < Height; i++)
-		{
-		  if (DGifGetLine (GifFile,
-				   &sp->RasterBits[(Row++) * Width + Col],
-				   Width) == GIF_ERROR)
-		    return GIF_ERROR;
-		}
-	    }
-
-	  /* Only get 1 image from animated gifs. */
-	  /* #### if the rest of the file was bad, we still return
-	     GIF_OK, since we don't even bother looking at it.  Should
-	     probably check for ImageCount == 1 above too, hmm. */
-	  goto done;
-	  break;
-
-	case EXTENSION_RECORD_TYPE:
-	  /* Skip any extension blocks in file: */
-	  if (DGifGetExtension (GifFile, &ExtCode, &Extension) == GIF_ERROR)
-	    return GIF_ERROR;
-
-	  while (Extension != NULL)
-	    {
-	      if (DGifGetExtensionNext (GifFile, &Extension) == GIF_ERROR)
-		return GIF_ERROR;
-	    }
-	  break;
-
-	case TERMINATE_RECORD_TYPE:
-	  break;
-
-	default:		    /* Should be traps by DGifGetRecordType. */
-	  break;
-	}
-    }
-  while (RecordType != TERMINATE_RECORD_TYPE);
-
- done:
-
-  return GIF_OK;
-}
-#endif
-
-static void
-gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
-		 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
-		 int dest_mask, Lisp_Object domain)
-{
-  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-  Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
-  Display *dpy;
-  Screen *scr;
-  /* It is OK for the unwind data to be local to this function,
-     because the unwind-protect is always executed when this
-     stack frame is still valid. */
-  struct gif_unwind_data unwind;
-  int speccount = specpdl_depth ();
-
-  if (!DEVICE_X_P (XDEVICE (device)))
-    signal_simple_error ("Not an X device", device);
-
-  dpy = DEVICE_X_DISPLAY (XDEVICE (device));
-  scr = DefaultScreenOfDisplay (dpy);
-
-  memset (&unwind, 0, sizeof (unwind));
-  unwind.dpy = dpy;
-  record_unwind_protect (gif_instantiate_unwind, make_opaque_ptr (&unwind));
-
-  /* 1. Now decode the data. */
-
-  /* #### The GIF routines currently require that you read from a file,
-     so write out to a temp file.  We should change this. */
-  {
-    Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
-
-    assert (!NILP (data));
-
-    write_lisp_string_to_temp_file (data, unwind.tempfile);
-    unwind.tempfile_needs_to_be_removed = 1;
-
-    /* Then slurp the image into memory, decoding along the way.
-       The result is the image in a simple one-byte-per-pixel
-       format (#### the GIF routines only support 8-bit GIFs,
-       it appears). */
-    unwind.giffile = DGifOpenFileName (unwind.tempfile);
-    if (unwind.giffile == NULL)
-      {
-      gif_decode_error:
-	signal_simple_error ("Unable to decode GIF",
-			     build_string (EmacsPrintGifError ()));
-      }
-#if 0
-    if (our_own_dgif_slurp_from_gif2x11_c(unwind.giffile) != GIF_OK)
-#else
-    /* DGifSlurp() doesn't handle interlaced files. */
-    /* Actually, it does, sort of.  It just sets the Interlace flag
-       and stores RasterBits in interlaced order.  We handle that below. */
-    if (DGifSlurp (unwind.giffile) != GIF_OK)
-#endif
-      goto gif_decode_error;
-  }
-
-  /* 2. Now allocate the colors for the image. */
-  {
-    int i;
-    ColorMapObject *cmap = unwind.giffile->SColorMap;
-    /* Just in case the image contains out-of-range pixels, we go
-       ahead and allocate space for all of them. */
-    unwind.pixels = xnew_array (unsigned long, 256);
-    unwind.npixels = cmap->ColorCount;
-
-    for (i = 0; i < 256; i++)
-      unwind.pixels[i] = 0;   /* Use a reasonable color for out of range. */
-
-    /* Allocate pixels for the various colors. */
-    for (i = 0; i < cmap->ColorCount; i++)
-      {
-	XColor color;
-
-	color.red = cmap->Colors[i].Red << 8;
-	color.green = cmap->Colors[i].Green << 8;
-	color.blue = cmap->Colors[i].Blue << 8;
-	color.flags = DoRed | DoGreen | DoBlue;
-
-	allocate_nearest_color (dpy, DefaultColormapOfScreen (scr), &color);
-	unwind.pixels[i] = color.pixel;
-      }
-  }
-
-  /* 3. Now create the image */
-  {
-    int height = unwind.giffile->SHeight;
-    int width = unwind.giffile->SWidth;
-    int depth;
-    int bitmap_pad;
-    int i, j, row, pass, interlace;
-    /* interlaced gifs have rows in this order:
-       0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ...  */
-    static int InterlacedOffset[] = { 0, 4, 2, 1 };
-    static int InterlacedJumps[] = { 8, 8, 4, 2 };
-
-
-    depth = DefaultDepthOfScreen (scr);
-
-    /* first get bitmap_pad (from XPM) */
-    bitmap_pad = ((depth > 16) ? 32 :
-		  (depth >  8) ? 16 :
-		  8);
-
-    unwind.ximage = XCreateImage (dpy, DefaultVisualOfScreen (scr),
-				  depth, ZPixmap, 0, 0, width, height,
-				  bitmap_pad, 0);
-
-    if (!unwind.ximage)
-      signal_simple_error ("Unable to create X image struct", instantiator);
-
-    /* now that bytes_per_line must have been set properly alloc data */
-    unwind.ximage->data =
-      (char *) xmalloc (unwind.ximage->bytes_per_line * height);
-
-    /* write the data --
-       #### XPutPixel() is a client-side-only function but could
-       still be slow.  Another possibility is to just convert to
-       XPM format and use the Xpm routines, which optimize this
-       stuff; but it's doubtful that this will be faster in the
-       long run, what with all the XPM overhead.  If this proves
-       to be a bottleneck here, maybe we should just copy the
-       optimization routines from XPM (they're in turn mostly
-       copied from the Xlib source code). */
-
-    /* Note: We just use the first image in the file and ignore the rest.
-             We check here that that image covers the full "screen" size.
-	     I don't know whether that's always the case.
-             -dkindred@cs.cmu.edu  */
-    if (unwind.giffile->SavedImages[0].ImageDesc.Height != height
-	|| unwind.giffile->SavedImages[0].ImageDesc.Width != width
-	|| unwind.giffile->SavedImages[0].ImageDesc.Left != 0
-	|| unwind.giffile->SavedImages[0].ImageDesc.Top != 0)
-      signal_simple_error ("First image in GIF file is not full size",
-			   instantiator);
-
-    interlace = unwind.giffile->SavedImages[0].ImageDesc.Interlace;
-    pass = 0;
-    row = interlace ? InterlacedOffset[pass] : 0;
-    for (i = 0; i < height; i++)
-      {
-	if (interlace && row >= height)
-	  row = InterlacedOffset[++pass];
-
-	for (j = 0; j < width; j++)
-	  XPutPixel (unwind.ximage, j, row,
-		     unwind.pixels[(unsigned char)
-				  /* incorrect signed declaration
-				     of RasterBits[] */
-				  (unwind.giffile->SavedImages[0].
-				   RasterBits[i * width + j])]);
-
-	row += interlace ? InterlacedJumps[pass] : 1;
-      }
-  }
-
-  /* 4. Now create the pixmap and set up the image instance */
-  init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
-				    unwind.pixels, unwind.npixels,
-				    instantiator);
-  /* Now that we've succeeded, we don't want the pixels
-     freed right now.  They're kept around in the image instance
-     structure until it's destroyed. */
-  unwind.npixels = 0;
-  unbind_to (speccount, Qnil);
-}
-
-#endif /* HAVE_GIF */
-
-
-#ifdef HAVE_PNG
-
-/**********************************************************************
- *                             PNG                                    *
- **********************************************************************/
-static void
-png_validate (Lisp_Object instantiator)
-{
-  file_or_data_must_be_present (instantiator);
-}
-
-static Lisp_Object
-png_normalize (Lisp_Object inst, Lisp_Object console_type)
-{
-  return simple_image_type_normalize (inst, console_type, Qpng);
-}
-
-static int
-png_possible_dest_types (void)
-{
-  return IMAGE_COLOR_PIXMAP_MASK;
-}
-
-#if !defined (USE_TEMP_FILES_FOR_PNG_IMAGES) && (PNG_LIBPNG_VER >= 87)
-struct png_memory_storage
-{
-  Extbyte *bytes;		/* The data       */
-  Extcount len;			/* How big is it? */
-  int index;			/* Where are we?  */
-};
-
-static void png_read_from_memory(png_structp png_ptr, png_bytep data,
-				 png_uint_32 length)
-{
-   struct png_memory_storage *tbr =
-     (struct png_memory_storage *) png_get_io_ptr (png_ptr);
-
-   if (length > (tbr->len - tbr->index))
-     png_error (png_ptr, (png_const_charp) "Read Error");
-   memcpy(data,tbr->bytes + tbr->index,length);
-   tbr->index = tbr->index + length;
-}
-#endif /* !USE_TEMP_FILES_FOR_PNG_IMAGESS || PNG_LIBPNG_VER >= 87 */
-
-struct png_unwind_data
-{
-  Display *dpy;
-  FILE *instream;
-  png_struct *png_ptr;
-  png_info *info_ptr;
-  unsigned long *pixels;
-  int npixels;
-  XImage *ximage;
-  char tempfile[50];
-  int tempfile_needs_to_be_removed;
-};
-
-static Lisp_Object
-png_instantiate_unwind (Lisp_Object unwind_obj)
-{
-  struct png_unwind_data *data =
-    (struct png_unwind_data *) get_opaque_ptr (unwind_obj);
-
-  free_opaque_ptr (unwind_obj);
-  if (data->png_ptr)
-    png_read_destroy (data->png_ptr, data->info_ptr, (png_info *) NULL);
-  if (data->instream)
-    fclose (data->instream);
-  if (data->tempfile_needs_to_be_removed)
-    unlink (data->tempfile);
-  if (data->npixels > 0)
-    {
-      Screen *scr = DefaultScreenOfDisplay (data->dpy);
-      Colormap cmap = DefaultColormapOfScreen (scr);
-      XFreeColors (data->dpy, cmap, data->pixels, data->npixels, 0L);
-      xfree (data->pixels);
-    }
-
-  if (data->ximage)
-    {
-      if (data->ximage->data)
-	{
-	  xfree (data->ximage->data);
-	  data->ximage->data = 0;
-	}
-      XDestroyImage (data->ximage);
-    }
-
-  return Qnil;
-}
-
-/* This doesn't appear to be used. */
-#if 0
-#define get_png_val(p) _get_png_val (&(p), info_ptr.bit_depth)
-png_uint_16
-_get_png_val (png_byte **pp, int bit_depth)
-{
-  png_uint_16 c = 0;
-
-  if (bit_depth == 16) {
-    c = (*((*pp)++)) << 8;
-  }
-  c |= (*((*pp)++));
-
-  return c;
-}
-#endif
-
-static void
-png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
-		 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
-		 int dest_mask, Lisp_Object domain)
-{
-  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-  Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
-  Display *dpy;
-  Screen *scr;
-  struct png_unwind_data unwind;
-  int speccount = specpdl_depth ();
-
-  /* PNG variables */
-  png_struct *png_ptr;
-  png_info *info_ptr;
-
-  if (!DEVICE_X_P (XDEVICE (device)))
-    signal_simple_error ("Not an X device", device);
-
-  dpy = DEVICE_X_DISPLAY (XDEVICE (device));
-  scr = DefaultScreenOfDisplay (dpy);
-
-  png_ptr  = xnew (png_struct);
-  info_ptr = xnew (png_info);
-
-  memset (&unwind, 0, sizeof (unwind));
-  unwind.png_ptr = png_ptr;
-  unwind.info_ptr = info_ptr;
-  unwind.dpy = dpy;
-
-  record_unwind_protect (png_instantiate_unwind, make_opaque_ptr (&unwind));
-
-  /* This code is a mixture of stuff from Ben's GIF/JPEG stuff from
-     this file, example.c from the libpng 0.81 distribution, and the
-     pngtopnm sources. -WMP-
-     */
-#if defined (USE_TEMP_FILES_FOR_PNG_IMAGES) || (PNG_LIBPNG_VER < 87)
-  /* Write out to a temp file - we really should take the time to
-     write appropriate memory bound IO stuff, but I am just trying
-     to get the stupid thing working right now.
-     */
-  {
-    Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
-
-    assert (!NILP (data));
-
-    write_lisp_string_to_temp_file (data, unwind.tempfile);
-    unwind.tempfile_needs_to_be_removed = 1;
-
-    if ((unwind.instream = fopen (unwind.tempfile, "rb")) == NULL)
-      report_file_error ("Opening PNG temp file",
-			 list1 (build_string (unwind.tempfile)));
-  }
-#else
-  /* Nothing */
-#endif
-
-  /* Set the jmp_buf reurn context for png_error ... if this returns !0, then
-     we ran into a problem somewhere, and need to clean up after ourselves. */
-  if (setjmp (png_ptr->jmpbuf))
-    {
-      /* Am I doing enough here?  I think so, since most things happen
-         in png_unwind */
-      png_read_destroy (png_ptr, info_ptr, (png_info *) NULL);
-      signal_simple_error ("Error decoding PNG", instantiator);
-    }
-
-  /* Initialize all PNG structures */
-  png_info_init (info_ptr);
-  png_read_init (png_ptr);
-
-  /* Initialize the IO layer and read in header information */
-#if defined (USE_TEMP_FILES_FOR_PNG_IMAGES) || (PNG_LIBPNG_VER < 87)
-  png_init_io (png_ptr, unwind.instream);
-#else
-  {
-    Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
-    Extbyte *bytes;
-    Extcount len;
-    struct png_memory_storage tbr; /* Data to be read */
-
-    assert (!NILP (data));
-
-    /* #### This is a definite problem under Mule due to the amount of
-       stack data it might allocate.  Need to be able to convert and
-       write out to a file. */
-    GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
-    tbr.bytes = bytes;
-    tbr.len = len;
-    tbr.index = 0;
-    png_set_read_fn(png_ptr,(void *) &tbr, png_read_from_memory);
-  }
-#endif
-
-  png_read_info (png_ptr, info_ptr);
-
-  /* set up the transformations you want.  Note that these are
-     all optional.  Only call them if you want them */
-  /* tell libpng to strip 16 bit depth files down to 8 bits */
-  if (info_ptr->bit_depth == 16)
-    png_set_strip_16 (png_ptr);
-  if (info_ptr->bit_depth < 8)
-    png_set_packing (png_ptr);
-  /* ##### Perhaps some way to specify the screen gamma should be in here? */
-
-  {
-    int height = info_ptr->height;
-    int width = info_ptr->width;
-    int depth = info_ptr->bit_depth;
-    int linesize = max (info_ptr->bit_depth >> 3, 1) * width;
-    int bitmap_pad;
-    int y;
-    XColor color;
-    png_byte *png_pixels;
-    png_byte **row_pointers;
-    png_color static_color_cube[216];
-
-    /* Wow, allocate all the memory.  Truly, exciting. */
-    unwind.pixels = xnew_array (unsigned long, 256);
-    png_pixels    = xnew_array (png_byte, linesize * height);
-    row_pointers  = xnew_array (png_byte *, height);
-
-    for (y = 0; y < 256; y++)
-      unwind.pixels[y] = 0;
-    for (y = 0; y < height; y++)
-      row_pointers[y] = png_pixels + (linesize * y);
-
-    /*  #### This is where we should handle transparency, but I am unsure of
-	how exactly to get that information right now, in a safe manner. */
-#if 0
-    {
-      png_color_16 current_background;
-
-      /* Some appropriate magic should go here to get the current
-	 buffers (device?)  background color and convert it to a
-	 png_color_16 struct */
-      if (info_ptr->valid & PNG_INFO_bKGD)
-	png_set_background (png_ptr, &(info_ptr->background), PNG_GAMMA_FILE,
-			    1, 1.0);
-      else
-	png_set_background (png_ptr, &current_background, PNG_GAMMA_SCREEN,
-			    0, 1.0);
-    }
-#endif
-
-    if ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
-	(info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA))
-      {
-	if (!(info_ptr->valid & PNG_INFO_PLTE))
-	  {
-	    for (y = 0; y < 216; y++)
-	      {
-		static_color_cube[y].red = (y % 6) * 255.0 / 5;
-		static_color_cube[y].green = ((y / 6) % 6) * 255.0 / 5;
-		static_color_cube[y].blue = (y / 36) * 255.0 / 5;
-	      }
-	    png_set_dither (png_ptr, static_color_cube, 216, 216, NULL, 1);
-	  }
-	else
-	  {
-	    png_set_dither (png_ptr, info_ptr->palette, info_ptr->num_palette,
-			    info_ptr->num_palette, info_ptr->hist, 1);
-	  }
-      }
-
-    png_read_image (png_ptr, row_pointers);
-    png_read_end (png_ptr, info_ptr);
-
-    /* Ok, now we go and allocate all the colors */
-    if (info_ptr->valid & PNG_INFO_PLTE)
-      {
-	unwind.npixels = info_ptr->num_palette;
-	for (y = 0; y < unwind.npixels; y++)
-	  {
-	    color.red = info_ptr->palette[y].red << 8;
-	    color.green = info_ptr->palette[y].green << 8;
-	    color.blue = info_ptr->palette[y].blue << 8;
-	    color.flags = DoRed | DoGreen | DoBlue;
-	    allocate_nearest_color (dpy, DefaultColormapOfScreen (scr),
-				    &color);
-	    unwind.pixels[y] = color.pixel;
-	  }
-      }
-    else
-      {
-	unwind.npixels = 216;
-	for (y = 0; y < 216; y++)
-	  {
-	    color.red = static_color_cube[y].red << 8;
-	    color.green = static_color_cube[y].green << 8;
-	    color.blue = static_color_cube[y].blue << 8;
-	    color.flags = DoRed|DoGreen|DoBlue;
-	    allocate_nearest_color (dpy, DefaultColormapOfScreen (scr),
-				    &color);
-	    unwind.pixels[y] = color.pixel;
-	  }
-      }
-
-#ifdef PNG_SHOW_COMMENTS
-    /* ####
-     * I turn this off by default now, because the !%^@#!% comments
-     * show up every time the image is instantiated, which can get
-     * really really annoying.  There should be some way to pass this
-     * type of data down into the glyph code, where you can get to it
-     * from lisp anyway. - WMP
-     */
-    {
-      int i;
-
-      for (i = 0 ; i < info_ptr->num_text ; i++)
-	{
-	  /* How paranoid do I have to be about no trailing NULLs, and
-	     using (int)info_ptr->text[i].text_length, and strncpy and a temp
-	     string somewhere? */
-
-	  warn_when_safe (Qpng, Qinfo, "%s - %s",
-			  info_ptr->text[i].key,
-			  info_ptr->text[i].text);
-	}
-    }
-#endif
-
-    /* Now create the image */
-
-    depth = DefaultDepthOfScreen (scr);
-
-    /* first get bitmap_pad (from XPM) */
-    bitmap_pad = ((depth > 16) ? 32 :
-		  (depth >  8) ? 16 :
-		  8);
-
-    unwind.ximage = XCreateImage (dpy, DefaultVisualOfScreen (scr),
-				  depth, ZPixmap, 0, 0, width, height,
-				  bitmap_pad, 0);
-
-    if (!unwind.ximage)
-      signal_simple_error ("Unable to create X image struct",
-			   instantiator);
-
-    /* now that bytes_per_line must have been set properly alloc data */
-    unwind.ximage->data = (char *) xmalloc (unwind.ximage->bytes_per_line *
-					    height);
-
-    {
-      int i, j;
-      for (i = 0; i < height; i++)
-	for (j = 0; j < width; j++)
-	  XPutPixel (unwind.ximage, j, i,
-		     unwind.pixels[png_pixels[i * width + j]]);
-    }
-
-    xfree (row_pointers);
-    xfree (png_pixels);
-  }
-
-  init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
-				    unwind.pixels, unwind.npixels,
-				    instantiator);
-
-  /* This will clean up everything else. */
-  unwind.npixels = 0;
-  unbind_to (speccount, Qnil);
-}
-
-#endif /* HAVE_PNG */
-
-
-#ifdef HAVE_TIFF
-
-/**********************************************************************
- *                             TIFF                                   *
- **********************************************************************/
-static void
-tiff_validate (Lisp_Object instantiator)
-{
-  file_or_data_must_be_present (instantiator);
-}
-
-static Lisp_Object
-tiff_normalize (Lisp_Object inst, Lisp_Object console_type)
-{
-  signal_simple_error ("No TIFF support yet", inst);
-  return Qnil;
-}
-
-static int
-tiff_possible_dest_types (void)
-{
-  return IMAGE_COLOR_PIXMAP_MASK;
-}
-
-static void
-tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
-		  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
-		  int dest_mask, Lisp_Object domain)
-{
-  abort ();
-}
-
-#endif /* HAVE_TIFF */
-
-
 #ifdef HAVE_XPM
 
 /**********************************************************************
@@ -2968,6 +1671,162 @@
 #endif /* HAVE_XPM */
 
 
+#ifdef HAVE_IMAGEMAGICK
+/**********************************************************************
+ *                             ImageMagick                            *
+ **********************************************************************/
+static void
+imagick_validate (Lisp_Object instantiator)
+{
+	file_or_data_must_be_present (instantiator);
+}
+
+static Lisp_Object
+imagick_normalize (Lisp_Object inst, Lisp_Object console_type)
+{
+	return simple_image_type_normalize (inst, console_type, Qimagick);
+}
+
+static int
+imagick_possible_dest_types (void)
+{
+	return IMAGE_COLOR_PIXMAP_MASK;
+}
+
+struct imagick_unwind_data
+{
+	/* FIXME - what goes here...*/
+	Display *dpy;
+	FILE *instream;
+	Image *image;
+	XImage *ximage;
+	unsigned long *pixels;
+	unsigned long npixels;
+	char tempfile[50];
+	int tempfile_needs_to_be_removed;
+};
+
+static Lisp_Object
+imagick_instantiate_unwind (Lisp_Object unwind_obj)
+{
+	struct imagick_unwind_data *data =
+		(struct imagick_unwind_data *) get_opaque_ptr (unwind_obj);
+ 
+	free_opaque_ptr (unwind_obj);
+	if (data->instream)
+		fclose (data->instream);
+	if (data->tempfile_needs_to_be_removed)
+		unlink (data->tempfile);
+
+	if (data->image) {
+		DestroyImage(data->image);
+	}
+
+	if (data->ximage)
+	{
+		if (data->ximage->data)
+		{
+			xfree (data->ximage->data);
+			data->ximage->data = NULL;
+		}
+		XDestroyImage (data->ximage);
+	}
+ 
+	return Qnil;
+}
+
+static void XDitherImage(Image *image,XImage *ximage);
+
+static void
+imagick_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+					 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+					 int dest_mask, Lisp_Object domain)
+{
+	struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+	Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
+	Display *dpy;
+	Screen *scr;
+	Dimension depth;
+	struct imagick_unwind_data unwind;
+	int speccount = specpdl_depth ();
+	ImageInfo image_info;
+
+	/* ImageMagick variables */
+
+	/* Basic error checking */
+	if (!DEVICE_X_P (XDEVICE (device)))
+		signal_simple_error ("Not an X device", device);
+
+	dpy = DEVICE_X_DISPLAY (XDEVICE (device));
+	scr = DefaultScreenOfDisplay (dpy);
+	depth = DefaultDepthOfScreen (scr);
+	/* Set up the unwind */
+	memset (&unwind, 0, sizeof (unwind));
+	unwind.dpy = dpy;
+	record_unwind_protect(imagick_instantiate_unwind,make_opaque_ptr(&unwind));
+
+	/* Write out to a temp file - not sure if ImageMagick supports the
+	** notion of an abstrat 'data source' right now.
+	*/
+	{
+		Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
+
+		assert (!NILP (data));
+
+		write_lisp_string_to_temp_file (data, unwind.tempfile);
+		unwind.tempfile_needs_to_be_removed = 1;
+
+		if ((unwind.instream = fopen (unwind.tempfile, "rb")) == NULL)
+			report_file_error ("Opening ImageMagick temp file",
+							   list1 (build_string (unwind.tempfile)));
+	}
+
+	/* Initialize structures and read in the image */
+	GetImageInfo(&image_info);
+	strcpy(image_info.filename,unwind.tempfile);
+	unwind.image = ReadImage(&image_info);
+	if (unwind.image == (Image *) NULL) {
+		signal_simple_error ("Unable to read image.",instantiator);
+	}
+
+	unwind.ximage = XCreateImage(dpy, DefaultVisualOfScreen (scr),
+								 depth,
+								 (depth == 1) ? XYPixmap : ZPixmap,
+								 0, 0,
+								 unwind.image->columns,
+								 unwind.image->rows,
+								 XBitmapPad(dpy), 0);
+
+	if (!unwind.ximage) {
+		signal_simple_error("Unable to allocate XImage structure",
+							instantiator);
+	}
+
+	unwind.ximage->data = (char *) xmalloc(unwind.ximage->bytes_per_line *
+										   unwind.ximage->height *
+										   unwind.ximage->depth);
+
+	if (unwind.ximage->data == (char *)NULL) {
+		signal_simple_error("Unable to allocate pixel information",
+							instantiator);
+	}
+
+	/* Need to pull the data from the 'Image' structure in
+	** unwind.image and convert it to an 'XImage' in unwind.ximage
+	**
+	** FIXME IM FUCKED
+	**
+	** WMP 10/30/97
+	*/
+
+	init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
+									  unwind.pixels, unwind.npixels,
+									  instantiator);
+}
+
+#endif /* HAVE_IMAGEMAGICK */
+
+
 #ifdef HAVE_XFACE
 
 /**********************************************************************
@@ -3872,52 +2731,16 @@
   IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
   IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
 
-#ifdef HAVE_JPEG
-  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (jpeg, "jpeg");
-
-  IIFORMAT_HAS_METHOD (jpeg, validate);
-  IIFORMAT_HAS_METHOD (jpeg, normalize);
-  IIFORMAT_HAS_METHOD (jpeg, possible_dest_types);
-  IIFORMAT_HAS_METHOD (jpeg, instantiate);
-
-  IIFORMAT_VALID_KEYWORD (jpeg, Q_data, check_valid_string);
-  IIFORMAT_VALID_KEYWORD (jpeg, Q_file, check_valid_string);
-#endif
-
-#ifdef HAVE_GIF
-  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gif, "gif");
-
-  IIFORMAT_HAS_METHOD (gif, validate);
-  IIFORMAT_HAS_METHOD (gif, normalize);
-  IIFORMAT_HAS_METHOD (gif, possible_dest_types);
-  IIFORMAT_HAS_METHOD (gif, instantiate);
-
-  IIFORMAT_VALID_KEYWORD (gif, Q_data, check_valid_string);
-  IIFORMAT_VALID_KEYWORD (gif, Q_file, check_valid_string);
-#endif
-
-#ifdef HAVE_PNG
-  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (png, "png");
-
-  IIFORMAT_HAS_METHOD (png, validate);
-  IIFORMAT_HAS_METHOD (png, normalize);
-  IIFORMAT_HAS_METHOD (png, possible_dest_types);
-  IIFORMAT_HAS_METHOD (png, instantiate);
-
-  IIFORMAT_VALID_KEYWORD (png, Q_data, check_valid_string);
-  IIFORMAT_VALID_KEYWORD (png, Q_file, check_valid_string);
-#endif
-
-#ifdef HAVE_TIFF
-  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tiff, "tiff");
-
-  IIFORMAT_HAS_METHOD (tiff, validate);
-  IIFORMAT_HAS_METHOD (tiff, normalize);
-  IIFORMAT_HAS_METHOD (tiff, possible_dest_types);
-  IIFORMAT_HAS_METHOD (tiff, instantiate);
-
-  IIFORMAT_VALID_KEYWORD (tiff, Q_data, check_valid_string);
-  IIFORMAT_VALID_KEYWORD (tiff, Q_file, check_valid_string);
+#ifdef HAVE_IMAGEMAGICK
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (imagick, "imagick");
+
+  IIFORMAT_HAS_METHOD (imagick, validate);
+  IIFORMAT_HAS_METHOD (imagick, normalize);
+  IIFORMAT_HAS_METHOD (imagick, possible_dest_types);
+  IIFORMAT_HAS_METHOD (imagick, instantiate);
+
+  IIFORMAT_VALID_KEYWORD (imagick, Q_data, check_valid_string);
+  IIFORMAT_VALID_KEYWORD (imagick, Q_file, check_valid_string);
 #endif
 
 #ifdef HAVE_XPM
@@ -3963,22 +2786,6 @@
 void
 vars_of_glyphs_x (void)
 {
-#ifdef HAVE_JPEG
-  Fprovide (Qjpeg);
-#endif
-
-#ifdef HAVE_GIF
-  Fprovide (Qgif);
-#endif
-
-#ifdef HAVE_PNG
-  Fprovide (Qpng);
-#endif
-
-#ifdef HAVE_TIFF
-  Fprovide (Qtiff);
-#endif
-
 #ifdef HAVE_XPM
   Fprovide (Qxpm);
 
@@ -3996,6 +2803,10 @@
   Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */
 #endif
 
+#ifdef HAVE_IMAGEMAGICK
+  Fprovide (Qimagick);
+#endif
+
 #ifdef HAVE_XFACE
   Fprovide (Qxface);
 #endif