root/magick/xwindow.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. MagickShmAt
  2. MagickShmCtl
  3. MagickShmDt
  4. MagickXDestroyX11Resources
  5. MagickXDestroyXWindows
  6. MagickXDestroyXWindowInfo
  7. MagickIsTrue
  8. MagickXAnnotateImage
  9. MagickFontToList
  10. MagickXBestFont
  11. MagickXBestIconSize
  12. MagickXBestPixel
  13. MagickXBestVisualInfo
  14. MagickXCheckRefreshWindows
  15. MagickXClientMessage
  16. MagickXClientWindow
  17. MagickXConfigureImageColormap
  18. MagickXConstrainWindowPosition
  19. MagickXDelay
  20. MagickXDestroyResourceInfo
  21. MagickXDestroyWindowColors
  22. MagickXDisplayImageInfo
  23. MagickXDitherImage
  24. MagickXDrawImage
  25. MagickXFreeResources
  26. MagickXFreeStandardColormap
  27. MagickXGetAnnotateInfo
  28. MagickXGetMapInfo
  29. MagickXGetImportInfo
  30. MagickXGetPixelPacket
  31. MagickXGetResourceClass
  32. MagickXGetResourceDatabase
  33. MagickXGetResourceInfo
  34. MagickXGetResourceInstance
  35. MagickXGetScreenDensity
  36. MagickXGetSubwindow
  37. MagickXGetWindowColor
  38. MagickXGetWindowImage
  39. MagickXGetWindowInfo
  40. MagickXHighlightEllipse
  41. MagickXHighlightLine
  42. MagickXHighlightRectangle
  43. MagickXImportImage
  44. MagickXInitializeWindows
  45. MagickXMakeCursor
  46. MagickXImageFormatToString
  47. MagickXByteOrderToString
  48. MagickXMakeImage
  49. MagickXMakeImageLSBFirst
  50. MagickXMakeImageMSBFirst
  51. MagickXMakeMagnifyImage
  52. MagickXMakePixmap
  53. MagickXMakeStandardColormap
  54. MagickXMakeWindow
  55. MagickXMagickMonitor
  56. MagickXQueryColorDatabase
  57. MagickXQueryPosition
  58. MagickXRefreshWindow
  59. MagickXRemoteCommand
  60. MagickXRetainWindowColors
  61. MagickXSelectWindow
  62. MagickXSetCursorState
  63. MagickXSetWindows
  64. MagickXUserPreferences
  65. MagickXVisualClassName
  66. MagickXWarning
  67. MagickXWindowByID
  68. MagickXWindowByName
  69. MagickXWindowByProperty

/*
% Copyright (C) 2003 - 2009 GraphicsMagick Group
% Copyright (C) 2002 ImageMagick Studio
%
% This program is covered by multiple licenses, which are described in
% Copyright.txt. You should have received a copy of Copyright.txt with this
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%              X   X  W   W  IIIII  N   N  DDDD    OOO   W   W                %
%               X X   W   W    I    NN  N  D   D  O   O  W   W                %
%                X    W   W    I    N N N  D   D  O   O  W   W                %
%               X X   W W W    I    N  NN  D   D  O   O  W W W                %
%              X   X   W W   IIIII  N   N  DDDD    OOO    W W                 %
%                                                                             %
%                                                                             %
%                  X11 Utility Methods for GraphicsMagick                     %
%                                                                             %
%                                                                             %
%                               Software Design                               %
%                                 John Cristy                                 %
%                                  July 1992                                  %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/

/*
  Include declarations.
*/
#include "magick/studio.h"
#include "magick/analyze.h"
#include "magick/blob.h"
#include "magick/color.h"
#include "magick/color_lookup.h"
#include "magick/colormap.h"
#include "magick/composite.h"
#include "magick/constitute.h"
#include "magick/describe.h"
#include "magick/log.h"
#include "magick/magick.h"
#include "magick/monitor.h"
#include "magick/pixel_cache.h"
#include "magick/resize.h"
#include "magick/shear.h"
#include "magick/tempfile.h"
#include "magick/texture.h"
#include "magick/transform.h"
#include "magick/utility.h"
#include "magick/version.h"
#if defined(HasSharedMemory)
# if defined(HAVE_MACHINE_PARAM_H)
   /* Need by some *BSD systems in order to use shmget */
#  include <machine/param.h>
# endif /* defined(HAVE_MACHINE_PARAM_H */
# if defined(__FreeBSD__)
#  if __FreeBSD__ >= 5 && defined(_POSIX_C_SOURCE)
   typedef unsigned short ushort; /* needed for sys/ipc.h at the moment */
#  endif
# endif
# include <sys/ipc.h>
# include <sys/shm.h>
#endif
#include "magick/xwindow.h"
#if defined(HasX11)
# if defined(HasShape)
#  include <X11/extensions/shape.h>
# endif
#if defined(HasSharedMemory)
# include <X11/extensions/XShm.h>
#endif

/*
  X defines.
*/
#define MagickXBlueGamma(color) ((Quantum) (blue_gamma == 1.0 ? (color) : \
  ((pow((double) (color)/MaxRGB,1.0/blue_gamma)*MaxRGB)+0.5)))
#define MagickXGammaPixel(map,color)  (unsigned long) (map->base_pixel+ \
  ((ScaleQuantumToShort(MagickXRedGamma((color)->red))*map->red_max/65535L)* \
    map->red_mult)+ \
  ((ScaleQuantumToShort(MagickXGreenGamma((color)->green))*map->green_max/65535L)* \
    map->green_mult)+ \
  ((ScaleQuantumToShort(MagickXBlueGamma((color)->blue))*map->blue_max/65535L)* \
    map->blue_mult))
#define MagickXGreenGamma(color) ((Quantum) (green_gamma == 1.0 ? (color) : \
  ((pow((double) (color)/MaxRGB,1.0/green_gamma)*MaxRGB)+0.5)))
#define MagickXRedGamma(color) ((Quantum) (red_gamma == 1.0 ? (color) : \
  ((pow((double) (color)/MaxRGB,1.0/red_gamma)*MaxRGB)+0.5)))
#define MagickXStandardPixel(map,color)  (unsigned long) (map->base_pixel+ \
  (((color)->red*map->red_max/65535L)*map->red_mult)+ \
  (((color)->green*map->green_max/65535L)*map->green_mult)+ \
  (((color)->blue*map->blue_max/65535L)*map->blue_mult))

/*
  Constant declaractions.
*/
static unsigned int
  xerror_alert = False;

/*
  Method prototypes.
*/
static char
  *MagickXVisualClassName(const int);

static double
  blue_gamma = 1.0,
  green_gamma = 1.0,
  red_gamma = 1.0;

static unsigned int
  MagickXMakePixmap(Display *,const MagickXResourceInfo *,MagickXWindowInfo *);

static void
  MagickXMakeImageLSBFirst(const MagickXResourceInfo *,const MagickXWindowInfo *,Image *,
    XImage *,XImage *),
  MagickXMakeImageMSBFirst(const MagickXResourceInfo *,const MagickXWindowInfo *,Image *,
    XImage *,XImage *);

static Window
  MagickXSelectWindow(Display *,RectangleInfo *);

#if defined(HasSharedMemory)
/*
  Attach to shared memory.
*/
static void *
MagickShmAt(int shmid, void *shmaddr, int shmflg)
{
  void *
    address;

  if ((address=shmat(shmid,shmaddr,shmflg)) == (void *) -1)
    {
      if (shmaddr)
        (void) LogMagickEvent(X11Event,GetMagickModule(),
           "shm attach to id %d failed (%s)", shmid, strerror(errno));
      else
        (void) LogMagickEvent(X11Event,GetMagickModule(),
           "shm attach to id %d at address 0x%p failed (%s)", shmid, shmaddr,
             strerror(errno));
    }
  else
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),
         "shm attach to id %d at address 0x%p", shmid, address);
    }


  (void) LogMagickEvent(X11Event,GetMagickModule(),
    "shm attach to id %d at address 0x%p, errno=%d", shmid, address, errno);
  return (address);
}
/*
  Shared memory control operations.
*/
static int 
MagickShmCtl(int shmid, int cmd, struct shmid_ds *buf)
{
  int status;
  if ((status=shmctl(shmid, cmd, buf)) == -1)
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"shm control id=%d cmd=%s failed (%s)",
                            shmid, ((cmd == IPC_STAT) ? "IPC_STAT" : 
                                    (cmd == IPC_SET) ? "IPC_SET" :
                                    (cmd == IPC_RMID) ? "IPC_RMID" : "Unknown"),
                            strerror(errno));
    }
  else
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"shm control id=%d cmd=%s",
                            shmid, ((cmd == IPC_STAT) ? "IPC_STAT" : 
                                    (cmd == IPC_SET) ? "IPC_SET" :
                                    (cmd == IPC_RMID) ? "IPC_RMID" : "Unknown"));
    }
  return status;
}
/*
  Detatch from shared memory.
*/
static int 
MagickShmDt(void *shmaddr)
{
  int result;
  if ((result=shmdt(shmaddr)) == -1)
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),
                            "shm detatch at address 0x%p failed (%s)",
                            shmaddr,
                            strerror(errno));
    }
  else
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),
                            "shm detatch at address 0x%p",
                            shmaddr);
    }
  return (result);
}
#endif

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e s t r o y X 1 1 R e s o u r c e s                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MagickXDestroyX11Resources() destroys all remaining allocations related
%  to X11, and closes the X11 display. It is intended to be invoked by
%  DestroyMagick().
%
%  The format of the MagickXDestroyX11Resources method is:
%
%      void MagickXDestroyX11Resources(void)
%
%  A description of each parameter follows:
%
%
*/
MagickExport void 
MagickXDestroyX11Resources(void)
{
  MagickXWindows *windows = MagickXSetWindows((MagickXWindows *) ~0);
  if (windows != (MagickXWindows *) NULL)
    {
      MagickXDestroyXWindows(windows);
      (void) MagickXSetWindows((MagickXWindows *) NULL);  
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e s t r o y X W i n d o w s                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MagickXDestroyXWindows() destroys existing allocations in an MagickXWindows
%  structure.
%
%  The format of the MagickXDestroyXWindows method is:
%
%      void MagickXDestroyXWindows(MagickXWindows *windows)
%
%  A description of each parameter follows:
%
%
*/
MagickExport void 
MagickXDestroyXWindows(MagickXWindows *windows)
{
  if (windows == (MagickXWindows *) NULL ||
      (windows->display == (Display *) NULL))
    return;
  MagickFreeMemory(windows->icon_resources);

  if (windows->icon_pixel)
    {
      MagickFreeMemory(windows->icon_pixel->pixels);
      if (windows->icon_pixel->annotate_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->icon_pixel->annotate_context); /* Allocated by XCreateGC */
      if (windows->icon_pixel->widget_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->icon_pixel->widget_context); /* Allocated by XCreateGC */
      if (windows->icon_pixel->highlight_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->icon_pixel->highlight_context); /* Allocated by XCreateGC */
      MagickFreeMemory(windows->icon_pixel);
    }

  if (windows->pixel_info)
    {
      MagickFreeMemory(windows->pixel_info->pixels);
      if (windows->pixel_info->annotate_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->pixel_info->annotate_context); /* Allocated by XCreateGC */
      if (windows->pixel_info->widget_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->pixel_info->widget_context); /* Allocated by XCreateGC */
      if (windows->pixel_info->highlight_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->pixel_info->highlight_context); /* Allocated by XCreateGC */
      MagickFreeMemory(windows->pixel_info);
    }

  if (windows->font_info != (XFontStruct *) NULL)
    {
      (void) XFreeFont(windows->display,windows->font_info); /* Allocated by XLoadQueryFont */
      windows->font_info=(XFontStruct *) NULL;
    }

  if (windows->class_hints != (XClassHint *) NULL)
    {
      (void) XFree(windows->class_hints); /* Allocated by XAllocClassHint */
      windows->class_hints=(XClassHint *) NULL;
    }

  if (windows->manager_hints != (XWMHints *) NULL)
    {
      (void) XFree(windows->manager_hints); /* Allocated by XAllocWMHints */
      windows->manager_hints=(XWMHints *) NULL;
    }

  if (windows->map_info != (XStandardColormap *) NULL)
    {
      (void) XFree(windows->map_info); /* Allocated by XAllocStandardColormap */
      windows->map_info=(XStandardColormap *) NULL;
    }

  if(windows->icon_map != (XStandardColormap *) NULL)
    {
      (void) XFree(windows->icon_map); /* Allocated by XAllocStandardColormap */
      windows->icon_map=(XStandardColormap *) NULL;
    }

  if (windows->visual_info != (XVisualInfo *) NULL)
    {
      (void) XFree(windows->visual_info); /* Allocated by XGetVisualInfo */
      windows->visual_info=(XVisualInfo *) NULL;
    }

  if (windows->icon_visual != (XVisualInfo *) NULL)
    {
      (void) XFree(windows->icon_visual); /* Allocated by XGetVisualInfo */
      windows->icon_visual=(XVisualInfo *) NULL;
    }

  MagickXDestroyXWindowInfo(windows->display,&windows->context);
  MagickXDestroyXWindowInfo(windows->display,&windows->backdrop);
  MagickXDestroyXWindowInfo(windows->display,&windows->icon);
  MagickXDestroyXWindowInfo(windows->display,&windows->image);
  MagickXDestroyXWindowInfo(windows->display,&windows->info);
  MagickXDestroyXWindowInfo(windows->display,&windows->magnify);
  MagickXDestroyXWindowInfo(windows->display,&windows->pan);
  MagickXDestroyXWindowInfo(windows->display,&windows->command);
  MagickXDestroyXWindowInfo(windows->display,&windows->widget);
  MagickXDestroyXWindowInfo(windows->display,&windows->popup);
  MagickXDestroyXWindowInfo(windows->display,&windows->group_leader);
  windows->display=(Display *) NULL;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e s t r o y X W i n d o w I n f o                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MagickXDestroyXWindowInfo() destroys existing allocations in an
%  MagickXWindowInfo structure. The MagickXWindowInfo structure itself is
%  not freed.
%
%  The format of the MagickXDestroyXWindowInfo method is:
%
%      void MagickXDestroyXWindowInfo(Display *display,
%                                     MagickXWindowInfo *window)
%
%  A description of each parameter follows:
%
%    o display: Pointer to an X11 Display structure
%
%    o window: Pointer to MagickXWindowInfo structure to destroy.
*/
MagickExport void 
MagickXDestroyXWindowInfo(Display *display,MagickXWindowInfo *window)
{
  if (window->mapped != False)
    {
      (void) XWithdrawWindow(display,window->id,
                             window->screen);
      (void) XSync(display,False);
      window->mapped=False;
    }

  MagickFreeMemory(window->name);

  MagickFreeMemory(window->icon_name);

  if (window->cursor != (Cursor) NULL)
    {
      (void) XFreeCursor(display,window->cursor);
      window->cursor=(Cursor) NULL;
    }

  if (window->highlight_stipple != (Pixmap) NULL)
    {
      (void) XFreePixmap(display,window->highlight_stipple);
      window->highlight_stipple=(Pixmap) NULL;
    }

  if (window->shadow_stipple != (Pixmap) NULL)
    {
      (void) XFreePixmap(display,window->shadow_stipple);
      window->shadow_stipple=(Pixmap) NULL;
   }

  if (window->ximage != (XImage *) NULL)
    {
      XDestroyImage(window->ximage);
      window->ximage=(XImage *) NULL;
    }

  if (window->matte_image != (XImage *) NULL)
    {
      /* MagickFreeMemory(window->matte_image->data); ???? */
      XDestroyImage(window->matte_image);
      window->matte_image=(XImage *) NULL;
    }

  if (window->pixmap != (Pixmap) NULL)
    {
      (void) XFreePixmap(display,window->pixmap);
      window->pixmap=(Pixmap) NULL;
    }

  if (window->id != (Window) NULL)
    {
      (void) XDestroyWindow(display,window->id);
      window->id=(Window) NULL;
    }

  if (window->destroy)
    {
      if (window->image != (Image *) NULL)
        {
          DestroyImage(window->image);
          window->image=(Image *) NULL;
        }
    }

  if (window->segment_info != (void *) NULL)
    {
#if defined(HasSharedMemory)
      XShmSegmentInfo
        *segment_info;
          
      segment_info=(XShmSegmentInfo *) window->segment_info;
      if (segment_info != (XShmSegmentInfo *) NULL)
        {
          if (segment_info[0].shmid >= 0)
            {
              if (segment_info[0].shmaddr != NULL)
                (void) MagickShmDt(segment_info[0].shmaddr);
              (void) MagickShmCtl(segment_info[0].shmid,IPC_RMID,0);
              segment_info[0].shmaddr=NULL;
              segment_info[0].shmid=(-1);
            }
        }
#endif

      MagickFreeMemory(window->segment_info);
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k I s T r u e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickIsTrue returns True if the reason is "true", "on", "yes"
%  or "1".
%
%  The format of the MagickIsTrue method is:
%
%      unsigned int MagickIsTrue(const char *reason)
%
%  A description of each parameter follows:
%
%    o option: either True or False depending on the reason parameter.
%
%    o reason: Specifies a pointer to a character array.
%
%
*/
MagickExport unsigned int 
MagickIsTrue(const char *reason)
{
  if (reason == (char *) NULL)
    return(False);
  if (LocaleCompare(reason,"true") == 0)
    return(True);
  if (LocaleCompare(reason,"on") == 0)
    return(True);
  if (LocaleCompare(reason,"yes") == 0)
    return(True);
  if (LocaleCompare(reason,"1") == 0)
    return(True);
  return(False);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X A n n o t a t e I m a g e                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXAnnotateImage annotates the image with text.
%
%  The format of the MagickXAnnotateImage method is:
%
%      unsigned int MagickXAnnotateImage(Display *display,
%        const MagickXPixelInfo *pixel,MagickXAnnotateInfo *annotate_info,
%        Image *image)
%
%  A description of each parameter follows:
%
%    o status: Method MagickXAnnotateImage returns True if the image is
%      successfully annotated with text.  False is returned is there is a
%      memory shortage.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%    o annotate_info: Specifies a pointer to a MagickXAnnotateInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%
*/
MagickExport unsigned int 
MagickXAnnotateImage(Display *display,
                     const MagickXPixelInfo *pixel,
                     MagickXAnnotateInfo *annotate_info,
                     Image *image)
{
  GC
    annotate_context;

  Image
    *annotate_image;

  int
    x,
    y;

  Pixmap
    annotate_pixmap;

  register PixelPacket
    *q;

  unsigned int
    depth,
    height,
    matte,
    width;

  Window
    root_window;

  XGCValues
    context_values;

  XImage
    *annotate_ximage;

  /*
    Initialize annotated image.
  */
  assert(display != (Display *) NULL);
  assert(pixel != (MagickXPixelInfo *) NULL);
  assert(annotate_info != (MagickXAnnotateInfo *) NULL);
  assert(image != (Image *) NULL);
  /*
    Initialize annotated pixmap.
  */
  root_window=XRootWindow(display,XDefaultScreen(display));
  depth=XDefaultDepth(display,XDefaultScreen(display));
  annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
    annotate_info->height,(int) depth);
  if (annotate_pixmap == (Pixmap) NULL)
    return(False);
  /*
    Initialize graphics info.
  */
  context_values.background=0;
  context_values.foreground=(unsigned long) (~0);
  context_values.font=annotate_info->font_info->fid;
  annotate_context=XCreateGC(display,root_window,GCBackground | GCFont |
    GCForeground,&context_values);
  if (annotate_context == (GC) NULL)
    return(False);
  /*
    Draw text to pixmap.
  */
  (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
    (int) annotate_info->font_info->ascent,annotate_info->text,
    (int) strlen(annotate_info->text));
  (void) XFreeGC(display,annotate_context);
  /*
    Initialize annotated X image.
  */
  annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
    annotate_info->height,AllPlanes,ZPixmap);
  if (annotate_ximage == (XImage *) NULL)
    return(False);
  (void) XFreePixmap(display,annotate_pixmap);
  /*
    Initialize annotated image.
  */
  annotate_image=AllocateImage((ImageInfo *) NULL);
  if (annotate_image == (Image *) NULL)
    return(False);
  annotate_image->columns=annotate_info->width;
  annotate_image->rows=annotate_info->height;
  /*
    Transfer annotated X image to image.
  */
  width=(unsigned int) image->columns;
  height=(unsigned int) image->rows;
  x=0;
  y=0;
  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
  (void) AcquireOnePixelByReference(image,&annotate_image->background_color,
                                    x,y,&image->exception);
  annotate_image->matte=annotate_info->stencil == ForegroundStencil;
  for (y=0; y < (long) annotate_image->rows; y++)
  {
    q=GetImagePixels(annotate_image,0,y,annotate_image->columns,1);
    if (q == (PixelPacket *) NULL)
      break;
    for (x=0; x < (long) annotate_image->columns; x++)
    {
      q->opacity=OpaqueOpacity;
      if (XGetPixel(annotate_ximage,x,y) == 0)
        {
          /*
            Set this pixel to the background color.
          */
          q->red=ScaleShortToQuantum(pixel->box_color.red);
          q->green=ScaleShortToQuantum(pixel->box_color.green);
          q->blue=ScaleShortToQuantum(pixel->box_color.blue);
          if ((annotate_info->stencil == ForegroundStencil) ||
              (annotate_info->stencil == OpaqueStencil))
            q->opacity=TransparentOpacity;
        }
      else
        {
          /*
            Set this pixel to the pen color.
          */
          q->red=ScaleShortToQuantum(pixel->pen_color.red);
          q->green=ScaleShortToQuantum(pixel->pen_color.green);
          q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
          if (annotate_info->stencil == BackgroundStencil)
            q->opacity=TransparentOpacity;
        }
      q++;
    }
    if (!SyncImagePixels(annotate_image))
      break;
  }
  XDestroyImage(annotate_ximage);
  annotate_ximage=(XImage *) NULL;
  /*
    Determine annotate geometry.
  */
  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
  if ((width != (unsigned int) annotate_image->columns) ||
      (height != (unsigned int) annotate_image->rows))
    {
      char
        image_geometry[MaxTextExtent];

      /*
        Scale image.
      */
      FormatString(image_geometry,"%ux%u",width,height);
      TransformImage(&annotate_image,(char *) NULL,image_geometry);
    }
  if (annotate_info->degrees != 0.0)
    {
      double
        normalized_degrees;

      Image
        *rotate_image;

      int
        rotations;

      /*
        Rotate image.
      */
      rotate_image=
        RotateImage(annotate_image,annotate_info->degrees,&image->exception);
      if (rotate_image == (Image *) NULL)
        return(False);
      DestroyImage(annotate_image);
      annotate_image=rotate_image;
      /*
        Annotation is relative to the degree of rotation.
      */
      normalized_degrees=annotate_info->degrees;
      while (normalized_degrees < -45.0)
        normalized_degrees+=360.0;
      for (rotations=0; normalized_degrees > 45.0; rotations++)
        normalized_degrees-=90.0;
      switch (rotations % 4)
      {
        default:
        case 0:
          break;
        case 1:
        {
          /*
            Rotate 90 degrees.
          */
          x-=(int) annotate_image->columns/2;
          y+=(int) annotate_image->columns/2;
          break;
        }
        case 2:
        {
          /*
            Rotate 180 degrees.
          */
          x=x-(int) annotate_image->columns;
          break;
        }
        case 3:
        {
          /*
            Rotate 270 degrees.
          */
          x=x-(int) annotate_image->columns/2;
          y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
          break;
        }
      }
    }
  /*
    Composite text onto the image.
  */
  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
  matte=image->matte;
  (void) CompositeImage(image,annotate_image->matte ? OverCompositeOp :
    CopyCompositeOp,annotate_image,x,y);
  image->matte=matte;
  DestroyImage(annotate_image);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X B e s t F o n t                                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXBestFont returns the "best" font.  "Best" is defined as a font
%  specified in the X resource database or a font such that the text width
%  displayed with the font does not exceed the specified maximum width.
%
%  The format of the MagickXBestFont method is:
%
%      XFontStruct *MagickXBestFont(Display *display,
%        const MagickXResourceInfo *resource_info,const unsigned int text_font)
%
%  A description of each parameter follows:
%
%    o font: MagickXBestFont returns a pointer to a XFontStruct structure.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o text_font:  True is font should be mono-spaced (typewriter style).
%
%
*/
static char **
MagickFontToList(char *font)
{
  char
    **fontlist;

  register char
    *p,
    *q;

  register int
    i;

  unsigned int
    fonts;

  if (font == (char *) NULL)
    return((char **) NULL);
  /*
    Convert string to an ASCII list.
  */
  fonts=1;
  for (p=font; *p != '\0'; p++)
    if ((*p == ':') || (*p == ';') || (*p == ','))
      fonts++;
  fontlist=MagickAllocateArray(char **,(fonts+1),sizeof(char *));
  if (fontlist == (char **) NULL)
    {
      MagickError3(ResourceLimitError,MemoryAllocationFailed,
        UnableToConvertFont);
      return((char **) NULL);
    }
  p=font;
  for (i=0; i < (int) fonts; i++)
  {
    for (q=p; *q != '\0'; q++)
      if ((*q == ':') || (*q == ';') || (*q == ','))
        break;
    fontlist[i]=MagickAllocateMemory(char *,(size_t) (q-p+1));
    if (fontlist[i] == (char *) NULL)
      {
        MagickError3(ResourceLimitError,MemoryAllocationFailed,
          UnableToConvertFont);
        return((char **) NULL);
      }
    (void) strlcpy(fontlist[i],p,q-p+1);
    p=q+1;
  }
  fontlist[i]=(char *) NULL;
  return(fontlist);
}

MagickExport XFontStruct *
MagickXBestFont(Display *display,
                const MagickXResourceInfo *resource_info,
                const unsigned int text_font)
{
  static const char
    *Fonts[]=
    {
      "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
      "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
      "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
      "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
      "variable",
      (char *) NULL
    },
    *TextFonts[]=
    {
      "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
      "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
      "fixed",
      (char *) NULL
    };

  char
    *font_name;

  register const char
    **p;

  XFontStruct
    *font_info;

  font_info=(XFontStruct *) NULL;
  font_name=resource_info->font;
  if (text_font)
    font_name=resource_info->text_font;
  if (font_name != (char *) NULL)
    {
      char
        **fontlist;

      register int
        i;

      /*
        Load preferred font specified in the X resource database.
      */
      fontlist=MagickFontToList(font_name);
      if (fontlist != (char **) NULL)
        {
          for (i=0; fontlist[i] != (char *) NULL; i++)
          {
            if (font_info == (XFontStruct *) NULL)
              font_info=XLoadQueryFont(display,fontlist[i]);
            MagickFreeMemory(fontlist[i]);
          }
          MagickFreeMemory(fontlist);
        }
      if (font_info == (XFontStruct *) NULL)
        MagickError(XServerError,UnableToLoadFont,font_name);
    }
  /*
    Load fonts from list of fonts until one is found.
  */
  p=Fonts;
  if (text_font)
    p=TextFonts;
  if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
    p++;
  while (*p != (char *) NULL)
  {
    if (font_info != (XFontStruct *) NULL)
      break;
    font_info=XLoadQueryFont(display,(char *) *p);
    p++;
  }
  return(font_info);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X B e s t I c o n S i z e                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXBestIconSize returns the "best" icon size.  "Best" is
%  defined as an icon size that maintains the aspect ratio of the image.
%  If the window manager has preferred icon sizes, one of the preferred
%  sizes is used.
%
%  The format of the MagickXBestIconSize method is:
%
%      void MagickXBestIconSize(Display *display,MagickXWindowInfo *window,
%                               Image *image)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%
*/
MagickExport void
MagickXBestIconSize(Display *display,MagickXWindowInfo *window,
  Image *image)
{
  double
    scale_factor;

  int
    i,
    number_sizes;

  unsigned int
    height,
    icon_height,
    icon_width,
    width;

  Window
    root_window;

  XIconSize
    *icon_size,
    *size_list;

  /*
    Determine if the window manager has specified preferred icon sizes.
  */
  assert(display != (Display *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  assert(image != (Image *) NULL);
  window->width=MaxIconSize;
  window->height=MaxIconSize;
  icon_size=(XIconSize *) NULL;
  number_sizes=0;
  root_window=XRootWindow(display,window->screen);
  if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
    if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
      icon_size=size_list;
  if (icon_size == (XIconSize *) NULL)
    {
      /*
        Window manager does not restrict icon size.
      */
      icon_size=XAllocIconSize();
      if (icon_size == (XIconSize *) NULL)
        {
          MagickError3(ResourceLimitError,MemoryAllocationFailed,
            UnableToGetBestIconSize);
          return;
        }
      icon_size->min_width=1;
      icon_size->max_width=MaxIconSize;
      icon_size->min_height=1;
      icon_size->max_height=MaxIconSize;
      icon_size->width_inc=1;
      icon_size->height_inc=1;
    }
  /*
    Determine aspect ratio of image.
  */
  width=(unsigned int) image->columns;
  height=(unsigned int) image->rows;
  i=0;
  if (window->crop_geometry)
    (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
  /*
    Look for an icon size that maintains the aspect ratio of image.
  */
  scale_factor=(double) icon_size->max_width/width;
  if (scale_factor > ((double) icon_size->max_height/height))
    scale_factor=(double) icon_size->max_height/height;
  icon_width=icon_size->min_width;
  while ((int) icon_width < icon_size->max_width)
  {
    if (icon_width >= (scale_factor*width))
      break;
    icon_width+=icon_size->width_inc;
  }
  icon_height=icon_size->min_height;
  while ((int) icon_height < icon_size->max_height)
  {
    if (icon_height >= (scale_factor*height))
      break;
    icon_height+=icon_size->height_inc;
  }
  (void) XFree((void *) icon_size);
  window->width=icon_width;
  window->height=icon_height;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X B e s t P i x e l                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXBestPixel returns a pixel from an array of pixels that is
%  closest to the requested color.  If the color array is NULL, the colors
%  are obtained from the X server.
%
%  The format of the MagickXBestPixel method is:
%
%      void MagickXBestPixel(Display *display,const Colormap colormap,
%        XColor *colors,unsigned int number_colors,XColor *color)
%
%  A description of each parameter follows:
%
%    o pixel: MagickXBestPixel returns the pixel value closest to the requested
%      color.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o colormap: Specifies the ID of the X server colormap.
%
%    o colors: Specifies an array of XColor structures.
%
%    o number_colors: Specifies the number of XColor structures in the
%      color definition array.
%
%    o color: Specifies the desired RGB value to find in the colors array.
%
%
*/
MagickExport void 
MagickXBestPixel(Display *display,const Colormap colormap,
                 XColor *colors,unsigned int number_colors,XColor *color)
{
  double
    min_distance;

  DoublePixelPacket
    pixel;

  int
    query_server,
    status;

  register double
    distance;

  register int
    i,
    j;

  /*
    Find closest representation for the requested RGB color.
  */
  assert(display != (Display *) NULL);
  assert(color != (XColor *) NULL);
  status=XAllocColor(display,colormap,color);
  if (status != 0)
    return;
  query_server=colors == (XColor *) NULL;
  if (query_server)
    {
      /*
        Read X server colormap.
      */
      colors=MagickAllocateArray(XColor *,number_colors,sizeof(XColor));
      if (colors == (XColor *) NULL)
        {
          MagickError3(ResourceLimitError,MemoryAllocationFailed,
            UnableToReadXServerColormap);
          return;
        }
      for (i=0; i < (int) number_colors; i++)
        colors[i].pixel=(unsigned long) i;
      if (number_colors > 256)
        number_colors=256;
      (void) XQueryColors(display,colormap,colors,number_colors);
    }
  min_distance=3.0*((double) MaxRGB+1.0)*((double) MaxRGB+1.0);
  j=0;
  for (i=0; i < (int) number_colors; i++)
  {
    pixel.red=colors[i].red-(double) color->red;
    distance=pixel.red*pixel.red;
    if (distance > min_distance)
      continue;
    pixel.green=colors[i].green-(double) color->green;
    distance+=pixel.green*pixel.green;
    if (distance > min_distance)
      continue;
    pixel.blue=colors[i].blue-(double) color->blue;
    distance+=pixel.blue*pixel.blue;
    if (distance > min_distance)
      continue;
    min_distance=distance;
    color->pixel=colors[i].pixel;
    j=i;
  }
  (void) XAllocColor(display,colormap,&colors[j]);
  if (query_server)
    MagickFreeMemory(colors);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X B e s t V i s u a l I n f o                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXBestVisualInfo returns visual information for a visual that is
%  the "best" the server supports.  "Best" is defined as:
%
%    1. Restrict the visual list to those supported by the default screen.
%
%    2. If a visual type is specified, restrict the visual list to those of
%       that type.
%
%    3. If a map type is specified, choose the visual that matches the id
%       specified by the Standard Colormap.
%
%    4  From the list of visuals, choose one that can display the most
%       simultaneous colors.  If more than one visual can display the same
%       number of simultaneous colors, one is chosen based on a rank.
%
%  The format of the MagickXBestVisualInfo method is:
%
%      XVisualInfo *MagickXBestVisualInfo(Display *display,
%        XStandardColormap *map_info,MagickXResourceInfo *resource_info)
%
%  A description of each parameter follows:
%
%    o visual_info: MagickXBestVisualInfo returns a pointer to a X11
%      XVisualInfo structure.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o map_info: If map_type is specified, this structure is initialized
%      with info from the Standard Colormap.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%
*/
#define MaxStandardColormaps  7
#define MagickXVisualColormapSize(visual_info) Min( (int) (\
  ((visual_info->class == TrueColor) || (visual_info->class == DirectColor)) ? \
    (int) (visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask) : \
    visual_info->colormap_size),(1 << visual_info->depth))

MagickExport XVisualInfo *
MagickXBestVisualInfo(Display *display,
                      XStandardColormap *map_info,
                      MagickXResourceInfo *resource_info)
{
  char
    *map_type,
    *visual_type;

  long
    visual_mask;

  register int
    i;

  static int
    number_visuals;

  static XVisualInfo
    visual_template;

  XVisualInfo
    *visual_info,
    *visual_list;

  /*
    Restrict visual search by screen number.
  */
  assert(display != (Display *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  map_type=resource_info->map_type;
  visual_type=resource_info->visual_type;
  visual_mask=VisualScreenMask;
  visual_template.screen=XDefaultScreen(display);
  visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
  if (resource_info->immutable && (resource_info->colors != 0))
    if (resource_info->colors <= (1UL << visual_template.depth))
      visual_mask|=VisualDepthMask;
  if (visual_type != (char *) NULL)
    {
      /*
        Restrict visual search by class or visual id.
      */
      if (LocaleCompare("staticgray",visual_type) == 0)
        {
          visual_mask|=VisualClassMask;
          visual_template.class=StaticGray;
        }
      else
        if (LocaleCompare("grayscale",visual_type) == 0)
          {
            visual_mask|=VisualClassMask;
            visual_template.class=GrayScale;
          }
        else
          if (LocaleCompare("staticcolor",visual_type) == 0)
            {
              visual_mask|=VisualClassMask;
              visual_template.class=StaticColor;
            }
          else
            if (LocaleCompare("pseudocolor",visual_type) == 0)
              {
                visual_mask|=VisualClassMask;
                visual_template.class=PseudoColor;
              }
            else
              if (LocaleCompare("truecolor",visual_type) == 0)
                {
                  visual_mask|=VisualClassMask;
                  visual_template.class=TrueColor;
                }
              else
                if (LocaleCompare("directcolor",visual_type) == 0)
                  {
                    visual_mask|=VisualClassMask;
                    visual_template.class=DirectColor;
                  }
                else
                  if (LocaleCompare("default",visual_type) == 0)
                    {
                      visual_mask|=VisualIDMask;
                      visual_template.visualid=XVisualIDFromVisual(
                        XDefaultVisual(display,XDefaultScreen(display)));
                    }
                  else
                    if (isdigit((int) (*visual_type)))
                      {
                        visual_mask|=VisualIDMask;
                        visual_template.visualid=
                          strtol(visual_type,(char **) NULL,0);
                      }
                    else
                      MagickError(XServerError,UnrecognizedVisualSpecifier,
                        visual_type);
    }
  /*
    Get all visuals that meet our criteria so far.
  */
  number_visuals=0;
  visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
    &number_visuals);
  visual_mask=VisualScreenMask | VisualIDMask;
  if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
    {
      /*
        Failed to get visual;  try using the default visual.
      */
      MagickWarning(XServerWarning,UnableToGetVisual,visual_type);
      visual_template.visualid=
        XVisualIDFromVisual(XDefaultVisual(display,XDefaultScreen(display)));
      visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
        &number_visuals);
      if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
        return((XVisualInfo *) NULL);
      MagickWarning(XServerWarning,UsingDefaultVisual,
        MagickXVisualClassName(visual_list->class));
    }
  resource_info->color_recovery=False;
  if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
    {
      Atom
        map_property;

      char
        map_name[MaxTextExtent];

      int
        j,
        number_maps,
        status;

      Window
        root_window;

      XStandardColormap
        *map_list;

      /*
        Choose a visual associated with a standard colormap.
      */
      root_window=XRootWindow(display,XDefaultScreen(display));
      status=0;
      if (LocaleCompare(map_type,"list") != 0)
        {
          /*
            User specified Standard Colormap.
          */
          FormatString((char *) map_name,"RGB_%.1024s_MAP",map_type);
          LocaleUpper(map_name);
          map_property=XInternAtom(display,(char *) map_name,True);
          if (map_property != (Atom) NULL)
            status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
              map_property);
        }
      else
        {
          static const char
            *colormap[MaxStandardColormaps]=
            {
              "_HP_RGB_SMOOTH_MAP_LIST",
              "RGB_BEST_MAP",
              "RGB_DEFAULT_MAP",
              "RGB_GRAY_MAP",
              "RGB_RED_MAP",
              "RGB_GREEN_MAP",
              "RGB_BLUE_MAP",
            };

          /*
            Choose a standard colormap from a list.
          */
          for (i=0; i < MaxStandardColormaps; i++)
          {
            map_property=XInternAtom(display,(char *) colormap[i],True);
            if (map_property == (Atom) NULL)
              continue;
            status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
              map_property);
            if (status != 0)
              break;
          }
          resource_info->color_recovery=(i == 0);  /* _HP_RGB_SMOOTH_MAP_LIST */
        }
      if (status == 0)
        {
          MagickError(XServerError,UnableToGetStandardColormap,map_type);
          return((XVisualInfo *) NULL);
        }
      /*
        Search all Standard Colormaps and visuals for ids that match.
      */
      *map_info=map_list[0];
#if !defined(PRE_R4_ICCCM)
      visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
      for (i=0; i < number_maps; i++)
        for (j=0; j < number_visuals; j++)
          if (map_list[i].visualid ==
              XVisualIDFromVisual(visual_list[j].visual))
            {
              *map_info=map_list[i];
              visual_template.visualid=
                XVisualIDFromVisual(visual_list[j].visual);
              break;
            }
      if (map_info->visualid != visual_template.visualid)
        {
          MagickError(XServerError,UnableToMatchVisualToStandardColormap,
            map_type);
          return((XVisualInfo *) NULL);
        }
#endif
      if (map_info->colormap == (Colormap) NULL)
        {
          MagickError(XServerError,StandardColormapIsNotInitialized,map_type);
          return((XVisualInfo *) NULL);
        }
      (void) XFree((void *) map_list);
    }
  else
    {
      static const unsigned int
        rank[]=
          {
            StaticGray,
            GrayScale,
            StaticColor,
            DirectColor,
            TrueColor,
            PseudoColor
          };

      XVisualInfo
        *p;

      /*
        Pick one visual that displays the most simultaneous colors.
      */
      visual_info=visual_list;
      p=visual_list;
      for (i=1; i < number_visuals; i++)
      {
        p++;
        if (MagickXVisualColormapSize(p) > MagickXVisualColormapSize(visual_info))
          visual_info=p;
        else
          if (MagickXVisualColormapSize(p) == MagickXVisualColormapSize(visual_info))
            if (rank[p->class] > rank[visual_info->class])
              visual_info=p;
      }
      visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
    }
  (void) XFree((void *) visual_list);
  /*
    Retrieve only one visual by its screen & id number.
  */
  visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
    &number_visuals);
  if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
    return((XVisualInfo *) NULL);
  return(visual_info);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X C h e c k R e f r e s h W i n d o w s                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXCheckRefreshWindows checks the X server for exposure events
%  for a particular window and updates the area associated with the exposure
%  event.
%
%  The format of the MagickXCheckRefreshWindows method is:
%
%      void MagickXCheckRefreshWindows(Display *display,
%                                      MagickXWindows *windows)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%
*/
MagickExport void 
MagickXCheckRefreshWindows(Display *display,MagickXWindows *windows)
{
  XEvent
    event;

  assert(display != (Display *) NULL);
  assert(windows != (MagickXWindows *) NULL);
  MagickXDelay(display,SuspendTime);
  while (XCheckTypedWindowEvent(display,windows->command.id,Expose,&event))
    (void) MagickXCommandWidget(display,windows,(char const **) NULL,&event);
  while (XCheckTypedWindowEvent(display,windows->image.id,Expose,&event))
    MagickXRefreshWindow(display,&windows->image,&event);
  MagickXDelay(display,SuspendTime << 1);
  while (XCheckTypedWindowEvent(display,windows->command.id,Expose,&event))
    (void) MagickXCommandWidget(display,windows,(char const **) NULL,&event);
  while (XCheckTypedWindowEvent(display,windows->image.id,Expose,&event))
    MagickXRefreshWindow(display,&windows->image,&event);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X C l i e n t M e s s a g e                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXClientMessage sends a reason to a window with XSendEvent.  The
%  reason is initialized with a particular protocol type and atom.
%
%  The format of the MagickXClientMessage function is:
%
%      MagickXClientMessage(display,window,protocol,reason,timestamp)
%
%  A description of each parameter follows:
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window structure.
%
%    o protocol: Specifies an atom value.
%
%    o reason: Specifies an atom value which is the reason to send.
%
%    o timestamp: Specifies a value of type Time.
%
%
*/
MagickExport void 
MagickXClientMessage(Display *display,const Window window,
  const Atom protocol,const Atom reason,const Time timestamp)
{
  XClientMessageEvent
    client_event;

  assert(display != (Display *) NULL);
  client_event.type=ClientMessage;
  client_event.window=window;
  client_event.message_type=protocol;
  client_event.format=32;
  client_event.data.l[0]=(long) reason;
  client_event.data.l[1]=(long) timestamp;
  (void) XSendEvent(display,window,False,NoEventMask,(XEvent *) &client_event);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   M a g i c k X C l i e n t W i n d o w                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method XClientWindow finds a window, at or below the specified window,
%  which has a WM_STATE property.  If such a window is found, it is returned,
%  otherwise the argument window is returned.
%
%  The format of the XClientWindow function is:
%
%      client_window=XClientWindow(display,target_window)
%
%  A description of each parameter follows:
%
%    o client_window: XClientWindow returns a window, at or below the specified
%      window, which has a WM_STATE property otherwise the argument
%      target_window is returned.
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o target_window: Specifies the window to find a WM_STATE property.
%
%
*/
static Window
MagickXClientWindow(Display *display,Window target_window)
{
  Atom
    state,
    type;

  int
    format,
    status;

  unsigned char
    *data;

  unsigned long
    after,
    number_items;

  Window
    client_window;

  assert(display != (Display *) NULL);
  state=XInternAtom(display,"WM_STATE",True);
  if (state == (Atom) NULL)
    return(target_window);
  type=(Atom) NULL;
  status=XGetWindowProperty(display,target_window,state,0L,0L,False,
    (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
  if ((status == Success) && (type != (Atom) NULL))
    return(target_window);
  client_window=MagickXWindowByProperty(display,target_window,state);
  if (client_window == (Window) NULL)
    return(target_window);
  return(client_window);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X C o n f i g u r e I m a g e C o l o r m a p                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXConfigureImageColormap creates a new X colormap.
%
%  The format of the MagickXConfigureImageColormap method is:
%
%      void MagickXConfigureImageColormap(Display *display,
%        MagickXResourceInfo *resource_info,MagickXWindows *windows,
%        Image *image)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo structure.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%
*/
MagickExport void
MagickXConfigureImageColormap(Display *display,
                              MagickXResourceInfo *resource_info,
                              MagickXWindows *windows,Image *image)
{
  Colormap
    colormap;

  /*
    Make standard colormap.
  */
  MagickXSetCursorState(display,windows,True);
  MagickXCheckRefreshWindows(display,windows);
  MagickXMakeStandardColormap(display,windows->visual_info,resource_info,image,
    windows->map_info,windows->pixel_info);
  colormap=windows->map_info->colormap;
  (void) XSetWindowColormap(display,windows->image.id,colormap);
  (void) XSetWindowColormap(display,windows->command.id,colormap);
  (void) XSetWindowColormap(display,windows->widget.id,colormap);
  if (windows->magnify.mapped)
    (void) XSetWindowColormap(display,windows->magnify.id,colormap);
  if (windows->pan.mapped)
    (void) XSetWindowColormap(display,windows->pan.id,colormap);
  MagickXSetCursorState(display,windows,False);
  MagickXClientMessage(display,windows->image.id,windows->im_protocols,
    windows->im_update_colormap,CurrentTime);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X C o n s t r a i n W i n d o w P o s i t i o n               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXConstrainWindowPosition assures a window is positioned
%  within the X server boundaries.
%
%  The format of the MagickXConstrainWindowPosition method is:
%
%      void MagickXConstrainWindowPosition(Display *display,
%                                          MagickXWindowInfo *window_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o window_info: Specifies a pointer to a MagickXWindowInfo structure.
%
%
*/
MagickExport void
MagickXConstrainWindowPosition(Display *display,
                               MagickXWindowInfo *window_info)
{
  unsigned int
    limit;

  assert(display != (Display *) NULL);
  assert(window_info != (MagickXWindowInfo *) NULL);
  limit=XDisplayWidth(display,window_info->screen)-window_info->width;
  if (window_info->x < 0)
    window_info->x=0;
  else
    if (window_info->x > (int) limit)
      window_info->x=limit;
  limit=XDisplayHeight(display,window_info->screen)-window_info->height;
  if (window_info->y < 0)
    window_info->y=0;
  else
    if (window_info->y > (int) limit)
      window_info->y=limit;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e l a y                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXDelay suspends program execution for the number of
%  milliseconds specified.
%
%  The format of the Delay method is:
%
%      void MagickXDelay(Display *display,const unsigned long milliseconds)
%
%  A description of each parameter follows:
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o milliseconds: Specifies the number of milliseconds to delay before
%      returning.
%
%
*/
MagickExport void
MagickXDelay(Display *display,const unsigned long milliseconds)
{
  assert(display != (Display *) NULL);
  (void) XFlush(display);
  if (milliseconds == 0)
    return;
#if defined(MSWINDOWS)
  Sleep(milliseconds);
#elif defined(HAVE_SELECT)
  {
    struct timeval
      timer;

    timer.tv_sec=(long) milliseconds/1000;
    timer.tv_usec=(long) (milliseconds % 1000)*1000;
    (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
  }
#elif defined(HAVE_POLL)
  (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
#else
# error "Time delay method not defined."
#endif
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e s t r o y R e s o u r c e I n f o                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MagickXDestroyResourceInfo() frees memory associated with the
%  MagickXResourceInfo structure.
%
%  The format of the MagickXDestroyResourceInfo method is:
%
%      void MagickXDestroyResourceInfo(MagickXResourceInfo *resource_info)
%
%  A description of each parameter follows:
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo structure.
%
%
*/
MagickExport void
MagickXDestroyResourceInfo(MagickXResourceInfo *resource_info)
{
  MagickFreeMemory(resource_info->image_geometry);
  if (resource_info->image_info != (ImageInfo *) NULL)
    {
      DestroyImageInfo(resource_info->image_info);
      resource_info->image_info=(ImageInfo *) NULL;
    }
  if (resource_info->quantize_info != (QuantizeInfo *) NULL)
    {
      DestroyQuantizeInfo(resource_info->quantize_info);
      resource_info->quantize_info=(QuantizeInfo *) NULL;
    }
  MagickFreeMemory(resource_info->client_name);
  MagickFreeMemory(resource_info->name);
  (void) memset((void *) resource_info,0,sizeof(MagickXResourceInfo));
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e s t r o y W i n d o w C o l o r s                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXDestroyWindowColors frees X11 color resources previously
%  saved on a window by MagickXRetainWindowColors or programs like xsetroot.
%
%  The format of the MagickXDestroyWindowColors method is:
%
%      void MagickXDestroyWindowColors(Display *display,Window window)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window structure.
%
%
*/
MagickExport void
MagickXDestroyWindowColors(Display *display,Window window)
{
  Atom
    property,
    type;

  int
    format,
    status;

  unsigned char
    *data;

  unsigned long
    after,
    length;

  /*
    If there are previous resources on the root window, destroy them.
  */
  assert(display != (Display *) NULL);
  property=XInternAtom(display,"_XSETROOT_ID",False);
  if (property == (Atom) NULL)
    {
      MagickError(XServerError,UnableToCreateProperty,"_XSETROOT_ID");
      return;
    }
  status=XGetWindowProperty(display,window,property,0L,1L,True,
    (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
  if (status != Success)
    return;
  if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
    {
      (void) XKillClient(display,(XID) (*((Pixmap *) data)));
      (void) XDeleteProperty(display,window,property);
    }
  if (type != None)
    (void) XFree((void *) data);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D i s p l a y I m a g e I n f o                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXDisplayImageInfo displays information about an X image.
%
%  The format of the MagickXDisplayImageInfo method is:
%
%      void MagickXDisplayImageInfo(Display *display,
%        const MagickXResourceInfo *resource_info,MagickXWindows *windows,
%        Image *undo_image,Image *image)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%    o undo_image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%
*/
MagickExport void
MagickXDisplayImageInfo(Display *display,
                        const MagickXResourceInfo *resource_info,
                        MagickXWindows *windows,Image *undo_image,
                        Image *image)
{
  char
    filename[MaxTextExtent],
    *text,
    **textlist;

  FILE
    *file;

  long
    bytes;

  register long
    i;

  size_t
    length;

  unsigned int
    levels;

  unsigned long
    number_pixels;

  /*
    Write info about the X server to a file.
  */
  assert(display != (Display *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(windows != (MagickXWindows *) NULL);
  assert(image != (Image *) NULL);
  file=AcquireTemporaryFileStream(filename,TextFileIOMode);
  if (file == (FILE *) NULL)
    {
      MagickXNoticeWidget(display,windows,"Unable to create temporary file",
        filename);
      return;
    }
  if (resource_info->gamma_correct)
    if (resource_info->display_gamma != (char *) NULL)
      (void) fprintf(file,"Display\n  gamma: %.1024s\n\n",
        resource_info->display_gamma);
  /*
    Write info about the X image to a file.
  */
  (void) fprintf(file,"X\n  visual: %.1024s\n",
    MagickXVisualClassName(windows->image.storage_class));
  (void) fprintf(file,"  depth: %d\n",windows->image.ximage->depth);
  if (windows->visual_info->colormap_size != 0)
    (void) fprintf(file,"  colormap size: %d\n",
      windows->visual_info->colormap_size);
  if (resource_info->colormap== SharedColormap)
    (void) fprintf(file,"  colormap type: Shared\n");
  else
    (void) fprintf(file,"  colormap type: Private\n");
  (void) fprintf(file,"  geometry: %dx%d\n",windows->image.ximage->width,
    windows->image.ximage->height);
  if (windows->image.crop_geometry != (char *) NULL)
    (void) fprintf(file,"  crop geometry: %.1024s\n",
      windows->image.crop_geometry);
  if (windows->image.pixmap == (Pixmap) NULL)
    (void) fprintf(file,"  type: X Image\n");
  else
    (void) fprintf(file,"  type: Pixmap\n");
  if (windows->image.shape)
    (void) fprintf(file,"  non-rectangular shape: True\n");
  else
    (void) fprintf(file,"  non-rectangular shape: False\n");
  if (windows->image.shared_memory)
    (void) fprintf(file,"  shared memory: True\n");
  else
    (void) fprintf(file,"  shared memory: False\n");
  (void) fprintf(file,"\n");
  if (resource_info->font != (char *) NULL)
    (void) fprintf(file,"Font: %.1024s\n\n",resource_info->font);
  if (resource_info->text_font != (char *) NULL)
    (void) fprintf(file,"Text font: %.1024s\n\n",resource_info->text_font);
  /*
    Write info about the undo cache to a file.
  */
  bytes=0;
  for (levels=0; undo_image != (Image *) NULL; levels++)
  {
    number_pixels=undo_image->list->columns*undo_image->list->rows;
    bytes+=number_pixels*sizeof(PixelPacket);
    undo_image=undo_image->previous;
  }
  (void) fprintf(file,"Undo Edit Cache\n  levels: %u\n",levels);
  (void) fprintf(file,"  bytes: %lumb\n",(bytes+(1 << 19)) >> 20);
  (void) fprintf(file,"  limit: %lumb\n\n",resource_info->undo_cache);
  /*
    Write info about the image to a file.
  */
  (void) DescribeImage(image,file,True);
  (void) fclose(file);
  text=(char *) FileToBlob(filename,&length,&image->exception);
  (void) LiberateTemporaryFile(filename);
  if (text == (char *) NULL)
    {
      MagickXNoticeWidget(display,windows,"MemoryAllocationFailed",
        "UnableToDisplayImageInfo");
      return;
    }
  textlist=StringToList(text);
  if (textlist != (char **) NULL)
    {
      char
        title[MaxTextExtent];

      /*
        Display information about the image in the Text View widget.
      */
      (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
      FormatString(title,"Image Info: %.1024s",image->filename);
      MagickXTextViewWidget(display,resource_info,windows,True,title,
        (char const **) textlist);
      for (i=0; textlist[i] != (char *) NULL; i++)
        MagickFreeMemory(textlist[i]);
      MagickFreeMemory(textlist);
    }
  MagickFreeMemory(text);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+     M a g i c k X D i t h e r I m a g e                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method XDitherImage dithers the reference image as required by the HP
%  Color Recovery algorithm.  The color values are quantized to 3 bits of red
%  and green, and 2 bits of blue (3/3/2) and can be used as indices into a
%  8-bit X standard colormap.
%
%  The format of the XDitherImage method is:
%
%      void XDitherImage(Image *image,XImage *ximage)
%
%  A description of each parameter follows:
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o ximage: Specifies a pointer to a XImage structure;  returned from
%      XCreateImage.
%
%
*/
static void MagickXDitherImage(Image *image,XImage *ximage)
{
  static const short int
    dither_red[2][16]=
    {
      {-16,  4, -1, 11,-14,  6, -3,  9,-15,  5, -2, 10,-13,  7, -4,  8},
      { 15, -5,  0,-12, 13, -7,  2,-10, 14, -6,  1,-11, 12, -8,  3, -9}
    },
    dither_green[2][16]=
    {
      { 11,-15,  7, -3,  8,-14,  4, -2, 10,-16,  6, -4,  9,-13,  5, -1},
      {-12, 14, -8,  2, -9, 13, -5,  1,-11, 15, -7,  3,-10, 12, -6,  0}
    },
    dither_blue[2][16]=
    {
      { -3,  9,-13,  7, -1, 11,-15,  5, -4,  8,-14,  6, -2, 10,-16,  4},
      {  2,-10, 12, -8,  0,-12, 14, -6,  3, -9, 13, -7,  1,-11, 15, -5}
    };

  PixelPacket
    color;

  int
    y;

  long
    value;

  register char
    *q;

  register const PixelPacket
    *p;

  register int
    i,
    j,
    x;

  unsigned int
    scanline_pad;

  register unsigned long
    pixel;

  unsigned char
    *blue_map[2][16],
    *green_map[2][16],
    *red_map[2][16];

  /*
    Allocate and initialize dither maps.
  */
  for (i=0; i < 2; i++)
    for (j=0; j < 16; j++)
    {
      red_map[i][j]=MagickAllocateArray(unsigned char *,256,sizeof(unsigned char));
      green_map[i][j]=MagickAllocateArray(unsigned char *,
                                          256,sizeof(unsigned char));
      blue_map[i][j]=MagickAllocateArray(unsigned char *,256,sizeof(unsigned char));
      if ((red_map[i][j] == (unsigned char *) NULL) ||
          (green_map[i][j] == (unsigned char *) NULL) ||
          (blue_map[i][j] == (unsigned char *) NULL))
        {
          MagickError3(ResourceLimitError,MemoryAllocationFailed,
            UnableToDitherImage);
          return;
        }
    }
  /*
    Initialize dither tables.
  */
  for (i=0; i < 2; i++)
    for (j=0; j < 16; j++)
      for (x=0; x < 256; x++)
      {
        value=x-16;
        if (x < 48)
          value=x/2+8;
        value+=dither_red[i][j];
        red_map[i][j][x]=(unsigned char)
          ((value < 0) ? 0 : (value > 255) ? 255 : value);
        value=x-16;
        if (x < 48)
          value=x/2+8;
        value+=dither_green[i][j];
        green_map[i][j][x]=(unsigned char)
          ((value < 0) ? 0 : (value > 255) ? 255 : value);
        value=x-32;
        if (x < 112)
          value=x/2+24;
        value+=(dither_blue[i][j] << 1);
        blue_map[i][j][x]=(unsigned char)
          ((value < 0) ? 0 : (value > 255) ? 255 : value);
      }
  /*
    Dither image.
  */
  scanline_pad=ximage->bytes_per_line-
    ((ximage->width*ximage->bits_per_pixel) >> 3);
  i=0;
  j=0;
  q=ximage->data;
  for (y=0; y < (long) image->rows; y++)
  {
    p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
    if (p == (const PixelPacket *) NULL)
      break;
    for (x=0; x < (long) image->columns; x++)
    {
      color.red=red_map[i][j][ScaleQuantumToChar(p->red)] << 8;
      color.green=green_map[i][j][ScaleQuantumToChar(p->green)] << 8;
      color.blue=blue_map[i][j][ScaleQuantumToChar(p->blue)] << 8;
      pixel=(unsigned long) ((color.red & 0xe0) |
        ((unsigned long) (color.green & 0xe0) >> 3) |
        ((unsigned long) (color.blue & 0xc0) >> 6));
      *q++=(unsigned char) pixel;
      p++;
      j++;
      if (j == 16)
        j=0;
    }
    q+=scanline_pad;
    i++;
    if (i == 2)
      i=0;
  }
  /*
    Free allocated memory.
  */
  for (i=0; i < 2; i++)
    for (j=0; j < 16; j++)
    {
      MagickFreeMemory(green_map[i][j]);
      MagickFreeMemory(blue_map[i][j]);
      MagickFreeMemory(red_map[i][j]);
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D r a w I m a g e                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXDrawImage draws a line on the image.
%
%  The format of the MagickXDrawImage method is:
%
%    status=MagickXDrawImage(display,pixel,draw_info,image)
%
%  A description of each parameter follows:
%
%    o status: Method MagickXDrawImage returns True if the image is
%      successfully drawd with text.  False is returned is there is a
%      memory shortage.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%    o draw_info: Specifies a pointer to a MagickXDrawInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%
*/
MagickExport unsigned int
MagickXDrawImage(Display *display,const MagickXPixelInfo *pixel,
                 MagickXDrawInfo *draw_info,Image *image)
{
  GC
    draw_context;

  Image
    *draw_image;

  int
    x,
    y;

  Pixmap
    draw_pixmap;

  register PixelPacket
    *q;

  unsigned int
    depth,
    height,
    matte,
    width;

  Window
    root_window;

  XGCValues
    context_values;

  XImage
    *draw_ximage;

  /*
    Initialize drawd image.
  */
  assert(display != (Display *) NULL);
  assert(pixel != (MagickXPixelInfo *) NULL);
  assert(draw_info != (MagickXDrawInfo *) NULL);
  assert(image != (Image *) NULL);
  /*
    Initialize drawd pixmap.
  */
  root_window=XRootWindow(display,XDefaultScreen(display));
  depth=XDefaultDepth(display,XDefaultScreen(display));
  draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
    draw_info->height,(int) depth);
  if (draw_pixmap == (Pixmap) NULL)
    return(False);
  /*
    Initialize graphics info.
  */
  context_values.background=(unsigned long) (~0);
  context_values.foreground=0;
  context_values.line_width=draw_info->line_width;
  draw_context=XCreateGC(display,root_window,GCBackground | GCForeground |
    GCLineWidth,&context_values);
  if (draw_context == (GC) NULL)
    return(False);
  /*
    Clear pixmap.
  */
  (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
    draw_info->height);
  /*
    Draw line to pixmap.
  */
  (void) XSetBackground(display,draw_context,0);
  (void) XSetForeground(display,draw_context,(unsigned long) (~0));
  (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
  (void) XSetStipple(display,draw_context,draw_info->stipple);
  switch (draw_info->element)
  {
    case PointElement:
    default:
    {
      (void) XDrawLines(display,draw_pixmap,draw_context,
        draw_info->coordinate_info,draw_info->number_coordinates,
        CoordModeOrigin);
      break;
    }
    case LineElement:
    {
      (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
        draw_info->line_info.y1,draw_info->line_info.x2,
        draw_info->line_info.y2);
      break;
    }
    case RectangleElement:
    {
      (void) XDrawRectangle(display,draw_pixmap,draw_context,
        (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
        (unsigned int) draw_info->rectangle_info.width,
        (unsigned int) draw_info->rectangle_info.height);
      break;
    }
    case FillRectangleElement:
    {
      (void) XFillRectangle(display,draw_pixmap,draw_context,
        (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
        (unsigned int) draw_info->rectangle_info.width,
        (unsigned int) draw_info->rectangle_info.height);
      break;
    }
    case CircleElement:
    case EllipseElement:
    {
      (void) XDrawArc(display,draw_pixmap,draw_context,
        (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
        (unsigned int) draw_info->rectangle_info.width,
        (unsigned int) draw_info->rectangle_info.height,0,360*64);
      break;
    }
    case FillCircleElement:
    case FillEllipseElement:
    {
      (void) XFillArc(display,draw_pixmap,draw_context,
        (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
        (unsigned int) draw_info->rectangle_info.width,
        (unsigned int) draw_info->rectangle_info.height,0,360*64);
      break;
    }
    case PolygonElement:
    {
      XPoint
        *coordinate_info;

      coordinate_info=draw_info->coordinate_info;
      (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
        draw_info->number_coordinates,CoordModeOrigin);
      (void) XDrawLine(display,draw_pixmap,draw_context,
        coordinate_info[draw_info->number_coordinates-1].x,
        coordinate_info[draw_info->number_coordinates-1].y,
        coordinate_info[0].x,coordinate_info[0].y);
      break;
    }
    case FillPolygonElement:
    {
      (void) XFillPolygon(display,draw_pixmap,draw_context,
        draw_info->coordinate_info,draw_info->number_coordinates,Complex,
        CoordModeOrigin);
      break;
    }
  }
  (void) XFreeGC(display,draw_context);
  /*
    Initialize X image.
  */
  draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
    draw_info->height,AllPlanes,ZPixmap);
  if (draw_ximage == (XImage *) NULL)
    return(False);
  (void) XFreePixmap(display,draw_pixmap);
  /*
    Initialize draw image.
  */
  draw_image=AllocateImage((ImageInfo *) NULL);
  if (draw_image == (Image *) NULL)
    return(False);
  draw_image->columns=draw_info->width;
  draw_image->rows=draw_info->height;
  /*
    Transfer drawn X image to image.
  */
  width=(unsigned int) image->columns;
  height=(unsigned int) image->rows;
  x=0;
  y=0;
  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
  (void) AcquireOnePixelByReference(image,&draw_image->background_color,x,y,&image->exception);
  (void) SetImageType(draw_image,TrueColorMatteType);
  for (y=0; y < (long) draw_image->rows; y++)
  {
    q=SetImagePixels(draw_image,0,y,draw_image->columns,1);
    if (q == (PixelPacket *) NULL)
      break;
    for (x=0; x < (long) draw_image->columns; x++)
    {
      if (XGetPixel(draw_ximage,x,y) == 0)
        {
          /*
            Set this pixel to the background color.
          */
          *q=draw_image->background_color;
          q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
            TransparentOpacity : OpaqueOpacity);
        }
      else
        {
          /*
            Set this pixel to the pen color.
          */
          q->red=ScaleShortToQuantum(pixel->pen_color.red);
          q->green=ScaleShortToQuantum(pixel->pen_color.green);
          q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
          q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
            OpaqueOpacity : TransparentOpacity);
        }
      q++;
    }
    if (!SyncImagePixels(draw_image))
      break;
  }
  XDestroyImage(draw_ximage);
  draw_ximage=(XImage *) NULL;
  /*
    Determine draw geometry.
  */
  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
  if ((width != (unsigned int) draw_image->columns) ||
      (height != (unsigned int) draw_image->rows))
    {
      char
        image_geometry[MaxTextExtent];

      /*
        Scale image.
      */
      FormatString(image_geometry,"%ux%u",width,height);
      TransformImage(&draw_image,(char *) NULL,image_geometry);
    }
  if (draw_info->degrees != 0.0)
    {
      double
        normalized_degrees;

      Image
        *rotate_image;

      int
        rotations;

      /*
        Rotate image.
      */
      rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
      if (rotate_image == (Image *) NULL)
        return(False);
      DestroyImage(draw_image);
      draw_image=rotate_image;
      /*
        Annotation is relative to the degree of rotation.
      */
      normalized_degrees=draw_info->degrees;
      while (normalized_degrees < -45.0)
        normalized_degrees+=360.0;
      for (rotations=0; normalized_degrees > 45.0; rotations++)
        normalized_degrees-=90.0;
      switch (rotations % 4)
      {
        default:
        case 0:
          break;
        case 1:
        {
          /*
            Rotate 90 degrees.
          */
          x=x-(int) draw_image->columns/2;
          y=y+(int) draw_image->columns/2;
          break;
        }
        case 2:
        {
          /*
            Rotate 180 degrees.
          */
          x=x-(int) draw_image->columns;
          break;
        }
        case 3:
        {
          /*
            Rotate 270 degrees.
          */
          x=x-(int) draw_image->columns/2;
          y=y-(int) (draw_image->rows-(draw_image->columns/2));
          break;
        }
      }
    }
  /*
    Composite text onto the image.
  */
  for (y=0; y < (long) draw_image->rows; y++)
  {
    q=GetImagePixels(draw_image,0,y,draw_image->columns,1);
    if (q == (PixelPacket *) NULL)
      break;
    for (x=0; x < (long) draw_image->columns; x++)
    {
      if (q->opacity != TransparentOpacity)
        q->opacity=OpaqueOpacity;
      q++;
    }
    if (!SyncImagePixels(draw_image))
      break;
  }
  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
  if (draw_info->stencil == TransparentStencil)
    (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,x,y);
  else
    {
      matte=image->matte;
      (void) CompositeImage(image,OverCompositeOp,draw_image,x,y);
      image->matte=matte;
    }
  DestroyImage(draw_image);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X E r r o r                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXError ignores BadWindow errors for XQueryTree and
%  XGetWindowAttributes, and ignores BadDrawable errors for XGetGeometry, and
%  ignores BadValue errors for XQueryColor.  It returns False in those cases.
%  Otherwise it returns True.
%
%  The format of the MagickXError function is:
%
%      MagickXError(display,error)
%
%  A description of each parameter follows:
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o error: Specifies the error event.
%
%
*/

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

MagickExport int
MagickXError(Display *display,XErrorEvent *error)
{
  assert(display != (Display *) NULL);
  assert(error != (XErrorEvent *) NULL);
  xerror_alert=True;
  switch (error->request_code)
  {
    case X_GetGeometry:
    {
      if (error->error_code == BadDrawable)
        return(False);
      break;
    }
    case X_GetWindowAttributes:
    case X_QueryTree:
    {
      if (error->error_code == BadWindow)
        return(False);
      break;
    }
    case X_QueryColors:
    {
      if (error->error_code == BadValue)
        return(False);
      break;
    }
  }
  return(True);
}

#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X F r e e R e s o u r c e s                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXFreeResources frees X11 resources.
%
%  The format of the MagickXFreeResources method is:
%
%      void MagickXFreeResources(Display *display,XVisualInfo *visual_info,
%         XStandardColormap *map_info,MagickXPixelInfo *pixel,
%         XFontStruct *font_info,MagickXResourceInfo *resource_info,
%         MagickXWindowInfo *window_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o map_info: If map_type is specified, this structure is initialized
%      with info from the Standard Colormap.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%    o font_info: Specifies a pointer to a XFontStruct structure.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o window_info: Specifies a pointer to a X11 MagickXWindowInfo structure.
%
%
*/
MagickExport void
MagickXFreeResources(Display *display,
                     XVisualInfo *visual_info,
                     XStandardColormap *map_info,
                     MagickXPixelInfo *pixel,
                     XFontStruct *font_info,
                     MagickXResourceInfo *resource_info,
                     MagickXWindowInfo *window_info)
{
  assert(display != (Display *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  if (window_info != (MagickXWindowInfo *) NULL)
    {
      /*
        Free X image.
      */
      if (window_info->ximage != (XImage *) NULL)
        {
          XDestroyImage(window_info->ximage);
          window_info->ximage=(XImage *) NULL;
        }
      if (window_info->id != (Window) NULL)
        {
          /*
            Free destroy window and free cursors.
          */
          if (window_info->id != XRootWindow(display,visual_info->screen))
            (void) XDestroyWindow(display,window_info->id);
          if (window_info->annotate_context != (GC) NULL)
            (void) XFreeGC(display,window_info->annotate_context);
          if (window_info->highlight_context != (GC) NULL)
            (void) XFreeGC(display,window_info->highlight_context);
          if (window_info->widget_context != (GC) NULL)
            (void) XFreeGC(display,window_info->widget_context);
          (void) XFreeCursor(display,window_info->cursor);
          (void) XFreeCursor(display,window_info->busy_cursor);
        }
    }
  /*
    Free font.
  */
  if (font_info != (XFontStruct *) NULL)
    (void) XFreeFont(display,font_info);
  if (map_info != (XStandardColormap *) NULL)
    {
      /*
        Free X Standard Colormap.
      */
      if (resource_info->map_type == (char *) NULL)
        (void) MagickXFreeStandardColormap(display,visual_info,map_info,pixel);
      (void) XFree((void *) map_info);
    }
  /*
    Free X visual info.
  */
  if (visual_info != (XVisualInfo *) NULL)
    (void) XFree((void *) visual_info);
  if (resource_info->close_server)
    (void) XCloseDisplay(display);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X F r e e S t a n d a r d C o l o r m a p                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXFreeStandardColormap frees an X11 colormap.
%
%  The format of the MagickXFreeStandardColormap method is:
%
%      void MagickXFreeStandardColormap(Display *display,
%        const XVisualInfo *visual_info,XStandardColormap *map_info,
%        MagickXPixelInfo *pixel)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o map_info: If map_type is specified, this structure is initialized
%      with info from the Standard Colormap.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%
*/
MagickExport void
MagickXFreeStandardColormap(Display *display,
                            const XVisualInfo *visual_info,
                            XStandardColormap *map_info,
                            MagickXPixelInfo *pixel)
{
  /*
    Free colormap.
  */
  assert(display != (Display *) NULL);
  assert(visual_info != (XVisualInfo *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  (void) XFlush(display);
  if (map_info->colormap != (Colormap) NULL)
    {
      if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
        (void) XFreeColormap(display,map_info->colormap);
      else
        if (pixel != (MagickXPixelInfo *) NULL)
          if ((visual_info->class != TrueColor) &&
              (visual_info->class != DirectColor))
            (void) XFreeColors(display,map_info->colormap,pixel->pixels,
              (int) pixel->colors,0);
    }
  map_info->colormap=(Colormap) NULL;
  if (pixel != (MagickXPixelInfo *) NULL)
    {
      if (pixel->pixels != (unsigned long *) NULL)
        MagickFreeMemory(pixel->pixels);
      pixel->pixels=(unsigned long *) NULL;
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t A n n o t a t e I n f o                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetAnnotateInfo initializes the AnnotateInfo structure.
%
%  The format of the MagickXGetAnnotateInfo method is:
%
%      void MagickXGetAnnotateInfo(MagickXAnnotateInfo *annotate_info)
%
%  A description of each parameter follows:
%
%    o annotate_info: Specifies a pointer to a MagickXAnnotateInfo structure.
%
%
*/
MagickExport void
MagickXGetAnnotateInfo(MagickXAnnotateInfo *annotate_info)
{
  /*
    Initialize annotate structure.
  */
  assert(annotate_info != (MagickXAnnotateInfo *) NULL);
  annotate_info->x=0;
  annotate_info->y=0;
  annotate_info->width=0;
  annotate_info->height=0;
  annotate_info->stencil=ForegroundStencil;
  annotate_info->degrees=0.0;
  annotate_info->font_info=(XFontStruct *) NULL;
  annotate_info->text=(char *) NULL;
  *annotate_info->geometry='\0';
  annotate_info->previous=(MagickXAnnotateInfo *) NULL;
  annotate_info->next=(MagickXAnnotateInfo *) NULL;
  (void) XSupportsLocale();
  (void) XSetLocaleModifiers("");
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t M a p I n f o                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetMapInfo initializes the XStandardColormap structure.
%
%  The format of the XStandardColormap method is:
%
%      void MagickXGetMapInfo(const XVisualInfo *visual_info,
%        const Colormap colormap,XStandardColormap *map_info)
%
%  A description of each parameter follows:
%
%    o colormap: Specifies the ID of the X server colormap.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o map_info: Specifies a pointer to a X11 XStandardColormap structure.
%
%
*/
MagickExport void
MagickXGetMapInfo(const XVisualInfo *visual_info,
                  const Colormap colormap,XStandardColormap *map_info)
{
  /*
    Initialize map info.
  */
  assert(visual_info != (XVisualInfo *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  map_info->colormap=colormap;
  map_info->red_max=visual_info->red_mask;
  map_info->red_mult=map_info->red_max != 0 ? 1 : 0;
  if (map_info->red_max != 0)
    while ((map_info->red_max & 0x01) == 0)
    {
      map_info->red_max>>=1;
      map_info->red_mult<<=1;
    }
  map_info->green_max=visual_info->green_mask;
  map_info->green_mult=map_info->green_max != 0 ? 1 : 0;
  if (map_info->green_max != 0)
    while ((map_info->green_max & 0x01) == 0)
    {
      map_info->green_max>>=1;
      map_info->green_mult<<=1;
    }
  map_info->blue_max=visual_info->blue_mask;
  map_info->blue_mult=map_info->blue_max != 0 ? 1 : 0;
  if (map_info->blue_max != 0)
    while ((map_info->blue_max & 0x01) == 0)
    {
      map_info->blue_max>>=1;
      map_info->blue_mult<<=1;
    }
  map_info->base_pixel=0;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t I m a g e I n f o                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetImportInfo initializes the MagickXImportInfo structure.
%
%  The format of the MagickXGetImportInfo method is:
%
%      void MagickXGetImportInfo(MagickXImportInfo *ximage_info)
%
%  A description of each parameter follows:
%
%    o ximage_info: Specifies a pointer to a ImageInfo structure.
%
%
*/
MagickExport void
MagickXGetImportInfo(MagickXImportInfo *ximage_info)
{
  assert(ximage_info != (MagickXImportInfo *) NULL);
  ximage_info->frame=False;
  ximage_info->borders=False;
  ximage_info->screen=False;
  ximage_info->descend=True;
  ximage_info->silent=False;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t P i x e l P a c k e t                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetPixelPacket initializes the PixelPacket structure.
%
%  The format of the MagickXGetPixelPacket method is:
%
%      void MagickXGetPixelPacket(Display *display,
%        const XVisualInfo *visual_info,const XStandardColormap *map_info,
%        const MagickXResourceInfo *resource_info,Image *image,
%        MagickXPixelInfo *pixel)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o map_info: If map_type is specified, this structure is initialized
%      with info from the Standard Colormap.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%
*/
MagickExport void
MagickXGetPixelPacket(Display *display,
                      const XVisualInfo *visual_info,
                      const XStandardColormap *map_info,
                      const MagickXResourceInfo *resource_info,
                      Image *image,
                      MagickXPixelInfo *pixel)
{
  static const char
    *PenColors[MaxNumberPens]=
    {
      "#000000000000",  /* black */
      "#00000000ffff",  /* blue */
      "#0000ffffffff",  /* cyan */
      "#0000ffff0000",  /* green */
      "#bdbdbdbdbdbd",  /* gray */
      "#ffff00000000",  /* red */
      "#ffff0000ffff",  /* magenta */
      "#ffffffff0000",  /* yellow */
      "#ffffffffffff",  /* white */
      "#bdbdbdbdbdbd",  /* gray */
      "#bdbdbdbdbdbd"   /* gray */
    };

  Colormap
    colormap;

  int
    status;

  register long
    i;

  unsigned int
    packets;

  /*
    Initialize pixel info.
  */
  assert(display != (Display *) NULL);
  assert(visual_info != (XVisualInfo *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(pixel != (MagickXPixelInfo *) NULL);
  pixel->colors=0;
  if (image != (Image *) NULL)
    if (image->storage_class == PseudoClass)
      pixel->colors=image->colors;
  packets=Max((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
  if (pixel->pixels != (unsigned long *) NULL)
    MagickFreeMemory(pixel->pixels);
  pixel->pixels=
    MagickAllocateArray(unsigned long *,packets,sizeof(unsigned long));
  if (pixel->pixels == (unsigned long *) NULL)
    MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
      MagickMsg(XServerFatalError,UnableToGetPixelInfo));
  /*
    Set foreground color.
  */
  colormap=map_info->colormap;
  (void) XParseColor(display,colormap,(char *) ForegroundColor,
    &pixel->foreground_color);
  status=XParseColor(display,colormap,resource_info->foreground_color,
    &pixel->foreground_color);
  if (status == 0)
    MagickError(XServerError,ColorIsNotKnownToServer,
      resource_info->foreground_color);
  pixel->foreground_color.pixel=
    MagickXStandardPixel(map_info,&pixel->foreground_color);
  pixel->foreground_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set background color.
  */
  (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",
                     &pixel->background_color);
  status=XParseColor(display,colormap,resource_info->background_color,
    &pixel->background_color);
  if (status == 0)
    MagickError(XServerError,ColorIsNotKnownToServer,
      resource_info->background_color);
  pixel->background_color.pixel=
    MagickXStandardPixel(map_info,&pixel->background_color);
  pixel->background_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set border color.
  */
  (void) XParseColor(display,colormap,(char *) BorderColor,
    &pixel->border_color);
  status=XParseColor(display,colormap,resource_info->border_color,
    &pixel->border_color);
  if (status == 0)
    MagickError(XServerError,ColorIsNotKnownToServer,
      resource_info->border_color);
  pixel->border_color.pixel=MagickXStandardPixel(map_info,&pixel->border_color);
  pixel->border_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set matte color.
  */
  pixel->matte_color=pixel->background_color;
  if (resource_info->matte_color != (char *) NULL)
    {
      /*
        Matte color is specified as a X resource or command line argument.
      */
      status=XParseColor(display,colormap,resource_info->matte_color,
        &pixel->matte_color);
      if (status == 0)
        MagickError(XServerError,ColorIsNotKnownToServer,
          resource_info->matte_color);
      pixel->matte_color.pixel=MagickXStandardPixel(map_info,&pixel->matte_color);
      pixel->matte_color.flags=DoRed | DoGreen | DoBlue;
    }
  /*
    Set highlight color.
  */
  pixel->highlight_color.red=(unsigned short) (((double)
     pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
     (ScaleQuantumToShort((double) MaxRGB-HighlightModulate)));
  pixel->highlight_color.green=(unsigned short) (((double)
     pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
     (ScaleQuantumToShort((double) MaxRGB-HighlightModulate)));
  pixel->highlight_color.blue=(unsigned short) (((double)
     pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
     (ScaleQuantumToShort((double) MaxRGB-HighlightModulate)));
  pixel->highlight_color.pixel=MagickXStandardPixel(map_info,&pixel->highlight_color);
  pixel->highlight_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set shadow color.
  */
  pixel->shadow_color.red=(unsigned short) (((double)
    pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
  pixel->shadow_color.green=(unsigned short) (((double)
    pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
  pixel->shadow_color.blue=(unsigned short) (((double)
    pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
  pixel->shadow_color.pixel=MagickXStandardPixel(map_info,&pixel->shadow_color);
  pixel->shadow_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set depth color.
  */
  pixel->depth_color.red=(unsigned short) (((double)
    pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
  pixel->depth_color.green=(unsigned short) (((double)
    pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
  pixel->depth_color.blue=(unsigned short) (((double)
    pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
  pixel->depth_color.pixel=MagickXStandardPixel(map_info,&pixel->depth_color);
  pixel->depth_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set trough color.
  */
  pixel->trough_color.red=(unsigned short) (((double)
    pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
  pixel->trough_color.green=(unsigned short) (((double)
    pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
  pixel->trough_color.blue=(unsigned short) (((double)
    pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
  pixel->trough_color.pixel=MagickXStandardPixel(map_info,&pixel->trough_color);
  pixel->trough_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set pen color.
  */
  for (i=0; i < MaxNumberPens; i++)
  {
    (void) XParseColor(display,colormap,(char *) PenColors[i],
      &pixel->pen_colors[i]);
    status=XParseColor(display,colormap,resource_info->pen_colors[i],
      &pixel->pen_colors[i]);
    if (status == 0)
      MagickError(XServerError,ColorIsNotKnownToServer,
        resource_info->pen_colors[i]);
    pixel->pen_colors[i].pixel=MagickXStandardPixel(map_info,&pixel->pen_colors[i]);
    pixel->pen_colors[i].flags=DoRed | DoGreen | DoBlue;
  }
  pixel->box_color=pixel->background_color;
  pixel->pen_color=pixel->foreground_color;
  pixel->box_index=0;
  pixel->pen_index=1;
  if (image != (Image *) NULL)
    {
      if (resource_info->gamma_correct && (image->gamma != 0.0))
        {
          int
            count;

          /*
            Initialize map relative to display and image gamma.
          */
          count=sscanf(resource_info->display_gamma,"%lf%*[,/]%lf%*[,/]%lf",
            &red_gamma,&green_gamma,&blue_gamma);
          if (count == 1)
            {
              green_gamma=red_gamma;
              blue_gamma=red_gamma;
            }
          red_gamma*=image->gamma;
          green_gamma*=image->gamma;
          blue_gamma*=image->gamma;
        }
      if (image->storage_class == PseudoClass)
        {
          /*
            Initialize pixel array for images of type PseudoClass.
          */
          for (i=0; i < (long) image->colors; i++)
            pixel->pixels[i]=
              MagickXGammaPixel(map_info,image->colormap+i);
          for (i=0; i < MaxNumberPens; i++)
            pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
          pixel->colors+=MaxNumberPens;
        }
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t R e s o u r c e C l a s s                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetResourceClass queries the X server for the specified
%  resource name or class.  If the resource name or class is not defined
%  in the database, the supplied default value is returned.
%
%  The format of the MagickXGetResourceClass method is:
%
%      char *MagickXGetResourceClass(XrmDatabase database,
%        const char *client_name,const char *keyword,char *resource_default)
%
%  A description of each parameter follows:
%
%    o value: Method MagickXGetResourceClass returns the resource value
%      associated with the name or class.  If none is found, the supplied
%      default value is returned.
%
%    o database: Specifies a resource database; returned from
%      XrmGetStringDatabase.
%
%    o client_name:  Specifies the application name used to retrieve resource
%      info from the X server database.
%
%    o keyword: Specifies the keyword of the value being retrieved.
%
%    o resource_default: Specifies the default value to return if the query
%      fails to find the specified keyword/class.
%
%
*/
MagickExport char *
MagickXGetResourceClass(XrmDatabase database,
                        const char *client_name,const char *keyword,
                        char *resource_default)
{
  char
    resource_class[MaxTextExtent],
    resource_name[MaxTextExtent];

  int
    status;

  static char
    *resource_type;

  XrmValue
    resource_value;

  if (database == (XrmDatabase) NULL)
    return(resource_default);
  *resource_name='\0';
  *resource_class='\0';
  if (keyword != (char *) NULL)
    {
      unsigned char
        c,
        k;

      /*
        Initialize resource keyword and class.
      */
      FormatString(resource_name,"%.1024s.%.1024s",client_name,keyword);
      c=(*client_name);
      if ((c >= XK_a) && (c <= XK_z))
        c-=(XK_a-XK_A);
      else
        if ((c >= XK_agrave) && (c <= XK_odiaeresis))
          c-=(XK_agrave-XK_Agrave);
        else
          if ((c >= XK_oslash) && (c <= XK_thorn))
            c-=(XK_oslash-XK_Ooblique);
      k=(*keyword);
      if ((k >= XK_a) && (k <= XK_z))
        k-=(XK_a-XK_A);
      else
        if ((k >= XK_agrave) && (k <= XK_odiaeresis))
          k-=(XK_agrave-XK_Agrave);
        else
          if ((k >= XK_oslash) && (k <= XK_thorn))
            k-=(XK_oslash-XK_Ooblique);
      FormatString(resource_class,"%c%.1024s.%c%.1024s",c,client_name+1,k,
        keyword+1);
    }
  status=XrmGetResource(database,resource_name,resource_class,&resource_type,
    &resource_value);
  if (status == False)
    return(resource_default);
  return(resource_value.addr);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t R e s o u r c e D a t a b a s e                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetResourceDatabase creates a new resource database and
%  initializes it.
%
%  The format of the MagickXGetResourceDatabase method is:
%
%      XrmDatabase MagickXGetResourceDatabase(Display *display,
%        const char *client_name)
%
%  A description of each parameter follows:
%
%    o database: Method MagickXGetResourceDatabase returns the database after
%      it is initialized.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o client_name:  Specifies the application name used to retrieve resource
%      info from the X server database.
%
%
*/
MagickExport XrmDatabase
MagickXGetResourceDatabase(Display *display,
                           const char *client_name)
{
  char
    filename[MaxTextExtent];

  register const char
    *p;

  unsigned char
    c;

  XrmDatabase
    resource_database,
    server_database;

  if (display == (Display *) NULL)
    return((XrmDatabase) NULL);
  assert(client_name != (char *) NULL);
  /*
    Initialize resource database.
  */
  XrmInitialize();
  (void) XGetDefault(display,(char *) client_name,(char *) "dummy");
  resource_database=XrmGetDatabase(display);
  /*
    Combine application database.
  */
  if (client_name != (char *) NULL)
    {
      /*
        Get basename of client.
      */
      p=client_name+(strlen(client_name)-1);
      while ((p > client_name) && (*p != '/'))
        p--;
      if (*p == '/')
        client_name=p+1;
    }
  c=(*client_name);
  if ((c >= XK_a) && (c <= XK_z))
    c-=(XK_a-XK_A);
  else
    if ((c >= XK_agrave) && (c <= XK_odiaeresis))
      c-=(XK_agrave-XK_Agrave);
    else
      if ((c >= XK_oslash) && (c <= XK_thorn))
        c-=(XK_oslash-XK_Ooblique);
#if defined(ApplicationDefaults)
  FormatString(filename,"%.1024s%c%.1024s",ApplicationDefaults,c,client_name+1);
  (void) XrmCombineFileDatabase(filename,&resource_database,False);
#endif
  if (XResourceManagerString(display) != (char *) NULL)
    {
      /*
        Combine server database.
      */
      server_database=XrmGetStringDatabase(XResourceManagerString(display));
      XrmCombineDatabase(server_database,&resource_database,False);
    }
  /*
    Merge user preferences database.
  */
#if defined(PreferencesDefaults)
  FormatString(filename,"%.1024s%.1024src",PreferencesDefaults,client_name);
  ExpandFilename(filename);
  (void) XrmCombineFileDatabase(filename,&resource_database,False);
#endif
  return(resource_database);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t R e s o u r c e I n f o                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetResourceInfo initializes the ResourceInfo structure.
%
%  The format of the MagickXGetResourceInfo method is:
%
%      void MagickXGetResourceInfo(XrmDatabase database,char *client_name,
%        MagickXResourceInfo *resource_info)
%
%  A description of each parameter follows:
%
%    o database: Specifies a resource database; returned from
%      XrmGetStringDatabase.
%
%    o client_name:  Specifies the application name used to retrieve
%      resource info from the X server database.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%
*/
MagickExport void
MagickXGetResourceInfo(XrmDatabase database,const char *client_name,
                       MagickXResourceInfo *resource_info)
{
  char
    *resource_value;

  /*
    Initialize resource info fields.
  */
  assert(resource_info != (MagickXResourceInfo *) NULL);
  (void) memset(resource_info,0,sizeof(MagickXResourceInfo));
  resource_info->resource_database=database;
  resource_info->image_info=CloneImageInfo((ImageInfo *) NULL);
  resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
  resource_info->close_server=True;
  resource_info->client_name=AllocateString(client_name);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "backdrop",
    (char *) "False");
  resource_info->backdrop=MagickIsTrue(resource_value);
  resource_info->background_color=MagickXGetResourceInstance(database,client_name,
    (char *) "background","#d6d6d6d6d6d6");
  resource_info->border_color=MagickXGetResourceInstance(database,client_name,
    (char *) "borderColor",BorderColor);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "borderWidth",
    (char *) "2");
  resource_info->border_width=MagickAtoI(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "colormap",
    (char *) "shared");
  resource_info->colormap=UndefinedColormap;
  if (LocaleCompare("private",resource_value) == 0)
    resource_info->colormap=PrivateColormap;
  if (LocaleCompare("shared",resource_value) == 0)
    resource_info->colormap=SharedColormap;
  if (resource_info->colormap == UndefinedColormap)
    MagickError(OptionError,UnrecognizedColormapType,resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,
    (char *) "colorRecovery",(char *) "False");
  resource_info->color_recovery=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "confirmExit",
    (char *) "False");
  resource_info->confirm_exit=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "delay",
    (char *) "1");
  resource_info->delay=MagickAtoI(resource_value);
  resource_info->display_gamma=MagickXGetResourceClass(database,client_name,
    (char *) "displayGamma",(char *) "2.2");
  resource_value=MagickXGetResourceClass(database,client_name,
    (char *) "displayWarnings",(char *) "True");
  resource_info->display_warnings=MagickIsTrue(resource_value);
  resource_info->font=MagickXGetResourceClass(database,client_name,(char *) "font",
    (char *) "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1");
  resource_info->font=MagickXGetResourceClass(database,client_name,
    (char *) "fontList",resource_info->font);
  resource_info->font_name[0]=MagickXGetResourceClass(database,client_name,
    (char *) "font1",(char *) "fixed");
  resource_info->font_name[1]=MagickXGetResourceClass(database,client_name,
    (char *) "font2",(char *) "variable");
  resource_info->font_name[2]=MagickXGetResourceClass(database,client_name,
    (char *) "font3",(char *) "5x8");
  resource_info->font_name[3]=MagickXGetResourceClass(database,client_name,
    (char *) "font4",(char *) "6x10");
  resource_info->font_name[4]=MagickXGetResourceClass(database,client_name,
    (char *) "font5",(char *) "7x13bold");
  resource_info->font_name[5]=MagickXGetResourceClass(database,client_name,
    (char *) "font6",(char *) "8x13bold");
  resource_info->font_name[6]=MagickXGetResourceClass(database,client_name,
    (char *) "font7",(char *) "9x15bold");
  resource_info->font_name[7]=MagickXGetResourceClass(database,client_name,
    (char *) "font8",(char *) "10x20");
  resource_info->font_name[8]=MagickXGetResourceClass(database,client_name,
    (char *) "font9",(char *) "12x24");
  resource_info->font_name[9]=MagickXGetResourceClass(database,client_name,
    (char *) "font0",(char *) "fixed");
  resource_info->font_name[10]=MagickXGetResourceClass(database,client_name,
    (char *) "font0",(char *) "fixed");
  resource_info->foreground_color=MagickXGetResourceInstance(database,client_name,
    "foreground",ForegroundColor);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "gammaCorrect",
    (char *) "True");
  resource_info->gamma_correct=MagickIsTrue(resource_value);
  resource_info->image_geometry=MagickXGetResourceClass(database,client_name,
    (char *) "geometry",(char *) NULL);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "gravity",
    (char *) "Center");
  resource_info->gravity=(-1);
  if (LocaleCompare("Forget",resource_value) == 0)
    resource_info->gravity=ForgetGravity;
  if (LocaleCompare("NorthWest",resource_value) == 0)
    resource_info->gravity=NorthWestGravity;
  if (LocaleCompare("North",resource_value) == 0)
    resource_info->gravity=NorthGravity;
  if (LocaleCompare("NorthEast",resource_value) == 0)
    resource_info->gravity=NorthEastGravity;
  if (LocaleCompare("West",resource_value) == 0)
    resource_info->gravity=WestGravity;
  if (LocaleCompare("Center",resource_value) == 0)
    resource_info->gravity=CenterGravity;
  if (LocaleCompare("East",resource_value) == 0)
    resource_info->gravity=EastGravity;
  if (LocaleCompare("SouthWest",resource_value) == 0)
    resource_info->gravity=SouthWestGravity;
  if (LocaleCompare("South",resource_value) == 0)
    resource_info->gravity=SouthGravity;
  if (LocaleCompare("SouthEast",resource_value) == 0)
    resource_info->gravity=SouthEastGravity;
  if (LocaleCompare("Static",resource_value) == 0)
    resource_info->gravity=StaticGravity;
  if (resource_info->gravity == (-1))
    {
      MagickError(OptionError,UnrecognizedGravityType,resource_value);
      resource_info->gravity=CenterGravity;
    }
  (void) getcwd(resource_info->home_directory,MaxTextExtent-1);
  resource_info->icon_geometry=MagickXGetResourceClass(database,client_name,
    (char *) "iconGeometry",(char *) NULL);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "iconic",
    (char *) "False");
  resource_info->iconic=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "immutable",
    LocaleCompare(client_name,(char *) "PerlMagick") == 0 ? (char *) "True" :
    (char *) "False");
  resource_info->immutable=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "magnify",
    (char *) "3");
  resource_info->magnify=MagickAtoI(resource_value);
  resource_info->map_type=MagickXGetResourceClass(database,client_name,(char *) "map",
    (char *) NULL);
  resource_info->matte_color=MagickXGetResourceInstance(database,client_name,
    (char *) "mattecolor",(char *) NULL);
  resource_info->name=MagickXGetResourceClass(database,client_name,(char *) "name",
    (char *) NULL);
  resource_info->pen_colors[0]=MagickXGetResourceClass(database,client_name,
    (char *) "pen1",(char *) "black");
  resource_info->pen_colors[1]=MagickXGetResourceClass(database,client_name,
    (char *) "pen2",(char *) "blue");
  resource_info->pen_colors[2]=MagickXGetResourceClass(database,client_name,
    (char *) "pen3",(char *) "cyan");
  resource_info->pen_colors[3]=MagickXGetResourceClass(database,client_name,
    (char *) "pen4",(char *) "green");
  resource_info->pen_colors[4]=MagickXGetResourceClass(database,client_name,
    (char *) "pen5",(char *) "gray");
  resource_info->pen_colors[5]=MagickXGetResourceClass(database,client_name,
    (char *) "pen6",(char *) "red");
  resource_info->pen_colors[6]=MagickXGetResourceClass(database,client_name,
    (char *) "pen7",(char *) "magenta");
  resource_info->pen_colors[7]=MagickXGetResourceClass(database,client_name,
    (char *) "pen8",(char *) "yellow");
  resource_info->pen_colors[8]=MagickXGetResourceClass(database,client_name,
    (char *) "pen9",(char *) "white");
  resource_info->pen_colors[9]=MagickXGetResourceClass(database,client_name,
    (char *) "pen0",(char *) "gray");
  resource_info->pen_colors[10]=MagickXGetResourceClass(database,client_name,
    (char *) "pen0",(char *) "gray");
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "pause",
    (char *) "0");
  resource_info->pause=MagickAtoI(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "quantum",
    (char *) "1");
  resource_info->quantum=MagickAtoI(resource_value);
  resource_info->text_font=MagickXGetResourceClass(database,client_name,(char *)
    "font",(char *) "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-iso8859-1");
  resource_info->text_font=MagickXGetResourceClass(database,client_name,
    (char *) "textFontList",resource_info->text_font);
  resource_info->title=MagickXGetResourceClass(database,client_name,(char *) "title",
    (char *) NULL);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "undoCache",
    (char *) "16");
  resource_info->undo_cache=MagickAtoL(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "update",
    (char *) "False");
  resource_info->update=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "usePixmap",
    (char *) "False");
  resource_info->use_pixmap=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "sharedMemory",
    (char *) "True");
  resource_info->use_shared_memory=MagickIsTrue(resource_value);
  resource_info->visual_type=MagickXGetResourceClass(database,client_name,
    (char *) "visual",(char *) NULL);
  resource_info->window_group=MagickXGetResourceClass(database,client_name,
    (char *) "windowGroup",(char *) NULL);
  resource_info->window_id=MagickXGetResourceClass(database,client_name,
    (char *) "window",(char *) NULL);
  resource_info->write_filename=MagickXGetResourceClass(database,client_name,
    (char *) "writeFilename",(char *) NULL);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t R e s o u r c e I n s t a n c e                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetResourceInstance queries the X server for the specified
%  resource name.  If the resource name is not defined in the database, the
%  supplied default value is returned.
%
%  The format of the MagickXGetResourceInstance method is:
%
%      char *MagickXGetResourceInstance(XrmDatabase database,
%        const char *client_name,const char *keyword,
%        const char *resource_default)
%
%  A description of each parameter follows:
%
%    o value: Method MagickXGetResourceInstance returns the resource value
%      associated with the name or class.  If none is found, the supplied
%      default value is returned.
%
%    o database: Specifies a resource database; returned from
%      XrmGetStringDatabase.
%
%    o client_name:  Specifies the application name used to retrieve
%      resource info from the X server database.
%
%    o keyword: Specifies the keyword of the value being retrieved.
%
%    o resource_default: Specifies the default value to return if the query
%      fails to find the specified keyword/class.
%
%
*/
MagickExport char *
MagickXGetResourceInstance(XrmDatabase database,
                           const char *client_name,
                           const char *keyword,
                           const char *resource_default)
{
  char
    *resource_type,
    resource_name[MaxTextExtent];

  int
    status;

  XrmValue
    resource_value;

  if (database == (XrmDatabase) NULL)
    return((char *) resource_default);
  *resource_name='\0';
  if (keyword != (char *) NULL)
    FormatString(resource_name,"%.1024s.%.1024s",client_name,keyword);
  status=XrmGetResource(database,resource_name,"GraphicsMagick",
    &resource_type,&resource_value);
  if (status == False)
    return((char *) resource_default);
  return(resource_value.addr);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t S c r e e n D e n s i t y                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetScreenDensity returns the density of the X server screen in
%  dots-per-inch.
%
%  The format of the MagickXGetScreenDensity method is:
%
%      char *MagickXGetScreenDensity(Display *display)
%
%  A description of each parameter follows:
%
%    o density: Method MagickXGetScreenDensity returns the density of the X
%     screen
%      in dots-per-inch.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%
*/
MagickExport char *
MagickXGetScreenDensity(Display *display)
{
  char
    density[MaxTextExtent];

  double
    x_density,
    y_density;

  /*
    Set density as determined by screen size.
  */
  x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
    ((double) DisplayWidthMM(display,XDefaultScreen(display))));
  y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
    ((double) DisplayHeightMM(display,XDefaultScreen(display))));
  FormatString(density,"%gx%g",x_density,y_density);
  return(GetPageGeometry(density));
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   M a g i c k X G e t S u b w i n d o w                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method XGetSubwindow returns the subwindow of a window chosen the
%  user with the pointer and a button press.
%
%  The format of the XGetSubwindow method is:
%
%      Window XGetSubwindow(Display *display,Window window,int x,int y)
%
%  A description of each parameter follows:
%
%    o subwindow: Method XGetSubwindow returns NULL if no subwindow is found
%      otherwise the subwindow is returned.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window.
%
%    o x: the x coordinate of the pointer relative to the origin of the
%      window.
%
%    o y: the y coordinate of the pointer relative to the origin of the
%      window.
%
%
*/
static Window
MagickXGetSubwindow(Display *display,Window window,int x,int y)
{
  Window
    source_window,
    target_window;

  int
    status,
    x_offset,
    y_offset;

  assert(display != (Display *) NULL);
  source_window=XRootWindow(display,XDefaultScreen(display));
  if (window == (Window) NULL)
    return(source_window);
  target_window=window;
  for ( ; ; )
  {
    status=XTranslateCoordinates(display,source_window,window,x,y,
      &x_offset,&y_offset,&target_window);
    if (status != True)
      break;
    if (target_window == (Window) NULL)
      break;
    source_window=window;
    window=target_window;
    x=x_offset;
    y=y_offset;
  }
  if (target_window == (Window) NULL)
    target_window=window;
  return(target_window);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t W i n d o w C o l o r                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetWindowColor returns the color of a pixel interactively
%  chosen from the X server.
%
%  The format of the MagickXGetWindowColor method is:
%
%      unsigned int MagickXGetWindowColor(Display *display,
%        MagickXWindows *windows,char *name)
%
%  A description of each parameter follows:
%
%    o status: Method MagickXGetWindowColor returns True if the color is
%      obtained from the X server.  False is returned if any errors occurs.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%    o name: The name of of the color if found in the X Color Database is
%      returned in this character string.
%
%
*/
MagickExport unsigned int
MagickXGetWindowColor(Display *display,MagickXWindows *windows,char *name)
{
  int
    x,
    y;

  PixelPacket
    pixel;

  RectangleInfo
    crop_info;

  unsigned int
    status;

  Window
    child,
    client_window,
    root_window,
    target_window;

  XColor
    color;

  XImage
    *ximage;

  XWindowAttributes
    window_attributes;

  /*
    Choose a pixel from the X server.
  */
  assert(display != (Display *) NULL);
  assert(name != (char *) NULL);
  *name='\0';
  target_window=MagickXSelectWindow(display,&crop_info);
  root_window=XRootWindow(display,XDefaultScreen(display));
  client_window=target_window;
  if (target_window != root_window)
    {
      unsigned int
        d;

      /*
        Get client window.
      */
      status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
      if (status != 0)
        {
          client_window=MagickXClientWindow(display,target_window);
          target_window=client_window;
        }
    }
  /*
    Verify window is viewable.
  */
  status=XGetWindowAttributes(display,target_window,&window_attributes);
  if ((status == False) || (window_attributes.map_state != IsViewable))
    return(False);
  /*
    Get window X image.
  */
  (void) XTranslateCoordinates(display,root_window,target_window,
    (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
  ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
  if (ximage == (XImage *) NULL)
    return(False);
  color.pixel=XGetPixel(ximage,0,0);
  XDestroyImage(ximage);
  ximage=(XImage *) NULL;
  /*
    Match color against the color database.
  */
  (void) XQueryColor(display,window_attributes.colormap,&color);
  pixel.red=ScaleShortToQuantum(color.red);
  pixel.green=ScaleShortToQuantum(color.green);
  pixel.blue=ScaleShortToQuantum(color.blue);
  pixel.opacity=OpaqueOpacity;
  (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
    &windows->image.image->exception);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   M a g i c k X G e t W i n d o w I m a g e                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetWindowImage reads an image from the target X window and
%  returns it.  MagickXGetWindowImage optionally descends the window
%  hierarchy and overlays the target image with each child image in an
%  optimized fashion.  Any child window that have the same visual, colormap,
%  and are contained by its parent are exempted.
%
%  The format of the MagickXGetWindowImage method is:
%
%      Image *MagickXGetWindowImage(Display *display,const Window window,
%        const unsigned int borders,const unsigned int level)
%
%  A description of each parameter follows:
%
%    o image: Method MagickXGetWindowImage returns a MIFF image if it can be
%      successfully read from the X window.  A null image is returned if
%      any errors occurs.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o window: Specifies the window to obtain the image from.
%
%    o borders: Specifies whether borders pixels are to be saved with
%      the image.
%
%    o level: Specifies an unsigned integer representing the level of
%      decent in the window hierarchy.  This value must be zero or one on
%      the initial call to MagickXGetWindowImage.  A value of zero returns
%      after one call.  A value of one causes the function to descend the
%      window hierarchy and overlay the target image with each subwindow image.
%
%
*/
static Image *
MagickXGetWindowImage(Display *display,const Window window,
                      const unsigned int borders,const unsigned int level)
{
  typedef struct _ColormapInfo
  {
    Colormap
      colormap;

    XColor
      *colors;

    struct _ColormapInfo
      *next;
  } ColormapInfo;

  typedef struct _WindowInfo
  {
    Window
      window,
      parent;

    Visual
      *visual;

    Colormap
      colormap;

    XSegment
      bounds;

    RectangleInfo
      crop_info;
  } WindowInfo;

  IndexPacket
    index_packet;

  int
    display_height,
    display_width,
    id,
    status,
    x_offset,
    y_offset;

  RectangleInfo
    crop_info;

  register IndexPacket
    *indexes;

  register int
    i;

  static ColormapInfo
    *colormap_info = (ColormapInfo *) NULL;

  static int
    max_windows = 0,
    number_windows = 0;

  static WindowInfo
    *window_info;

  Window
    child,
    root_window;

  XWindowAttributes
    window_attributes;

  /*
    Verify window is viewable.
  */
  assert(display != (Display *) NULL);
  status=XGetWindowAttributes(display,window,&window_attributes);
  if ((status == False) || (window_attributes.map_state != IsViewable))
    return((Image *) NULL);
  /*
    Cropping rectangle is relative to root window.
  */
  root_window=XRootWindow(display,XDefaultScreen(display));
  (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
    &y_offset,&child);
  crop_info.x=x_offset;
  crop_info.y=y_offset;
  crop_info.width=window_attributes.width;
  crop_info.height=window_attributes.height;
  if (borders)
    {
      /*
        Include border in image.
      */
      crop_info.x-=window_attributes.border_width;
      crop_info.y-=window_attributes.border_width;
      crop_info.width+=window_attributes.border_width << 1;
      crop_info.height+=window_attributes.border_width << 1;
    }
  /*
    Crop to root window.
  */
  if (crop_info.x < 0)
    {
      crop_info.width+=crop_info.x;
      crop_info.x=0;
    }
  if (crop_info.y < 0)
    {
      crop_info.height+=crop_info.y;
      crop_info.y=0;
    }
  display_width=XDisplayWidth(display,XDefaultScreen(display));
  if ((int) (crop_info.x+crop_info.width) > display_width)
    crop_info.width=display_width-crop_info.x;
  display_height=XDisplayHeight(display,XDefaultScreen(display));
  if ((int) (crop_info.y+crop_info.height) > display_height)
    crop_info.height=display_height-crop_info.y;
  /*
    Initialize window info attributes.
  */
  if (number_windows >= max_windows)
    {
      /*
        Allocate or resize window info buffer.
      */
      max_windows+=1024;
      if (window_info == (WindowInfo *) NULL)
        window_info=MagickAllocateArray(WindowInfo *,
                                        max_windows,sizeof(WindowInfo));
      else
        MagickReallocMemory(WindowInfo *,window_info,max_windows*sizeof(WindowInfo));
    }
  if (window_info == (WindowInfo *) NULL)
    {
      MagickError3(ResourceLimitError,MemoryAllocationFailed,
        UnableToReadXImage);
      return((Image *) NULL);
    }
  id=number_windows++;
  window_info[id].window=window;
  window_info[id].visual=window_attributes.visual;
  window_info[id].colormap=window_attributes.colormap;
  window_info[id].bounds.x1=(short) crop_info.x;
  window_info[id].bounds.y1=(short) crop_info.y;
  window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
  window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
  crop_info.x-=x_offset;
  crop_info.y-=y_offset;
  window_info[id].crop_info=crop_info;
  if (level != 0)
    {
      unsigned int
        number_children;

      Window
        *children;

      /*
        Descend the window hierarchy.
      */
      status=XQueryTree(display,window,&root_window,&window_info[id].parent,
        &children,&number_children);
      for (i=0; i < id; i++)
        if ((window_info[i].window == window_info[id].parent) &&
            (window_info[i].visual == window_info[id].visual) &&
            (window_info[i].colormap == window_info[id].colormap))
          if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
              (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
              (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
              (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
            {
              /*
                Eliminate windows not circumscribed by their parent.
              */
              number_windows--;
              break;
            }
      if ((status == True) && (number_children != 0))
        {
          for (i=0; i < (int) number_children; i++)
            (void) MagickXGetWindowImage(display,children[i],False,level+1);
          (void) XFree((void *) children);
        }
    }
  if (level <= 1)
    {
      ColormapInfo
        *next;

      Image
        *composite_image,
        *image;

      int
        y;

      register int
        j,
        x;

      register PixelPacket
        *q;

      register unsigned long
        pixel;

      unsigned int
        import,
        number_colors;

      XColor
        *colors;

      XImage
        *ximage;

      /*
        Get X image for each window in the list.
      */
      image=(Image *) NULL;
      for (id=0; id < number_windows; id++)
      {
        /*
          Does target window intersect top level window?
        */
        import=(window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
          (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
          (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
          (window_info[id].bounds.y1 <= window_info[0].bounds.y2);
        /*
          Is target window contained by another window with the same colormap?
        */
        for (j=0; j < id; j++)
          if ((window_info[id].visual == window_info[j].visual) &&
              (window_info[id].colormap == window_info[j].colormap) &&
              (window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
              (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
              (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
              (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
            import=False;
          else
            if ((window_info[id].visual != window_info[j].visual) ||
                (window_info[id].colormap != window_info[j].colormap))
              if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
                  (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
                  (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
                  (window_info[id].bounds.y1 < window_info[j].bounds.y2))
                import=True;
        if (!import)
          continue;
        /*
          Get X image.
        */
        ximage=XGetImage(display,window_info[id].window,
          (int) window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
          (unsigned int) window_info[id].crop_info.width,
          (unsigned int) window_info[id].crop_info.height,AllPlanes,ZPixmap);
        if (ximage == (XImage *) NULL)
          continue;
        /*
          Initialize window colormap.
        */
        number_colors=0;
        colors=(XColor *) NULL;
        if (window_info[id].colormap != (Colormap) NULL)
          {
            ColormapInfo
              *p;

            /*
              Search colormap list for window colormap.
            */
            number_colors=window_info[id].visual->map_entries;
            for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
              if (p->colormap == window_info[id].colormap)
                break;
            if (p == (ColormapInfo *) NULL)
              {
                /*
                  Get the window colormap.
                */
                colors=MagickAllocateArray(XColor *,number_colors,sizeof(XColor));
                if (colors == (XColor *) NULL)
                  {
                    XDestroyImage(ximage);
                    ximage=(XImage *) NULL;
                    return((Image *) NULL);
                  }
                if ((window_info[id].visual->class != DirectColor) &&
                    (window_info[id].visual->class != TrueColor))
                  for (i=0; i < (int) number_colors; i++)
                  {
                    colors[i].pixel=i;
                    colors[i].pad=0;
                  }
                else
                  {
                    unsigned long
                      blue,
                      blue_bit,
                      green,
                      green_bit,
                      red,
                      red_bit;

                    /*
                      DirectColor or TrueColor visual.
                    */
                    red=0;
                    green=0;
                    blue=0;
                    red_bit=window_info[id].visual->red_mask &
                      (~(window_info[id].visual->red_mask)+1);
                    green_bit=window_info[id].visual->green_mask &
                      (~(window_info[id].visual->green_mask)+1);
                    blue_bit=window_info[id].visual->blue_mask &
                      (~(window_info[id].visual->blue_mask)+1);
                    for (i=0; i < (int) number_colors; i++)
                    {
                      colors[i].pixel=red | green | blue;
                      colors[i].pad=0;
                      red+=red_bit;
                      if (red > window_info[id].visual->red_mask)
                        red=0;
                      green+=green_bit;
                      if (green > window_info[id].visual->green_mask)
                        green=0;
                      blue+=blue_bit;
                      if (blue > window_info[id].visual->blue_mask)
                        blue=0;
                    }
                  }
                (void) XQueryColors(display,window_info[id].colormap,colors,
                 (int) number_colors);
                /*
                  Append colormap to colormap list.
                */
                p=MagickAllocateMemory(ColormapInfo *,sizeof(ColormapInfo));
                if (p == (ColormapInfo *) NULL)
                  return((Image *) NULL);
                p->colormap=window_info[id].colormap;
                p->colors=colors;
                p->next=colormap_info;
                colormap_info=p;
              }
            colors=p->colors;
          }
        /*
          Allocate image structure.
        */
        composite_image=AllocateImage((ImageInfo *) NULL);
        if (composite_image == (Image *) NULL)
          {
            XDestroyImage(ximage);
            ximage=(XImage *) NULL;
            return((Image *) NULL);
          }
        /*
          Convert X image to MIFF format.
        */
        if ((window_info[id].visual->class != TrueColor) &&
            (window_info[id].visual->class != DirectColor))
          composite_image->storage_class=PseudoClass;
        composite_image->columns=ximage->width;
        composite_image->rows=ximage->height;
        switch (composite_image->storage_class)
        {
          case DirectClass:
          default:
          {
            register unsigned long
              color,
              colormap_index;

            unsigned long
              blue_mask,
              blue_shift,
              green_mask,
              green_shift,
              red_mask,
              red_shift;

            /*
              Determine shift and mask for red, green, and blue.
            */
            red_mask=window_info[id].visual->red_mask;
            red_shift=0;
            while ((red_mask & 0x01) == 0)
            {
              red_mask>>=1;
              red_shift++;
            }
            green_mask=window_info[id].visual->green_mask;
            green_shift=0;
            while ((green_mask & 0x01) == 0)
            {
              green_mask>>=1;
              green_shift++;
            }
            blue_mask=window_info[id].visual->blue_mask;
            blue_shift=0;
            while ((blue_mask & 0x01) == 0)
            {
              blue_mask>>=1;
              blue_shift++;
            }
            /*
              Convert X image to DirectClass packets.
            */
            if ((number_colors != 0) &&
                (window_info[id].visual->class == DirectColor))
              for (y=0; y < (long) composite_image->rows; y++)
              {
                q=SetImagePixels(composite_image,0,y,
                  composite_image->columns,1);
                if (q == (PixelPacket *) NULL)
                  break;
                for (x=0; x < (long) composite_image->columns; x++)
                {
                  pixel=XGetPixel(ximage,x,y);
                  colormap_index=(pixel >> red_shift) & red_mask;
                  q->red=ScaleShortToQuantum(colors[colormap_index].red);
                  colormap_index=(pixel >> green_shift) & green_mask;
                  q->green=ScaleShortToQuantum(colors[colormap_index].green);
                  colormap_index=(pixel >> blue_shift) & blue_mask;
                  q->blue=ScaleShortToQuantum(colors[colormap_index].blue);
                  q++;
                }
                if (!SyncImagePixels(composite_image))
                  break;
              }
            else
              for (y=0; y < (long) composite_image->rows; y++)
              {
                q=SetImagePixels(composite_image,0,y,
                  composite_image->columns,1);
                if (q == (PixelPacket *) NULL)
                  break;
                for (x=0; x < (long) composite_image->columns; x++)
                {
                  pixel=XGetPixel(ximage,x,y);
                  color=(pixel >> red_shift) & red_mask;
                  q->red=ScaleShortToQuantum((65535L*color)/red_mask);
                  color=(pixel >> green_shift) & green_mask;
                  q->green=ScaleShortToQuantum((65535L*color)/green_mask);
                  color=(pixel >> blue_shift) & blue_mask;
                  q->blue=ScaleShortToQuantum((65535L*color)/blue_mask);
                  q++;
                }
                if (!SyncImagePixels(composite_image))
                  break;
              }
            break;
          }
          case PseudoClass:
          {
            /*
              Create colormap.
            */
            if (!AllocateImageColormap(composite_image,number_colors))
              {
                XDestroyImage(ximage);
                ximage=(XImage *) NULL;
                DestroyImage(composite_image);
                return((Image *) NULL);
              }
            for (i=0; i < (int) composite_image->colors; i++)
            {
              composite_image->colormap[colors[i].pixel].red=
                ScaleShortToQuantum(colors[i].red);
              composite_image->colormap[colors[i].pixel].green=
                ScaleShortToQuantum(colors[i].green);
              composite_image->colormap[colors[i].pixel].blue=
                ScaleShortToQuantum(colors[i].blue);
            }
            /*
              Convert X image to PseudoClass packets.
            */
            for (y=0; y < (long) composite_image->rows; y++)
            {
              q=SetImagePixels(composite_image,0,y,composite_image->columns,1);
              if (q == (PixelPacket *) NULL)
                break;
              indexes=AccessMutableIndexes(composite_image);
              for (x=0; x < (long) composite_image->columns; x++)
              {
                index_packet=(IndexPacket) XGetPixel(ximage,x,y);
                indexes[x]=index_packet;
                *q++=composite_image->colormap[index_packet];
              }
              if (!SyncImagePixels(composite_image))
                break;
            }
            break;
          }
        }
        XDestroyImage(ximage);
        ximage=(XImage *) NULL;

        /*
          Evaluate image depth.
        */
        composite_image->depth=GetImageDepth(composite_image,&composite_image->exception);
        if (composite_image->depth < 8)
          composite_image->depth=8;

        if (image == (Image *) NULL)
          {
            image=composite_image;
            continue;
          }
        /*
          Composite any children in back-to-front order.
        */
        (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
          &x_offset,&y_offset,&child);
        x_offset-=(int) crop_info.x;
        if (x_offset < 0)
          x_offset=0;
        y_offset-=(int) crop_info.y;
        if (y_offset < 0)
          y_offset=0;
        (void) CompositeImage(image,CopyCompositeOp,composite_image,
          x_offset,y_offset);
      }
      /*
        Free resources.
      */
      while (colormap_info != (ColormapInfo *) NULL)
      {
        next=colormap_info->next;
        MagickFreeMemory(colormap_info->colors);
        MagickFreeMemory(colormap_info);
        colormap_info=next;
      }
      /*
        Free resources and restore initial state.
      */
      MagickFreeMemory(window_info);
      window_info=(WindowInfo *) NULL;
      max_windows=0;
      number_windows=0;
      colormap_info=(ColormapInfo *) NULL;
      return(image);
    }
  return((Image *) NULL);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t W i n d o w I n f o                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetWindowInfo initializes the MagickXWindowInfo structure.
%
%  The format of the MagickXGetWindowInfo method is:
%
%      void MagickXGetWindowInfo(Display *display,XVisualInfo *visual_info,
%        XStandardColormap *map_info,MagickXPixelInfo *pixel,
%        XFontStruct *font_info,MagickXResourceInfo *resource_info,
%        MagickXWindowInfo *window)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o map_info: If map_type is specified, this structure is initialized
%      with info from the Standard Colormap.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%    o font_info: Specifies a pointer to a XFontStruct structure.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%
*/
MagickExport void
MagickXGetWindowInfo(Display *display,
                     XVisualInfo *visual_info,
                     XStandardColormap *map_info,
                     MagickXPixelInfo *pixel,
                     XFontStruct *font_info,
                     MagickXResourceInfo *resource_info,
                     MagickXWindowInfo *window)
{
  /*
    Initialize window info.
  */
  assert(display != (Display *) NULL);
  assert(visual_info != (XVisualInfo *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  assert(pixel != (MagickXPixelInfo *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  if (window->id != (Window) NULL)
    {
      (void) XFreeCursor(display,window->cursor);
      (void) XFreeCursor(display,window->busy_cursor);
      if (window->highlight_stipple != (Pixmap) NULL)
        (void) XFreePixmap(display,window->highlight_stipple);
      if (window->shadow_stipple != (Pixmap) NULL)
        (void) XFreePixmap(display,window->shadow_stipple);
    }
  else
    {
      /*
        Initialize these attributes just once.
      */
      window->id=(Window) NULL;
      window->x=XDisplayWidth(display,visual_info->screen) >> 1;
      window->y=XDisplayWidth(display,visual_info->screen) >> 1;
      window->ximage=(XImage *) NULL;
      window->matte_image=(XImage *) NULL;
      window->pixmap=(Pixmap) NULL;
      window->matte_pixmap=(Pixmap) NULL;
      window->mapped=False;
      window->stasis=False;
      window->shared_memory=True;
      /* window->segment_info=0; */
#if defined(HasSharedMemory)
      {
        XShmSegmentInfo
          *segment_info;

        if (window->segment_info == (void *) NULL)
          window->segment_info=MagickAllocateArray(void *,2,sizeof(XShmSegmentInfo));
        segment_info=(XShmSegmentInfo *) window->segment_info;
        segment_info[0].shmid=(-1);
        segment_info[0].shmaddr=NULL;
        segment_info[1].shmid=(-1);
        segment_info[1].shmaddr=NULL;
      }
#endif
    }
  /*
    Initialize these attributes every time function is called.
  */
  window->screen=visual_info->screen;
  window->root=XRootWindow(display,visual_info->screen);
  window->visual=visual_info->visual;
  window->storage_class=visual_info->class;
  window->depth=visual_info->depth;
  window->visual_info=visual_info;
  window->map_info=map_info;
  window->pixel_info=pixel;
  window->font_info=font_info;
  window->cursor=XCreateFontCursor(display,XC_left_ptr);
  window->busy_cursor=XCreateFontCursor(display,XC_watch);
  (void) CloneString(&window->name,(char *) NULL);
  window->geometry=(char *) NULL;
  (void) CloneString(&window->icon_name,(char *) NULL);
  window->icon_geometry=resource_info->icon_geometry;
  window->crop_geometry=(char *) NULL;
  window->flags=PSize;
  window->width=1;
  window->height=1;
  window->min_width=1;
  window->min_height=1;
  window->width_inc=1;
  window->height_inc=1;
  window->border_width=resource_info->border_width;
  window->annotate_context=pixel->annotate_context;
  window->highlight_context=pixel->highlight_context;
  window->widget_context=pixel->widget_context;
  window->shadow_stipple=(Pixmap) NULL;
  window->highlight_stipple=(Pixmap) NULL;
  window->use_pixmap=True;
  window->immutable=False;
  window->shape=False;
  window->data=0;
  window->mask=CWBackingStore | CWBackPixel | CWBackPixmap | CWBitGravity |
    CWBorderPixel | CWColormap | CWCursor | CWDontPropagate | CWEventMask |
    CWOverrideRedirect | CWSaveUnder | CWWinGravity;
  window->attributes.background_pixel=pixel->background_color.pixel;
  window->attributes.background_pixmap=(Pixmap) NULL;
  window->attributes.bit_gravity=ForgetGravity;
  window->attributes.backing_store=NotUseful;
  window->attributes.save_under=False;
  window->attributes.border_pixel=pixel->border_color.pixel;
  window->attributes.colormap=map_info->colormap;
  window->attributes.cursor=window->cursor;
  window->attributes.do_not_propagate_mask=NoEventMask;
  window->attributes.event_mask=NoEventMask;
  window->attributes.override_redirect=False;
  window->attributes.win_gravity=NorthWestGravity;
  window->orphan=False;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X H i g h l i g h t E l l i p s e                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXHighlightEllipse puts a border on the X server around a region
%  defined by highlight_info.
%
%  The format of the MagickXHighlightEllipse method is:
%
%      void MagickXHighlightEllipse(Display *display,Window window,
%        GC annotate_context,const RectangleInfo *highlight_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window structure.
%
%    o annotate_context: Specifies a pointer to a GC structure.
%
%    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
%      contains the extents of any highlighting rectangle.
%
%
*/
MagickExport void
MagickXHighlightEllipse(Display *display,Window window,
                        GC annotate_context,
                        const RectangleInfo *highlight_info)
{
  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(annotate_context != (GC) NULL);
  assert(highlight_info != (RectangleInfo *) NULL);
  if ((highlight_info->width < 4) || (highlight_info->height < 4))
    return;
  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
    (int) highlight_info->y,(unsigned int) highlight_info->width-1,
    (unsigned int) highlight_info->height-1,0,360*64);
  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
    (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
    (unsigned int) highlight_info->height-3,0,360*64);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X H i g h l i g h t L i n e                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXHighlightLine puts a border on the X server around a region
%  defined by highlight_info.
%
%  The format of the MagickXHighlightLine method is:
%
%      void MagickXHighlightLine(Display *display,Window window,
%        GC annotate_context,const XSegment *highlight_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window structure.
%
%    o annotate_context: Specifies a pointer to a GC structure.
%
%    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
%      contains the extents of any highlighting rectangle.
%
%
*/
MagickExport void 
MagickXHighlightLine(Display *display,Window window,
                     GC annotate_context,const XSegment *highlight_info)
{
  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(annotate_context != (GC) NULL);
  assert(highlight_info != (XSegment *) NULL);
  (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
    highlight_info->y1,highlight_info->x2,highlight_info->y2);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X H i g h l i g h t R e c t a n g l e                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXHighlightRectangle puts a border on the X server around a
%  region defined by highlight_info.
%
%  The format of the MagickXHighlightRectangle method is:
%
%      void MagickXHighlightRectangle(Display *display,Window window,
%        GC annotate_context,const RectangleInfo *highlight_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window structure.
%
%    o annotate_context: Specifies a pointer to a GC structure.
%
%    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
%      contains the extents of any highlighting rectangle.
%
%
*/
MagickExport void
MagickXHighlightRectangle(Display *display,Window window,
                          GC annotate_context,
                          const RectangleInfo *highlight_info)
{
  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(annotate_context != (GC) NULL);
  assert(highlight_info != (RectangleInfo *) NULL);
  if ((highlight_info->width < 4) || (highlight_info->height < 4))
    return;
  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
    (int) highlight_info->y,(unsigned int) highlight_info->width-1,
    (unsigned int) highlight_info->height-1);
  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
    1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
    (unsigned int) highlight_info->height-3);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X I m p o r t I m a g e                                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Procedure MagickXImportImage reads an image from an X window.
%
%  The format of the MagickXImportImage method is:
%
%      Image *MagickXImportImage(const ImageInfo *image_info,
%        MagickXImportInfo *ximage_info)
%
%  A description of each parameter follows:
%
%    o image_info: The image info..
%
%    o ximage_info: Specifies a pointer to an MagickXImportInfo structure.
%
%
*/
MagickExport Image *
MagickXImportImage(const ImageInfo *image_info,
                   MagickXImportInfo *ximage_info)
{
  Colormap
    *colormaps;

  Display
    *display;

  Image
    *image;

  int
    number_colormaps,
    number_windows,
    status,
    x;

  RectangleInfo
    crop_info;

  Window
    *children,
    client,
    prior_target,
    root,
    target;

  XTextProperty
    window_name;

  /*
    Open X server connection.
  */
  assert(image_info != (ImageInfo *) NULL);
  assert(ximage_info != (MagickXImportInfo *) NULL);
  display=XOpenDisplay(image_info->server_name);
  if (display == (Display *) NULL)
    {
      MagickError(XServerError,UnableToOpenXServer,
        XDisplayName(image_info->server_name));
      return((Image *) NULL);
    }
  /*
    Set our forgiving error handler.
  */
  (void) XSetErrorHandler(MagickXError);
  /*
    Select target window.
  */
  crop_info.x=0;
  crop_info.y=0;
  crop_info.width=0;
  crop_info.height=0;
  root=XRootWindow(display,XDefaultScreen(display));
  target=(Window) NULL;
  if ((image_info->filename != (char *) NULL) &&
      (*image_info->filename != '\0'))
    {
      if (LocaleCompare(image_info->filename,"root") == 0)
        target=root;
      else
        {
          /*
            Select window by ID or name.
          */
          if (isdigit((int) (*image_info->filename)))
            target=MagickXWindowByID(display,root,(Window)
              strtol(image_info->filename,(char **) NULL,0));
          if (target == (Window) NULL)
            target=MagickXWindowByName(display,root,image_info->filename);
          if (target == (Window) NULL)
            MagickError(XServerError,NoWindowWithSpecifiedIDExists,
              image_info->filename);
        }
    }
  /*
    If target window is not defined, interactively select one.
  */
  prior_target=target;
  if (target == (Window) NULL)
    target=MagickXSelectWindow(display,&crop_info);
  client=target;   /* obsolete */
  if (target != root)
    {
      unsigned int
        d;

      status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
      if (status != 0)
        {
          for ( ; ; )
          {
            Window
              parent;

            /*
              Find window manager frame.
            */
            status=XQueryTree(display,target,&root,&parent,&children,&d);
            if (status && (children != (Window *) NULL))
              (void) XFree((char *) children);
            if (!status || (parent == (Window) NULL) || (parent == root))
              break;
            target=parent;
          }
          /*
            Get client window.
          */
          client=MagickXClientWindow(display,target);
          if (!ximage_info->frame)
            target=client;
          if (!ximage_info->frame && prior_target)
            target=prior_target;
          (void) XRaiseWindow(display,target);
          MagickXDelay(display,SuspendTime << 4);
        }
    }
  if (ximage_info->screen)
    {
      int
        y;

      Window
        child;

      XWindowAttributes
        window_attributes;

      /*
        Obtain window image directly from screen.
      */
      status=XGetWindowAttributes(display,target,&window_attributes);
      if (status == False)
        {
          MagickError(XServerError,UnableToReadXAttributes,
            image_info->filename);
          (void) XCloseDisplay(display);
          return((Image *) NULL);
        }
      (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
      crop_info.x=x;
      crop_info.y=y;
      crop_info.width=window_attributes.width;
      crop_info.height=window_attributes.height;
      if (ximage_info->borders)
        {
          /*
            Include border in image.
          */
          crop_info.x-=window_attributes.border_width;
          crop_info.y-=window_attributes.border_width;
          crop_info.width+=window_attributes.border_width << 1;
          crop_info.height+=window_attributes.border_width << 1;
        }
      target=root;
    }
  /*
    If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
  */
  number_windows=0;
  status=XGetWMColormapWindows(display,target,&children,&number_windows);
  if ((status == True) && (number_windows > 0))
    {
      ximage_info->descend=True;
      (void) XFree ((char *) children);
    }
  colormaps=XListInstalledColormaps(display,target,&number_colormaps);
  if (number_colormaps > 0)
    {
      if (number_colormaps > 1)
        ximage_info->descend=True;
      (void) XFree((char *) colormaps);
    }
  /*
    Alert the user not to alter the screen.
  */
  if (!ximage_info->silent)
    (void) XBell(display,0);
  /*
    Get image by window id.
  */
  (void) XGrabServer(display);
  image=MagickXGetWindowImage(display,target,ximage_info->borders,
    ximage_info->descend ? 1 : 0);
  (void) XUngrabServer(display);
  if (image == (Image *) NULL)
    MagickError(XServerError,UnableToReadXWindowImage,image_info->filename);
  else
    {
      (void) strlcpy(image->filename,image_info->filename,MaxTextExtent);
      if ((crop_info.width != 0) && (crop_info.height != 0))
        {
          Image
            *clone_image,
            *crop_image;

          /*
            Crop image as defined by the cropping rectangle.
          */
          clone_image=CloneImage(image,0,0,True,&image->exception);
          if (clone_image != (Image *) NULL)
            {
              crop_image=CropImage(clone_image,&crop_info,&image->exception);
              if (crop_image != (Image *) NULL)
                {
                  DestroyImage(image);
                  image=crop_image;
                }
            }
        }
      status=XGetWMName(display,target,&window_name);
      if (status == True)
        {
          if ((image_info->filename != (char *) NULL) &&
              (*image_info->filename == '\0'))
            {
              /*
                Initialize image filename.
              */
              (void) strlcpy(image->filename,(char *) window_name.value,
                (int) window_name.nitems+1);
              image->filename[window_name.nitems]='\0';
            }
          (void) XFree((void *) window_name.value);
        }
    }
  if (!ximage_info->silent)
    {
      /*
        Alert the user we're done.
      */
      (void) XBell(display,0);
      (void) XBell(display,0);
    }
  (void) XCloseDisplay(display);
  return(image);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X I n i t i a l i z e W i n d o w s                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXInitializeWindows initializes the MagickXWindows structure.
%
%  The format of the MagickXInitializeWindows method is:
%
%      MagickXWindows *MagickXInitializeWindows(Display *display,
%        MagickXResourceInfo *resource_info)
%
%  A description of each parameter follows:
%
%    o windows: MagickXInitializeWindows returns a pointer to a
%      MagickXWindows structure.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
*/
MagickExport MagickXWindows *
MagickXInitializeWindows(Display *display,
                         MagickXResourceInfo *resource_info)
{
  Window
    root_window;

  MagickXWindows
    *windows;

  /*
    Allocate windows structure.
  */
  windows=MagickAllocateMemory(MagickXWindows *,sizeof(MagickXWindows));
  if (windows == (MagickXWindows *) NULL)
    {
      MagickError3(ResourceLimitError,MemoryAllocationFailed,
        UnableToCreateXWindow);
      return((MagickXWindows *) NULL);
    }
  (void) memset(windows,0,sizeof(MagickXWindows));
  windows->pixel_info=MagickAllocateMemory(MagickXPixelInfo *,sizeof(MagickXPixelInfo));
  windows->icon_pixel=MagickAllocateMemory(MagickXPixelInfo *,sizeof(MagickXPixelInfo));
  windows->icon_resources=MagickAllocateMemory(MagickXResourceInfo *,
    sizeof(MagickXResourceInfo));
  if ((windows->pixel_info == (MagickXPixelInfo *) NULL) ||
      (windows->icon_pixel == (MagickXPixelInfo *) NULL) ||
      (windows->icon_resources == (MagickXResourceInfo *) NULL))
    {
      MagickError3(ResourceLimitError,MemoryAllocationFailed,
        UnableToCreateXWindow);
      return((MagickXWindows *) NULL);
    }
  /*
    Initialize windows structure.
  */
  windows->display=display;
  windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",False);
  windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",False);
  windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",False);
  windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",False);
  windows->im_remote_command=XInternAtom(display,"IM_REMOTE_COMMAND",False);
  windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",False);
  windows->im_update_colormap=
    XInternAtom(display,"IM_UPDATE_COLORMAP",False);
  windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",False);
  windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",False);
  windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",False);
  windows->im_exit=XInternAtom(display,"IM_EXIT",False);
  windows->dnd_protocols=XInternAtom(display,"DndProtocol",False);
#if defined(MSWINDOWS)
  (void) XSynchronize(display,IsWindows95());
#endif
  if (IsEventLogging())
    {
      (void) XSynchronize(display,True);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %.1024s",
        GetMagickVersion((unsigned long *) NULL));
      (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  Window Manager: 0x%lx",
        windows->wm_protocols);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    delete window: 0x%lx",
        windows->wm_delete_window);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    take focus: 0x%lx",
        windows->wm_take_focus);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  GraphicsMagick: 0x%lx",
        windows->im_protocols);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    remote command: 0x%lx",
        windows->im_remote_command);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    update widget: 0x%lx",
        windows->im_update_widget);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "    update colormap: 0x%lx",windows->im_update_colormap);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    former image: 0x%lx",
        windows->im_former_image);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    next image: 0x%lx",
        windows->im_next_image);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    retain colors: 0x%lx",
        windows->im_retain_colors);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    exit: 0x%lx",
        windows->im_exit);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  Drag and Drop: 0x%lx",
        windows->dnd_protocols);
    }
  /*
    Allocate standard colormap.
  */
  windows->map_info=XAllocStandardColormap();
  windows->icon_map=XAllocStandardColormap();
  if ((windows->map_info == (XStandardColormap *) NULL) ||
      (windows->icon_map == (XStandardColormap *) NULL))
    MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
      MagickMsg(XServerFatalError,UnableToCreateStandardColormap));
  windows->map_info->colormap=(Colormap) NULL;
  windows->icon_map->colormap=(Colormap) NULL;
  (void) memset((void *) windows->pixel_info, 0, sizeof(MagickXPixelInfo));
  windows->pixel_info->pixels=(unsigned long *) NULL;
  windows->pixel_info->annotate_context=(GC) NULL;
  windows->pixel_info->highlight_context=(GC) NULL;
  windows->pixel_info->widget_context=(GC) NULL;
  windows->font_info=(XFontStruct *) NULL;
  (void) memset((void *) windows->icon_pixel, 0, sizeof(MagickXPixelInfo));
  windows->icon_pixel->annotate_context=(GC) NULL;
  windows->icon_pixel->pixels=(unsigned long *) NULL;
  windows->icon_pixel->highlight_context=(GC) NULL;
  /*
    Allocate visual.
  */
  *windows->icon_resources=(*resource_info);
  windows->icon_resources->map_type=(char *) NULL;
  windows->icon_resources->visual_type=(char *) "default";
  windows->icon_resources->colormap=SharedColormap;
  windows->visual_info=
    MagickXBestVisualInfo(display,windows->map_info,resource_info);
  windows->icon_visual=
    MagickXBestVisualInfo(display,windows->icon_map,windows->icon_resources);
  if ((windows->visual_info == (XVisualInfo *) NULL) ||
      (windows->icon_visual == (XVisualInfo *) NULL))
    MagickFatalError(XServerFatalError,UnableToGetVisual,
      resource_info->visual_type);
  if (IsEventLogging())
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  visual id: 0x%lx",
        windows->visual_info->visualid);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  class: %.1024s",
        MagickXVisualClassName(windows->visual_info->class));
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d planes",
        windows->visual_info->depth);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  size of colormap: %d entries",windows->visual_info->colormap_size);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",
        windows->visual_info->red_mask,windows->visual_info->green_mask,
        windows->visual_info->blue_mask);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  significant bits in color: %d bits",
        windows->visual_info->bits_per_rgb);
    }
  /*
    Allocate class and manager hints.
  */
  windows->class_hints=XAllocClassHint();
  windows->manager_hints=XAllocWMHints();
  if ((windows->class_hints == (XClassHint *) NULL) ||
      (windows->manager_hints == (XWMHints *) NULL))
    MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
      MagickMsg(XServerFatalError,UnableToAllocateXHints));
  /*
    Determine group leader if we have one.
  */
  root_window=XRootWindow(display,windows->visual_info->screen);
  windows->group_leader.id=(Window) NULL;
  if (resource_info->window_group != (char *) NULL)
    {
      if (isdigit((int) (*resource_info->window_group)))
        windows->group_leader.id=MagickXWindowByID(display,root_window,(Window)
          strtol((char *) resource_info->window_group,(char **) NULL,0));
      if (windows->group_leader.id == (Window) NULL)
        windows->group_leader.id=
          MagickXWindowByName(display,root_window,resource_info->window_group);
    }
  return(windows);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e C u r s o r                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeCursor creates a crosshairs X11 cursor.
%
%  The format of the MagickXMakeCursor method is:
%
%      Cursor MagickXMakeCursor(Display *display,Window window,
%        Colormap colormap,char *background_color,char *foreground_color)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o window: Specifies the ID of the window for which the cursor is
%      assigned.
%
%    o colormap: Specifies the ID of the colormap from which the background
%      and foreground color will be retrieved.
%
%    o background_color: Specifies the color to use for the cursor background.
%
%    o foreground_color: Specifies the color to use for the cursor foreground.
%
%
*/
MagickExport Cursor
MagickXMakeCursor(Display *display,Window window,
                  Colormap colormap,char *background_color,
                  char *foreground_color)
{
#define scope_height 17
#define scope_x_hot 8
#define scope_y_hot 8
#define scope_width 17

  static const unsigned char
    scope_bits[] =
    {
      0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
      0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
      0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
      0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
      0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
    },
    scope_mask_bits[] =
    {
      0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
      0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
      0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
      0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
      0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
    };

  Cursor
    cursor;

  Pixmap
    mask,
    source;

  XColor
    background,
    foreground;

  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(colormap != (Colormap) NULL);
  assert(background_color != (char *) NULL);
  assert(foreground_color != (char *) NULL);
  source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
    scope_height);
  mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
    scope_width,scope_height);
  if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
    {
      MagickError(XServerError,UnableToCreatePixmap,(char *) NULL);
      return((Cursor) NULL);
    }
  (void) XParseColor(display,colormap,background_color,&background);
  (void) XParseColor(display,colormap,foreground_color,&foreground);
  cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
    scope_x_hot,scope_y_hot);
  (void) XFreePixmap(display,source);
  (void) XFreePixmap(display,mask);
  return(cursor);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e I m a g e                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeImage creates an X11 image.  If the image size differs
%  from the X11 image size, the image is first resized.
%
%  The format of the MagickXMakeImage method is:
%
%      unsigned int MagickXMakeImage(Display *display,
%        const MagickXResourceInfo *resource_info,MagickXWindowInfo *window,
%        Image *image,unsigned int width,unsigned int height)
%
%  A description of each parameter follows:
%
%    o status: Method MagickXMakeImage returns True if the X image is
%      successfully created.  False is returned is there is a memory shortage.
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o width: Specifies the width in pixels of the rectangular area to
%      display.
%
%    o height: Specifies the height in pixels of the rectangular area to
%      display.
%
%
*/
static const char *
MagickXImageFormatToString(int xformat)
{
  static const char
    *formats[] = 
    {
      "XYBitmap",
      "XYPixmap",
      "ZPixmap"
    };
  
  const char
    *format = "Unknown";

  if ((size_t) xformat < sizeof(formats)/sizeof(formats[0]))
    format=formats[xformat];

  return format;
}
static const char *
MagickXByteOrderToString(int xbyte_order)
{
  static const char
    *byte_orders[] =
    {
      "LSBFirst",
      "MSBFirst"
    };
  
  const char
    *byte_order = "Unknown";

  if ((size_t) xbyte_order < sizeof(byte_orders)/sizeof(byte_orders[0]))
    byte_order=byte_orders[xbyte_order];

  return byte_order;
}
MagickExport unsigned int
MagickXMakeImage(Display *display,
                 const MagickXResourceInfo *resource_info,
                 MagickXWindowInfo *window,
                 Image *image,
                 unsigned int width,unsigned int height)
{
  int
    depth,
    format;

  size_t
    length;

  XImage
    *matte_image,
    *ximage;

  assert(display != (Display *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  assert(width != 0);
  assert(height != 0);
  if ((window->width == 0) || (window->height == 0))
    return(False);
  /*
    Apply user transforms to the image.
  */
  (void) XDefineCursor(display,window->id,window->busy_cursor);
  (void) XFlush(display);
  depth=window->depth;
  if (window->destroy && window->image)
    DestroyImage(window->image);
  window->image=image;
  window->destroy=False;
  if (window->image != (Image *) NULL)
    {
      MonitorHandler
        handler=(MonitorHandler) NULL;

      handler=SetMonitorHandler((MonitorHandler) NULL);
      if (window->crop_geometry)
        {
          Image
            *crop_image;

          RectangleInfo
            crop_info;

          /*
            Crop image.
          */
          SetGeometry(window->image,&crop_info);
          (void) GetGeometry(window->crop_geometry,&crop_info.x,&crop_info.y,
            &crop_info.width,&crop_info.height);
          crop_image=CropImage(window->image,&crop_info,&image->exception);
          if (crop_image != (Image *) NULL)
            {
              if (window->image != image)
                DestroyImage(window->image);
              window->image=crop_image;
              window->destroy=MagickTrue;
            }
        }
      if ((width != (unsigned int) window->image->columns) ||
          (height != (unsigned int) window->image->rows))
        {
          Image
            *resize_image;

          /*
            Resize image.
          */
          resize_image=(Image *) NULL;
          if ((window->pixel_info->colors != 0) ||
              (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) ||
              (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
            resize_image=SampleImage(window->image,width,height,
              &image->exception);
          else
            resize_image=ZoomImage(window->image,width,height,
              &image->exception);
          if (resize_image != (Image *) NULL)
            {
              if (window->image != image)
                DestroyImage(window->image);
              window->image=resize_image;
              window->destroy=MagickTrue;
            }
        }
      if ((window->image->matte != MagickFalse) &&
          (window->pixel_info->colors == 0)
          /* && (window->immutable == MagickFalse) */)
        {
          Image
            *texture;

          /*
            Tile background with texture according to opacity
          */
          strlcpy(resource_info->image_info->filename,"image:checkerboard",
                  sizeof(resource_info->image_info->filename));
          texture=ReadImage(resource_info->image_info,&window->image->exception);
          if (texture != (Image *) NULL)
            {
              Image
                *textured_image;

              textured_image=CloneImage(window->image,0,0,MagickTrue,
                                        &window->image->exception);
              if (textured_image != (Image *) NULL)
                {
                  if (TextureImage(textured_image,texture) != MagickFail)
                    {
                      if (window->image != image)
                        DestroyImage(window->image);
                      window->image=textured_image;
                      window->destroy=MagickTrue;
                    }
                  else
                    {
                      DestroyImage(textured_image);
                    }
                }
              DestroyImage(texture);
              texture=(Image *) NULL;
            }
          }
      width=(unsigned int) window->image->columns;
      assert(width == window->image->columns);
      height=(unsigned int) window->image->rows;
      assert(height == window->image->rows);
      (void) SetMonitorHandler(handler);
    }
  /*
    Create X image.
  */
  ximage=(XImage *) NULL;
  format=(depth == 1) ? XYBitmap : ZPixmap;
#if defined(HasSharedMemory)
  window->shared_memory &= XShmQueryExtension(display);
  if (window->shared_memory)
    {
      XShmSegmentInfo
        *segment_info;

      size_t
        shm_extent;

      segment_info=(XShmSegmentInfo *) window->segment_info;
      segment_info[1].shmid=(-1);
      segment_info[1].shmaddr=NULL;
      ximage=XShmCreateImage(display,window->visual,depth,format,(char *) NULL,
                             &segment_info[1],width,height);
      window->shared_memory &= (ximage != (XImage *) NULL);

      shm_extent=MagickArraySize(ximage->height,ximage->bytes_per_line);
      window->shared_memory &= (shm_extent != 0);

      if (window->shared_memory)
        segment_info[1].shmid=shmget(IPC_PRIVATE,shm_extent,IPC_CREAT | 0777);
      window->shared_memory &= (segment_info[1].shmid >= 0);

      if (window->shared_memory)
        segment_info[1].shmaddr=(char *) MagickShmAt(segment_info[1].shmid,0,0);
      window->shared_memory &= (segment_info[1].shmaddr != NULL);

      if (!window->shared_memory)
        {
          /*
            Clean up if there is an error.
          */
          if (ximage != (XImage *) NULL)
            XDestroyImage(ximage);
          ximage=(XImage *) NULL;

          if (segment_info[1].shmaddr)
            {
              (void) MagickShmDt(segment_info[1].shmaddr);
              segment_info[1].shmaddr=NULL;
            }

          if (segment_info[1].shmid >= 0)
            {
              (void) MagickShmCtl(segment_info[1].shmid,IPC_RMID,0);
              segment_info[1].shmid=(-1);
            }
        }
    }
#endif
  /*
    Allocate X image pixel data.
  */
#if defined(HasSharedMemory)
  if (window->shared_memory)
    {
      XShmSegmentInfo
        *segment_info;

      Status
        shm_attached;

      (void) XSync(display,False);
      xerror_alert=False;
      segment_info=(XShmSegmentInfo *) window->segment_info;
      ximage->data=segment_info[1].shmaddr;
      segment_info[1].readOnly=False;
      shm_attached=XShmAttach(display,&segment_info[1]);
      if (shm_attached)
        (void) XSync(display,False);
      if (!shm_attached || xerror_alert)
        {
          window->shared_memory=False;
          if (shm_attached)
            (void) XShmDetach(display,&segment_info[1]);
          if (ximage != (XImage *) NULL)
            {
              ximage->data=NULL;
              XDestroyImage(ximage);
              ximage=(XImage *) NULL;
            }
          if (segment_info[1].shmid >= 0)
            {
              if (segment_info[1].shmaddr != NULL)
                (void) MagickShmDt(segment_info[1].shmaddr);
              (void) MagickShmCtl(segment_info[1].shmid,IPC_RMID,0);
              segment_info[1].shmaddr=NULL;
              segment_info[1].shmid=(-1);
            }
        }
    }
#endif
  if (!window->shared_memory)
    {
      ximage=XCreateImage(display,window->visual,depth,format,0,(char *) NULL,
        width,height,XBitmapPad(display),0);
    }
  if (ximage == (XImage *) NULL)
    {
      /*
        Unable to create X image.
      */
      (void) XDefineCursor(display,window->id,window->cursor);
      return(False);
    }
  if (IsEventLogging())
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  width x height: %dx%d",
        ximage->width,ximage->height);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  format: %s",
                            MagickXImageFormatToString(ximage->format));
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  byte order: %s",
                            MagickXByteOrderToString(ximage->byte_order));
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
        ximage->bitmap_bit_order,ximage->bitmap_pad);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d",
        ximage->depth);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  bytes per line: %d",
        ximage->bytes_per_line);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  bits per pixel: %d",
        ximage->bits_per_pixel);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
        ximage->green_mask,ximage->blue_mask);
    }
  if (!window->shared_memory)
    {
      if (ximage->format == XYBitmap)
        ximage->data=
          MagickAllocateArray(char *,
                              MagickArraySize(ximage->height,ximage->bytes_per_line),
                              ximage->depth);
      else
        ximage->data=
          MagickAllocateArray(char *,ximage->height,ximage->bytes_per_line);
    }
  if (ximage->data == (char *) NULL)
    {
      /*
        Unable to allocate pixel data.
      */
      XDestroyImage(ximage);
      ximage=(XImage *) NULL;
      (void) XDefineCursor(display,window->id,window->cursor);
      return(False);
    }
  if (window->ximage != (XImage *) NULL)
    {
      /*
        Destroy previous X image.
      */
      length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
#if defined(HasSharedMemory)
      if (window->segment_info != (XShmSegmentInfo *) NULL)
        {
          XShmSegmentInfo
            *segment_info;

          segment_info=(XShmSegmentInfo *) window->segment_info;
          if (segment_info[0].shmid >= 0)
            {
              (void) XSync(display,False);
              (void) XShmDetach(display,&segment_info[0]);
              (void) XSync(display,False);
              if (segment_info[0].shmaddr != NULL)
                (void) MagickShmDt(segment_info[0].shmaddr);
              (void) MagickShmCtl(segment_info[0].shmid,IPC_RMID,0);
              segment_info[0].shmaddr=NULL;
              segment_info[0].shmid=(-1);
              window->ximage->data=(char *) NULL;
            }
        }
#endif
      MagickFreeMemory(window->ximage->data);
      XDestroyImage(window->ximage);
      window->ximage=(XImage *) NULL;
    }
#if defined(HasSharedMemory)
  if (window->segment_info != (XShmSegmentInfo *) NULL)
    {
      XShmSegmentInfo
        *segment_info;
      
      segment_info=(XShmSegmentInfo *) window->segment_info;
      segment_info[0]=segment_info[1];
    }
#endif
  window->ximage=ximage;
  matte_image=(XImage *) NULL;
  if (window->shape && (window->image != (Image *) NULL))
    if (window->image->matte &&
        (width <= (unsigned int) XDisplayWidth(display,window->screen)) &&
        (height <= (unsigned int) XDisplayHeight(display,window->screen)))
      {
        /*
          Create matte image.
        */
        matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
          (char *) NULL,width,height,XBitmapPad(display),0);
        if (IsEventLogging())
          {
            (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
            (void) LogMagickEvent(X11Event,GetMagickModule(),
              "  width, height: %dx%d",matte_image->width,matte_image->height);
          }
        if (matte_image != (XImage *) NULL)
          {
            /*
              Allocate matte image pixel data.
            */
            length=MagickArraySize(MagickArraySize(matte_image->bytes_per_line,
                                                   matte_image->height),
                                   matte_image->depth);
            matte_image->data=MagickAllocateMemory(char *,length);
            if (matte_image->data == (char *) NULL)
              {
                XDestroyImage(matte_image);
                matte_image=(XImage *) NULL;
              }
          }
      }
  if (window->matte_image != (XImage *) NULL)
    {
      /*
        Free matte image.
      */
      MagickFreeMemory(window->matte_image->data);
      XDestroyImage(window->matte_image);
      window->matte_image=(XImage *) NULL;
    }
  window->matte_image=matte_image;
  if (window->matte_pixmap != (Pixmap) NULL)
    {
      (void) XFreePixmap(display,window->matte_pixmap);
      window->matte_pixmap=(Pixmap) NULL;
#if defined(HasShape)
      if (window->shape)
        XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
#endif
    }
  window->stasis=False;
  /*
    Convert pixels to X image data.
  */
  if (window->image != (Image *) NULL)
    {
      if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
          (ximage->bitmap_bit_order == LSBFirst)))
        MagickXMakeImageLSBFirst(resource_info,window,window->image,ximage,
          matte_image);
      else
        MagickXMakeImageMSBFirst(resource_info,window,window->image,ximage,
          matte_image);
    }
  if (window->matte_image != (XImage *) NULL)
    {
      /*
        Create matte pixmap.
      */
      window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
      if (window->matte_pixmap != (Pixmap) NULL)
        {
          GC
            graphics_context;

          XGCValues
            context_values;

          /*
            Copy matte image to matte pixmap.
          */
          context_values.background=1;
          context_values.foreground=0;
          graphics_context=XCreateGC(display,window->matte_pixmap,
            GCBackground | GCForeground,&context_values);
          (void) XPutImage(display,window->matte_pixmap,graphics_context,
            window->matte_image,0,0,0,0,width,height);
          (void) XFreeGC(display,graphics_context);
#if defined(HasShape)
          if (window->shape)
            XShapeCombineMask(display,window->id,ShapeBounding,0,0,
              window->matte_pixmap,ShapeSet);
#endif
        }
      }
  (void) MagickXMakePixmap(display,resource_info,window);
  /*
    Restore cursor.
  */
  (void) XDefineCursor(display,window->id,window->cursor);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   M a g i c k X M a k e I m a g e L S B F i r s t                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeImageLSBFirst initializes the pixel data of an X11 Image.
%  The X image pixels are copied in least-significant bit and byte first
%  order.  The server's scanline pad is respected.  Rather than using one or
%  two general cases, many special cases are found here to help speed up the
%  image conversion.
%
%  The format of the MagickXMakeImageLSBFirst method is:
%
%      void MagickXMakeMagnifyImage(Display *display,MagickXWindows *windows)
%
%  A description of each parameter follows:
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo structure.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o ximage: Specifies a pointer to a XImage structure;  returned from
%      XCreateImage.
%
%    o matte_image: Specifies a pointer to a XImage structure;  returned from
%      XCreateImage.
%
*/
static void
MagickXMakeImageLSBFirst(const MagickXResourceInfo *resource_info,
                         const MagickXWindowInfo *window,Image *image,
                         XImage *ximage,XImage *matte_image)
{
  int
    y;

  register const IndexPacket
    *indexes;

  register int
    x;

  register const PixelPacket
    *p;

  register unsigned char
    *q;

  unsigned char
    bit,
    byte;

  unsigned int
    scanline_pad;

  unsigned long
    pixel,
    *pixels;

  XStandardColormap
    *map_info;

  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  assert(image != (Image *) NULL);
  scanline_pad=ximage->bytes_per_line-
    ((ximage->width*ximage->bits_per_pixel) >> 3);
  map_info=window->map_info;
  pixels=window->pixel_info->pixels;
  q=(unsigned char *) ximage->data;
  x=0;
  if (ximage->format == XYBitmap)
    {
      register unsigned short
        polarity;

      unsigned char
        background,
        foreground;

      /*
        Convert image to big-endian bitmap.
      */
      background=(PixelIntensity(&window->pixel_info->foreground_color) <
        PixelIntensity(&window->pixel_info->background_color) ?  0x80 : 0x00);
      foreground=(PixelIntensity(&window->pixel_info->background_color) <
        PixelIntensity(&window->pixel_info->foreground_color) ?  0x80 : 0x00);
      polarity=PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2);
      if (image->colors == 2)
        polarity=PixelIntensity(&image->colormap[0]) <
          PixelIntensity(&image->colormap[1]);
      for (y=0; y < (long) image->rows; y++)
      {
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
        if (p == (const PixelPacket *) NULL)
          break;
        indexes=AccessImmutableIndexes(image);
        bit=0;
        byte=0;
        for (x=0; x < (long) image->columns; x++)
        {
          byte>>=1;
          if (indexes[x] == polarity)
            byte|=foreground;
          else
            byte|=background;
          bit++;
          if (bit == 8)
            {
              *q++=byte;
              bit=0;
              byte=0;
            }
        }
        if (bit != 0)
          *q=byte >> (8-bit);
        q+=scanline_pad;
      }
    }
  else
    if (window->pixel_info->colors != 0)
      switch (ximage->bits_per_pixel)
      {
        case 2:
        {
          register unsigned int
            nibble;

          /*
            Convert to 2 bit color-mapped X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            nibble=0;
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=pixels[indexes[x]] & 0x0f;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) pixel;
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 2);
                  nibble++;
                  break;
                }
                case 2:
                {
                  *q|=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 3:
                {
                  *q|=(unsigned char) (pixel << 6);
                  q++;
                  nibble=0;
                  break;
                }
              }
            }
            q+=scanline_pad;
          }
          break;
        }
        case 4:
        {
          register unsigned int
            nibble;

          /*
            Convert to 4 bit color-mapped X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            nibble=0;
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=pixels[indexes[x]] & 0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) pixel;
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 4);
                  q++;
                  nibble=0;
                  break;
                }
              }
            }
            q+=scanline_pad;
          }
          break;
        }
        case 6:
        case 8:
        {
          /*
            Convert to 8 bit color-mapped X image.
          */
          if (resource_info->color_recovery &&
              resource_info->quantize_info->dither)
            {
              MagickXDitherImage(image,ximage);
              break;
            }
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=pixels[indexes[x]];
              *q++=(unsigned char) pixel;
            }
            q+=scanline_pad;
          }
          break;
        }
        default:
        {
          register int
            k;

          register unsigned int
            bytes_per_pixel;

          unsigned char
            channel[sizeof(unsigned long)];

          /*
            Convert to multi-byte color-mapped X image.
          */
          bytes_per_pixel=ximage->bits_per_pixel >> 3;
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=pixels[indexes[x]];
              for (k=0; k < (int) bytes_per_pixel; k++)
              {
                channel[k]=(unsigned char) pixel;
                pixel>>=8;
              }
              for (k=0; k < (int) bytes_per_pixel; k++)
                *q++=channel[k];
            }
            q+=scanline_pad;
          }
          break;
        }
      }
    else
      switch (ximage->bits_per_pixel)
      {
        case 2:
        {
          register unsigned int
            nibble;

          /*
            Convert to contiguous 2 bit continuous-tone X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            nibble=0;
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=MagickXGammaPixel(map_info,p);
              pixel&=0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) pixel;
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 2);
                  nibble++;
                  break;
                }
                case 2:
                {
                  *q|=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 3:
                {
                  *q|=(unsigned char) (pixel << 6);
                  q++;
                  nibble=0;
                  break;
                }
              }
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        case 4:
        {
          register unsigned int
            nibble;

          /*
            Convert to contiguous 4 bit continuous-tone X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            nibble=0;
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=MagickXGammaPixel(map_info,p);
              pixel&=0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) pixel;
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 4);
                  q++;
                  nibble=0;
                  break;
                }
              }
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        case 6:
        case 8:
        {
          /*
            Convert to contiguous 8 bit continuous-tone X image.
          */
          if (resource_info->color_recovery &&
              resource_info->quantize_info->dither)
            {
              MagickXDitherImage(image,ximage);
              break;
            }
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=MagickXGammaPixel(map_info,p);
              *q++=(unsigned char) pixel;
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        default:
        {
          if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
              (map_info->green_max == 255) && (map_info->blue_max == 255) &&
              (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
              (map_info->blue_mult == 1))
            {
              /*
                Convert to 32 bit continuous-tone X image.
              */
              for (y=0; y < (long) image->rows; y++)
              {
                p=AcquireImagePixels(image,0,y,image->columns,1,
                  &image->exception);
                if (p == (const PixelPacket *) NULL)
                  break;
                if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
                    (blue_gamma != 1.0))
                  {
                    /*
                      Gamma correct image.
                    */
                    for (x=(long) image->columns; x > 0; x--)
                    {
                      *q++=ScaleQuantumToChar(MagickXBlueGamma(p->blue));
                      *q++=ScaleQuantumToChar(MagickXGreenGamma(p->green));
                      *q++=ScaleQuantumToChar(MagickXRedGamma(p->red));
                      *q++=0;
                      p++;
                    }
                    continue;
                  }
                for (x=(long) image->columns; x > 0; x--)
                {
                  *q++=ScaleQuantumToChar((Quantum) p->blue);
                  *q++=ScaleQuantumToChar((Quantum) p->green);
                  *q++=ScaleQuantumToChar((Quantum) p->red);
                  *q++=0;
                  p++;
                }
              }
            }
          else
            if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
                (map_info->green_max == 255) && (map_info->blue_max == 255) &&
                (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
                (map_info->blue_mult == 65536L))
              {
                /*
                  Convert to 32 bit continuous-tone X image.
                */
                for (y=0; y < (long) image->rows; y++)
                {
                  p=AcquireImagePixels(image,0,y,image->columns,1,
                    &image->exception);
                  if (p == (const PixelPacket *) NULL)
                    break;
                  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
                      (blue_gamma != 1.0))
                    {
                      /*
                        Gamma correct image.
                      */
                      for (x=(long) image->columns; x > 0; x--)
                      {
                        *q++=ScaleQuantumToChar(MagickXRedGamma(p->red));
                        *q++=ScaleQuantumToChar(MagickXGreenGamma(p->green));
                        *q++=ScaleQuantumToChar(MagickXBlueGamma(p->blue));
                        *q++=0;
                        p++;
                      }
                      continue;
                    }
                  for (x=(long) image->columns; x > 0; x--)
                  {
                    *q++=ScaleQuantumToChar((Quantum) p->red);
                    *q++=ScaleQuantumToChar((Quantum) p->green);
                    *q++=ScaleQuantumToChar((Quantum) p->blue);
                    *q++=0;
                    p++;
                  }
                }
              }
            else
              {
                register int
                  k;

                register unsigned int
                  bytes_per_pixel;

                unsigned char
                  channel[sizeof(unsigned long)];

                /*
                  Convert to multi-byte continuous-tone X image.
                */
                bytes_per_pixel=ximage->bits_per_pixel >> 3;
                for (y=0; y < (long) image->rows; y++)
                {
                  p=AcquireImagePixels(image,0,y,image->columns,1,
                    &image->exception);
                  if (p == (PixelPacket *) NULL)
                    break;
                  for (x=0; x < (long) image->columns; x++)
                  {
                    pixel=MagickXGammaPixel(map_info,p);
                    for (k=0; k < (int) bytes_per_pixel; k++)
                    {
                      channel[k]=(unsigned char) pixel;
                      pixel>>=8;
                    }
                    for (k=0; k < (int) bytes_per_pixel; k++)
                      *q++=channel[k];
                    p++;
                  }
                  q+=scanline_pad;
                }
              }
          break;
        }
      }
  if (matte_image != (XImage *) NULL)
    {
      /*
        Initialize matte image.
      */
      scanline_pad=matte_image->bytes_per_line-
        ((matte_image->width*matte_image->bits_per_pixel) >> 3);
      q=(unsigned char *) matte_image->data;
      for (y=0; y < (long) image->rows; y++)
      {
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
        if (p == (const PixelPacket *) NULL)
          break;
        bit=0;
        byte=0;
        for (x=0; x < (long) image->columns; x++)
        {
          byte>>=1;
          if (p->opacity == TransparentOpacity)
            byte|=0x80;
          bit++;
          if (bit == 8)
            {
              *q++=byte;
              bit=0;
              byte=0;
            }
          p++;
        }
        if (bit != 0)
          *q=byte >> (8-bit);
        q+=scanline_pad;
      }
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   M a g i c k X M a k e I m a g e M S B F i r s t                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeImageMSBFirst initializes the pixel data of an X11 Image.
%  The X image pixels are copied in most-significant bit and byte first order.
%  The server's scanline pad is also respected. Rather than using one or two
%  general cases, many special cases are found here to help speed up the image
%  conversion.
%
%  The format of the MagickXMakeImageMSBFirst method is:
%
%      MagickXMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
%
%  A description of each parameter follows:
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o ximage: Specifies a pointer to a XImage structure;  returned from
%      XCreateImage.
%
%    o matte_image: Specifies a pointer to a XImage structure;  returned from
%      XCreateImage.
%
%
*/
static void
MagickXMakeImageMSBFirst(const MagickXResourceInfo *resource_info,
                         const MagickXWindowInfo *window,Image *image,
                         XImage *ximage,XImage *matte_image)
{
  int
    y;

  register const IndexPacket
    *indexes;

  register int
    x;

  register const PixelPacket
    *p;

  register unsigned char
    *q;

  unsigned char
    bit,
    byte;

  unsigned int
    scanline_pad;

  unsigned long
    pixel,
    *pixels;

  XStandardColormap
    *map_info;

  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  assert(image != (Image *) NULL);
  scanline_pad=ximage->bytes_per_line-
    ((ximage->width*ximage->bits_per_pixel) >> 3);
  map_info=window->map_info;
  pixels=window->pixel_info->pixels;
  q=(unsigned char *) ximage->data;
  x=0;
  if (ximage->format == XYBitmap)
    {
      register unsigned short
        polarity;

      unsigned char
        background,
        foreground;

      /*
        Convert image to big-endian bitmap.
      */
      background=(PixelIntensity(&window->pixel_info->foreground_color) <
        PixelIntensity(&window->pixel_info->background_color) ?  0x01 : 0x00);
      foreground=(PixelIntensity(&window->pixel_info->background_color) <
        PixelIntensity(&window->pixel_info->foreground_color) ?  0x01 : 0x00);
      polarity=PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2);
      if (image->colors == 2)
        polarity=PixelIntensity(&image->colormap[0]) <
          PixelIntensity(&image->colormap[1]);
      for (y=0; y < (long) image->rows; y++)
      {
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
        if (p == (const PixelPacket *) NULL)
          break;
        indexes=AccessImmutableIndexes(image);
        bit=0;
        byte=0;
        for (x=(long) image->columns; x > 0; x--)
        {
          byte<<=1;
          if (*indexes++ == polarity)
            byte|=foreground;
          else
            byte|=background;
          bit++;
          if (bit == 8)
            {
              *q++=byte;
              bit=0;
              byte=0;
            }
        }
        if (bit != 0)
          *q=byte << (8-bit);
        q+=scanline_pad;
      }
    }
  else
    if (window->pixel_info->colors != 0)
      switch (ximage->bits_per_pixel)
      {
        case 2:
        {
          register unsigned int
            nibble;

          /*
            Convert to 2 bit color-mapped X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            nibble=0;
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=pixels[*indexes++] & 0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) (pixel << 6);
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 2:
                {
                  *q|=(unsigned char) (pixel << 2);
                  nibble++;
                  break;
                }
                case 3:
                {
                  *q|=(unsigned char) pixel;
                  q++;
                  nibble=0;
                  break;
                }
              }
            }
            q+=scanline_pad;
          }
          break;
        }
        case 4:
        {
          register unsigned int
            nibble;

          /*
            Convert to 4 bit color-mapped X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            nibble=0;
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=pixels[*indexes++] & 0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) pixel;
                  q++;
                  nibble=0;
                  break;
                }
              }
            }
            q+=scanline_pad;
          }
          break;
        }
        case 6:
        case 8:
        {
          /*
            Convert to 8 bit color-mapped X image.
          */
          if (resource_info->color_recovery &&
              resource_info->quantize_info->dither)
            {
              MagickXDitherImage(image,ximage);
              break;
            }
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            for (x=(long) image->columns; x > 0; x--)
              *q++=(unsigned char) (pixels[*indexes++]);
            q+=scanline_pad;
          }
          break;
        }
        default:
        {
          register int
            k;

          register unsigned int
            bytes_per_pixel;

          unsigned char
            channel[sizeof(unsigned long)];

          /*
            Convert to 8 bit color-mapped X image.
          */
          bytes_per_pixel=ximage->bits_per_pixel >> 3;
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=pixels[*indexes++];
              for (k=bytes_per_pixel-1; k >= 0; k--)
              {
                channel[k]=(unsigned char) pixel;
                pixel>>=8;
              }
              for (k=0; k < (int) bytes_per_pixel; k++)
                *q++=channel[k];
            }
            q+=scanline_pad;
          }
          break;
        }
      }
    else
      switch (ximage->bits_per_pixel)
      {
        case 2:
        {
          register unsigned int
            nibble;

          /*
            Convert to 4 bit continuous-tone X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            nibble=0;
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=MagickXGammaPixel(map_info,p);
              pixel&=0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) (pixel << 6);
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 2:
                {
                  *q|=(unsigned char) (pixel << 2);
                  nibble++;
                  break;
                }
                case 3:
                {
                  *q|=(unsigned char) pixel;
                  q++;
                  nibble=0;
                  break;
                }
              }
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        case 4:
        {
          register unsigned int
            nibble;

          /*
            Convert to 4 bit continuous-tone X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            nibble=0;
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=MagickXGammaPixel(map_info,p);
              pixel&=0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) pixel;
                  q++;
                  nibble=0;
                  break;
                }
              }
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        case 6:
        case 8:
        {
          /*
            Convert to 8 bit continuous-tone X image.
          */
          if (resource_info->color_recovery &&
              resource_info->quantize_info->dither)
            {
              MagickXDitherImage(image,ximage);
              break;
            }
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=MagickXGammaPixel(map_info,p);
              *q++=(unsigned char) pixel;
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        default:
        {
          if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
              (map_info->green_max == 255) && (map_info->blue_max == 255) &&
              (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
              (map_info->blue_mult == 1))
            {
              /*
                Convert to 32 bit continuous-tone X image.
              */
              for (y=0; y < (long) image->rows; y++)
              {
                p=AcquireImagePixels(image,0,y,image->columns,1,
                  &image->exception);
                if (p == (const PixelPacket *) NULL)
                  break;
                if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
                    (blue_gamma != 1.0))
                  {
                    /*
                      Gamma correct image.
                    */
                    for (x=(long) image->columns; x > 0; x--)
                    {
                      *q++=0;
                      *q++=ScaleQuantumToChar(MagickXRedGamma(p->red));
                      *q++=ScaleQuantumToChar(MagickXGreenGamma(p->green));
                      *q++=ScaleQuantumToChar(MagickXBlueGamma(p->blue));
                      p++;
                    }
                    continue;
                  }
                for (x=(long) image->columns; x > 0; x--)
                {
                  *q++=0;
                  *q++=ScaleQuantumToChar((Quantum) p->red);
                  *q++=ScaleQuantumToChar((Quantum) p->green);
                  *q++=ScaleQuantumToChar((Quantum) p->blue);
                  p++;
                }
              }
            }
          else
            if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
                (map_info->green_max == 255) && (map_info->blue_max == 255) &&
                (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
                (map_info->blue_mult == 65536L))
              {
                /*
                  Convert to 32 bit continuous-tone X image.
                */
                for (y=0; y < (long) image->rows; y++)
                {
                  p=AcquireImagePixels(image,0,y,image->columns,1,
                    &image->exception);
                  if (p == (const PixelPacket *) NULL)
                    break;
                  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
                      (blue_gamma != 1.0))
                    {
                      /*
                        Gamma correct image.
                      */
                      for (x=(long) image->columns; x > 0; x--)
                      {
                        *q++=0;
                        *q++=ScaleQuantumToChar(MagickXBlueGamma(p->blue));
                        *q++=ScaleQuantumToChar(MagickXGreenGamma(p->green));
                        *q++=ScaleQuantumToChar(MagickXRedGamma(p->red));
                        p++;
                      }
                      continue;
                    }
                  for (x=(long) image->columns; x > 0; x--)
                  {
                    *q++=0;
                    *q++=ScaleQuantumToChar((Quantum) p->blue);
                    *q++=ScaleQuantumToChar((Quantum) p->green);
                    *q++=ScaleQuantumToChar((Quantum) p->red);
                    p++;
                  }
                }
              }
            else
              {
                register int
                  k;

                register unsigned int
                  bytes_per_pixel;

                unsigned char
                  channel[sizeof(unsigned long)];

                /*
                  Convert to multi-byte continuous-tone X image.
                */
                bytes_per_pixel=ximage->bits_per_pixel >> 3;
                for (y=0; y < (long) image->rows; y++)
                {
                  p=AcquireImagePixels(image,0,y,image->columns,1,
                    &image->exception);
                  if (p == (const PixelPacket *) NULL)
                    break;
                  for (x=(long) image->columns; x > 0; x--)
                  {
                    pixel=MagickXGammaPixel(map_info,p);
                    for (k=bytes_per_pixel-1; k >= 0; k--)
                    {
                      channel[k]=(unsigned char) pixel;
                      pixel>>=8;
                    }
                    for (k=0; k < (int) bytes_per_pixel; k++)
                      *q++=channel[k];
                    p++;
                  }
                  q+=scanline_pad;
                }
              }
          break;
        }
      }
  if (matte_image != (XImage *) NULL)
    {
      /*
        Initialize matte image.
      */
      scanline_pad=matte_image->bytes_per_line-
        ((matte_image->width*matte_image->bits_per_pixel) >> 3);
      q=(unsigned char *) matte_image->data;
      for (y=0; y < (long) image->rows; y++)
      {
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
        if (p == (const PixelPacket *) NULL)
          break;
        bit=0;
        byte=0;
        for (x=(long) image->columns; x > 0; x--)
        {
          byte<<=1;
          if (p->opacity == TransparentOpacity)
            byte|=0x01;
          bit++;
          if (bit == 8)
            {
              *q++=byte;
              bit=0;
              byte=0;
            }
          p++;
        }
        if (bit != 0)
          *q=byte << (8-bit);
        q+=scanline_pad;
      }
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e M a g n i f y I m a g e                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeMagnifyImage magnifies a region of an X image and
%  displays it.
%
%  The format of the MagickXMakeMagnifyImage method is:
%
%      MagickXMakeMagnifyImage(display,windows)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%
*/
MagickExport void 
MagickXMakeMagnifyImage(Display *display,MagickXWindows *windows)
{
  char
    tuple[MaxTextExtent];

  int
    y;

  long
    n;

  register int
    x;

  register long
    i;

  register unsigned char
    *p,
    *q;

  PixelPacket
    color;

  static char
    text[MaxTextExtent];

  static unsigned int
    previous_magnify = 0;

  static MagickXWindowInfo
    magnify_window;

  unsigned int
    height,
    j,
    k,
    l,
    magnify,
    scanline_pad,
    width;

  XImage
    *ximage;

  /*
    Check boundary conditions.
  */
  assert(display != (Display *) NULL);
  assert(windows != (MagickXWindows *) NULL);
  magnify=1;
  for (n=1; n < (long) windows->magnify.data; n++)
    magnify<<=1;
  while ((magnify*windows->image.ximage->width) < windows->magnify.width)
    magnify<<=1;
  while ((magnify*windows->image.ximage->height) < windows->magnify.height)
    magnify<<=1;
  while (magnify > windows->magnify.width)
    magnify>>=1;
  while (magnify > windows->magnify.height)
    magnify>>=1;
  if (magnify != previous_magnify)
    {
      unsigned int
        status;

      XTextProperty
        window_name;

      /*
        New magnify factor:  update magnify window name.
      */
      i=0;
      while ((1 << i) <= (int) magnify)
        i++;
      FormatString(windows->magnify.name,"Magnify %luX",i);
      status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
      if (status != 0)
        {
          XSetWMName(display,windows->magnify.id,&window_name);
          XSetWMIconName(display,windows->magnify.id,&window_name);
          (void) XFree((void *) window_name.value);
        }
    }
  previous_magnify=magnify;
  ximage=windows->image.ximage;
  width=windows->magnify.ximage->width;
  height=windows->magnify.ximage->height;
  if ((windows->magnify.x < 0) ||
      (windows->magnify.x >= windows->image.ximage->width))
    windows->magnify.x=windows->image.ximage->width >> 1;
  x=windows->magnify.x-((width/magnify) >> 1);
  if (x < 0)
    x=0;
  else
    if (x > (int) (ximage->width-(width/magnify)))
      x=ximage->width-width/magnify;
  if ((windows->magnify.y < 0) ||
      (windows->magnify.y >= windows->image.ximage->height))
    windows->magnify.y=windows->image.ximage->height >> 1;
  y=windows->magnify.y-((height/magnify) >> 1);
  if (y < 0)
    y=0;
  else
    if (y > (int) (ximage->height-(height/magnify)))
      y=ximage->height-height/magnify;
  q=(unsigned char *) windows->magnify.ximage->data;
  scanline_pad=windows->magnify.ximage->bytes_per_line-
    ((width*windows->magnify.ximage->bits_per_pixel) >> 3);
  if (ximage->bits_per_pixel < 8)
    {
      register unsigned char
        background,
        byte,
        foreground,
        p_bit,
        q_bit;

      register unsigned int
        plane;

      MagickXPixelInfo
        *pixel_info;

      pixel_info=windows->magnify.pixel_info;
      switch (ximage->bitmap_bit_order)
      {
        case LSBFirst:
        {
          /*
            Magnify little-endian bitmap.
          */
          background=0x00;
          foreground=0x80;
          if (ximage->format == XYBitmap)
            {
              background=(PixelIntensity(&pixel_info->foreground_color) <
                PixelIntensity(&pixel_info->background_color) ?  0x80 : 0x00);
              foreground=(PixelIntensity(&pixel_info->background_color) <
                PixelIntensity(&pixel_info->foreground_color) ?  0x80 : 0x00);
              if (windows->magnify.depth > 1)
                Swap(background,foreground);
            }
          for (i=0; i < (long) height; i+=magnify)
          {
            /*
              Propogate pixel magnify rows.
            */
            for (j=0; j < magnify; j++)
            {
              p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
                ((x*ximage->bits_per_pixel) >> 3);
              p_bit=(x*ximage->bits_per_pixel) & 0x07;
              q_bit=0;
              byte=0;
              for (k=0; k < width; k+=magnify)
              {
                /*
                  Propogate pixel magnify columns.
                */
                for (l=0; l < magnify; l++)
                {
                  /*
                    Propogate each bit plane.
                  */
                  for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
                  {
                    byte>>=1;
                    if (*p & (0x01 << (p_bit+plane)))
                      byte|=foreground;
                    else
                      byte|=background;
                    q_bit++;
                    if (q_bit == 8)
                      {
                        *q++=byte;
                        q_bit=0;
                        byte=0;
                      }
                  }
                }
                p_bit+=ximage->bits_per_pixel;
                if (p_bit == 8)
                  {
                    p++;
                    p_bit=0;
                  }
                if (q_bit != 0)
                  *q=byte >> (8-q_bit);
                q+=scanline_pad;
              }
            }
            y++;
          }
          break;
        }
        case MSBFirst:
        default:
        {
          /*
            Magnify big-endian bitmap.
          */
          background=0x00;
          foreground=0x01;
          if (ximage->format == XYBitmap)
            {
              background=(PixelIntensity(&pixel_info->foreground_color) <
                PixelIntensity(&pixel_info->background_color) ?  0x01 : 0x00);
              foreground=(PixelIntensity(&pixel_info->background_color) <
                PixelIntensity(&pixel_info->foreground_color) ?  0x01 : 0x00);
              if (windows->magnify.depth > 1)
                Swap(background,foreground);
            }
          for (i=0; i < (long) height; i+=magnify)
          {
            /*
              Propogate pixel magnify rows.
            */
            for (j=0; j < magnify; j++)
            {
              p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
                ((x*ximage->bits_per_pixel) >> 3);
              p_bit=(x*ximage->bits_per_pixel) & 0x07;
              q_bit=0;
              byte=0;
              for (k=0; k < width; k+=magnify)
              {
                /*
                  Propogate pixel magnify columns.
                */
                for (l=0; l < magnify; l++)
                {
                  /*
                    Propogate each bit plane.
                  */
                  for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
                  {
                    byte<<=1;
                    if (*p & (0x80 >> (p_bit+plane)))
                      byte|=foreground;
                    else
                      byte|=background;
                    q_bit++;
                    if (q_bit == 8)
                      {
                        *q++=byte;
                        q_bit=0;
                        byte=0;
                      }
                  }
                }
                p_bit+=ximage->bits_per_pixel;
                if (p_bit == 8)
                  {
                    p++;
                    p_bit=0;
                  }
                if (q_bit != 0)
                  *q=byte << (8-q_bit);
                q+=scanline_pad;
              }
            }
            y++;
          }
          break;
        }
      }
    }
  else
    switch (ximage->bits_per_pixel)
    {
      case 6:
      case 8:
      {
        /*
          Magnify 8 bit X image.
        */
        for (i=0; i < (long) height; i+=magnify)
        {
          /*
            Propogate pixel magnify rows.
          */
          for (j=0; j < magnify; j++)
          {
            p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
              ((x*ximage->bits_per_pixel) >> 3);
            for (k=0; k < width; k+=magnify)
            {
              /*
                Propogate pixel magnify columns.
              */
              for (l=0; l < magnify; l++)
                *q++=(*p);
              p++;
            }
            q+=scanline_pad;
          }
          y++;
        }
        break;
      }
      default:
      {
        register unsigned int
          bytes_per_pixel,
          m;

        /*
          Magnify multi-byte X image.
        */
        bytes_per_pixel=ximage->bits_per_pixel >> 3;
        for (i=0; i < (long) height; i+=magnify)
        {
          /*
            Propogate pixel magnify rows.
          */
          for (j=0; j < magnify; j++)
          {
            p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
              ((x*ximage->bits_per_pixel) >> 3);
            for (k=0; k < width; k+=magnify)
            {
              /*
                Propogate pixel magnify columns.
              */
              for (l=0; l < magnify; l++)
                for (m=0; m < bytes_per_pixel; m++)
                  *q++=(*(p+m));
              p+=bytes_per_pixel;
            }
            q+=scanline_pad;
          }
          y++;
        }
        break;
      }
    }
  /*
    Copy X image to magnify pixmap.
  */
  x=windows->magnify.x-((width/magnify) >> 1);
  if (x < 0)
    x=(width >> 1)-windows->magnify.x*magnify;
  else
    if (x > (int) (ximage->width-(width/magnify)))
      x=(ximage->width-windows->magnify.x)*magnify-(width >> 1);
    else
      x=0;
  y=windows->magnify.y-((height/magnify) >> 1);
  if (y < 0)
    y=(height >> 1)-windows->magnify.y*magnify;
  else
    if (y > (int) (ximage->height-(height/magnify)))
      y=(ximage->height-windows->magnify.y)*magnify-(height >> 1);
    else
      y=0;
  if ((x != 0) || (y != 0))
    (void) XFillRectangle(display,windows->magnify.pixmap,
      windows->magnify.annotate_context,0,0,width,height);
  (void) XPutImage(display,windows->magnify.pixmap,
    windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
    height-y);
  if ((magnify > 1) && ((magnify <= (width >> 1)) &&
      (magnify <= (height >> 1))))
    {
      RectangleInfo
        highlight_info;

      /*
        Highlight center pixel.
      */
      highlight_info.x=(long) windows->magnify.width >> 1;
      highlight_info.y=(long) windows->magnify.height >> 1;
      highlight_info.width=magnify;
      highlight_info.height=magnify;
      (void) XDrawRectangle(display,windows->magnify.pixmap,
        windows->magnify.highlight_context,(int) highlight_info.x,
        (int) highlight_info.y,(unsigned int) highlight_info.width-1,
        (unsigned int) highlight_info.height-1);
      if (magnify > 2)
        (void) XDrawRectangle(display,windows->magnify.pixmap,
          windows->magnify.annotate_context,(int) highlight_info.x+1,
          (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
          (unsigned int) highlight_info.height-3);
    }
  /*
    Show center pixel color.
  */
  (void) AcquireOnePixelByReference(windows->image.image,&color,windows->magnify.x,
                        windows->magnify.y,&windows->image.image->exception);
  GetColorTuple(&color,windows->image.image->depth,windows->image.image->matte,
    False,tuple);
  FormatString(text," %+d%+d  %.1024s ",windows->magnify.x,windows->magnify.y,
    tuple);
  height=windows->magnify.font_info->ascent+windows->magnify.font_info->descent;
  x=windows->magnify.font_info->max_bounds.width >> 1;
  y=windows->magnify.font_info->ascent+(height >> 2);
  (void) XDrawImageString(display,windows->magnify.pixmap,
    windows->magnify.annotate_context,x,y,text,(int) strlen(text));
  y+=height;
  (void) QueryColorname(windows->image.image,&color,X11Compliance,text,
    &windows->image.image->exception);
  (void) XDrawImageString(display,windows->magnify.pixmap,
    windows->magnify.annotate_context,x,y,text,(int) strlen(text));
  /*
    Refresh magnify window.
  */
  magnify_window=windows->magnify;
  magnify_window.x=0;
  magnify_window.y=0;
  MagickXRefreshWindow(display,&magnify_window,(XEvent *) NULL);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e P i x m a p                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakePixmap creates an X11 pixmap.
%
%  The format of the MagickXMakePixmap method is:
%
%      unsigned int MagickXMakePixmap(Display *display,
%                                     const MagickXResourceInfo *resource_info,
%                                     MagickXWindowInfo *window)
%
%  A description of each parameter follows:
%
%    o status: Method MagickXMakePixmap returns True if the X pixmap is
%      successfully created.  False is returned is there is a memory shortage.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%
*/
static unsigned int
MagickXMakePixmap(Display *display,
                  const MagickXResourceInfo *resource_info,
                  MagickXWindowInfo *window)
{
  unsigned int
    height,
    width;

  assert(display != (Display *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(window != (MagickXWindowInfo  *) NULL);
  if (window->pixmap != (Pixmap) NULL)
    {
      /*
        Destroy previous X pixmap.
      */
      (void) XFreePixmap(display,window->pixmap);
      window->pixmap=(Pixmap) NULL;
    }
  if (!window->use_pixmap)
    return(False);
  if (window->ximage == (XImage *) NULL)
    return(False);
  /*
    Display busy cursor.
  */
  (void) XDefineCursor(display,window->id,window->busy_cursor);
  (void) XFlush(display);
  /*
    Create pixmap.
  */
  width=window->ximage->width;
  height=window->ximage->height;
  window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
  if (window->pixmap == (Pixmap) NULL)
    {
      /*
        Unable to allocate pixmap.
      */
      (void) XDefineCursor(display,window->id,window->cursor);
      return(False);
    }
  /*
    Copy X image to pixmap.
  */
#if defined(HasSharedMemory)
  if (window->shared_memory)
    (void) XShmPutImage(display,window->pixmap,window->annotate_context,window->ximage,
      0,0,0,0,width,height,True);
#endif
  if (!window->shared_memory)
    (void) XPutImage(display,window->pixmap,window->annotate_context,
      window->ximage,0,0,0,0,width,height);
  if (IsEventLogging())
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %ux%u",
        width,height);
    }
  /*
    Restore cursor.
  */
  (void) XDefineCursor(display,window->id,window->cursor);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e S t a n d a r d C o l o r m a p                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeStandardColormap creates an X11 Standard Colormap.
%
%  The format of the MagickXMakeStandardColormap method is:
%
%      MagickXMakeStandardColormap(display,visual_info,resource_info,image,
%        map_info,pixel)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o map_info: If a Standard Colormap type is specified, this structure is
%      initialized with info from the Standard Colormap.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%
*/

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

static int IntensityCompare(const void *x,const void *y)
{
  DiversityPacket
    *color_1,
    *color_2;

  color_1=(DiversityPacket *) x;
  color_2=(DiversityPacket *) y;
  return((int) (PixelIntensity(color_2)-PixelIntensity(color_1)));
}

static int PopularityCompare(const void *x,const void *y)
{
  DiversityPacket
    *color_1,
    *color_2;

  color_1=(DiversityPacket *) x;
  color_2=(DiversityPacket *) y;
  return((int) color_2->count-(int) color_1->count);
}

#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

MagickExport void
MagickXMakeStandardColormap(Display *display,
                            XVisualInfo *visual_info,
                            MagickXResourceInfo *resource_info,
                            Image *image,
                            XStandardColormap *map_info,
                            MagickXPixelInfo *pixel)
{
  Colormap
    colormap;

  int
    status;

  register IndexPacket
    *indexes;

  register PixelPacket
    *q;

  register long
    i;

  unsigned long
    number_colors,
    retain_colors;

  unsigned short
    gray_value;

  XColor
    color,
    *colors,
    *p;

  assert(display != (Display *) NULL);
  assert(visual_info != (XVisualInfo *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(pixel != (MagickXPixelInfo *) NULL);
  if (resource_info->map_type != (char *) NULL)
    {
      /*
        Standard Colormap is already defined (i.e. xstdcmap).
      */
      MagickXGetPixelPacket(display,visual_info,map_info,resource_info,image,
        pixel);
      number_colors=(unsigned int) (map_info->base_pixel+
        (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
      if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
        if (!image->matte && !resource_info->color_recovery &&
            resource_info->quantize_info->dither &&
            (number_colors < MaxColormapSize))
          {
            Image
              *map_image;

            /*
              Improve image appearance with error diffusion.
            */
            map_image=AllocateImage((ImageInfo *) NULL);
            if (map_image == (Image *) NULL)
              MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
                MagickMsg(XServerFatalError,UnableToDitherImage));
            map_image->columns=number_colors;
            map_image->rows=1;
            /*
              Initialize colormap image.
            */
            q=SetImagePixels(map_image,0,0,map_image->columns,1);
            if (q != (PixelPacket *) NULL)
              {
                for (i=0; i < (long) number_colors; i++)
                {
                  q->red=0;
                  if (map_info->red_max != 0)
                    q->red=(Quantum) (((double) MaxRGB*
                      (i/map_info->red_mult))/map_info->red_max+0.5);
                  q->green=0;
                  if (map_info->green_max != 0)
                    q->green=(Quantum) (((double) MaxRGB*
                      ((i/map_info->green_mult) % (map_info->green_max+1)))/
                      map_info->green_max+0.5);
                  q->blue=0;
                  if (map_info->blue_max != 0)
                    q->blue=(Quantum) (((double) MaxRGB*
                      (i % map_info->green_mult))/map_info->blue_max+0.5);
                  q->opacity=TransparentOpacity;
                  q++;
                }
                (void) SyncImagePixels(map_image);
                (void) MapImage(image,map_image,True);
              }
            MagickXGetPixelPacket(display,visual_info,map_info,resource_info,image,
              pixel);
            (void) SetImageType(image,TrueColorType);
            DestroyImage(map_image);
          }
      if (IsEventLogging())
        {
          (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
          (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
            map_info->colormap);
          (void) LogMagickEvent(X11Event,GetMagickModule(),
            "  red, green, blue max: %lu %lu %lu",map_info->red_max,
            map_info->green_max,map_info->blue_max);
          (void) LogMagickEvent(X11Event,GetMagickModule(),
            "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
            map_info->green_mult,map_info->blue_mult);
        }
      return;
    }
  if ((visual_info->class != DirectColor) &&
      (visual_info->class != TrueColor))
    if ((image->storage_class == DirectClass) ||
        ((int) image->colors > visual_info->colormap_size))
      {
        QuantizeInfo
          quantize_info;

        /*
          Image has more colors than the visual supports.
        */
        quantize_info=(*resource_info->quantize_info);
        quantize_info.number_colors=visual_info->colormap_size;
        (void) QuantizeImage(&quantize_info,image);
      }
  /*
    Free previous and create new colormap.
  */
  (void) MagickXFreeStandardColormap(display,visual_info,map_info,pixel);
  colormap=XDefaultColormap(display,visual_info->screen);
  if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
    colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
      visual_info->visual,visual_info->class == DirectColor ?
      AllocAll : AllocNone);
  if (colormap == (Colormap) NULL)
    MagickFatalError3(ResourceLimitError,MemoryAllocationFailed,
      UnableToCreateColormap);
  /*
    Initialize the map and pixel info structures.
  */
  MagickXGetMapInfo(visual_info,colormap,map_info);
  MagickXGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
  /*
    Allocating colors in server colormap is based on visual class.
  */
  switch (visual_info->class)
  {
    case StaticGray:
    case StaticColor:
    {
      /*
        Define Standard Colormap for StaticGray or StaticColor visual.
      */
      number_colors=image->colors;
      colors=MagickAllocateArray(XColor *,
                                 visual_info->colormap_size,sizeof(XColor));
      if (colors == (XColor *) NULL)
        MagickFatalError3(ResourceLimitError,MemoryAllocationFailed,
          UnableToCreateColormap);
      p=colors;
      color.flags=DoRed | DoGreen | DoBlue;
      for (i=0; i < (long) image->colors; i++)
      {
        color.red=ScaleQuantumToShort(MagickXRedGamma(image->colormap[i].red));
        color.green=ScaleQuantumToShort(MagickXGreenGamma(image->colormap[i].green));
        color.blue=ScaleQuantumToShort(MagickXBlueGamma(image->colormap[i].blue));
        if (visual_info->class != StaticColor)
          {
            gray_value=(unsigned short) PixelIntensity(&color);
            color.red=gray_value;
            color.green=gray_value;
            color.blue=gray_value;
          }
        status=XAllocColor(display,colormap,&color);
        if (status == 0)
          {
            colormap=XCopyColormapAndFree(display,colormap);
            (void) XAllocColor(display,colormap,&color);
          }
        pixel->pixels[i]=color.pixel;
        *p++=color;
      }
      break;
    }
    case GrayScale:
    case PseudoColor:
    {
      unsigned int
        colormap_type;

      /*
        Define Standard Colormap for GrayScale or PseudoColor visual.
      */
      number_colors=image->colors;
      colors=MagickAllocateArray(XColor *,
                                 visual_info->colormap_size,sizeof(XColor));
      if (colors == (XColor *) NULL)
        MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
          UnableToCreateColormap);
      /*
        Preallocate our GUI colors.
      */
      (void) XAllocColor(display,colormap,&pixel->foreground_color);
      (void) XAllocColor(display,colormap,&pixel->background_color);
      (void) XAllocColor(display,colormap,&pixel->border_color);
      (void) XAllocColor(display,colormap,&pixel->matte_color);
      (void) XAllocColor(display,colormap,&pixel->highlight_color);
      (void) XAllocColor(display,colormap,&pixel->shadow_color);
      (void) XAllocColor(display,colormap,&pixel->depth_color);
      (void) XAllocColor(display,colormap,&pixel->trough_color);
      for (i=0; i < MaxNumberPens; i++)
        (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
      /*
        Determine if image colors will "fit" into X server colormap.
      */
      colormap_type=resource_info->colormap;
      status=XAllocColorCells(display,colormap,False,(unsigned long *) NULL,0,
        pixel->pixels,(int) image->colors);
      if (status != 0)
        colormap_type=PrivateColormap;
      if (colormap_type == SharedColormap)
        {
          DiversityPacket
            *diversity;

          int
            y;

          register int
            x;

          unsigned short
            colormap_index;

          XColor
            *server_colors;

          /*
            Define Standard colormap for shared GrayScale or PseudoColor visual.
          */
          diversity=MagickAllocateArray(DiversityPacket *,
                                        image->colors,sizeof(DiversityPacket));
          if (diversity == (DiversityPacket *) NULL)
            MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
              UnableToCreateColormap);
          for (i=0; i < (long) image->colors; i++)
          {
            diversity[i].red=image->colormap[i].red;
            diversity[i].green=image->colormap[i].green;
            diversity[i].blue=image->colormap[i].blue;
            diversity[i].index=(unsigned short) i;
            diversity[i].count=0;
          }
          for (y=0; y < (long) image->rows; y++)
          {
            q=GetImagePixels(image,0,y,image->columns,1);
            if (q == (PixelPacket *) NULL)
              break;
            indexes=AccessMutableIndexes(image);
            for (x=0; x < (long) image->columns; x++)
              diversity[indexes[x]].count++;
          }
          /*
            Sort colors by decreasing intensity.
          */
          qsort((void *) diversity,image->colors,sizeof(DiversityPacket),
            IntensityCompare);
          for (i=0; i < (long) image->colors; i+=Max(image->colors >> 4,2))
            diversity[i].count<<=4;  /* increase this colors popularity */
          diversity[image->colors-1].count<<=4;
          qsort((void *) diversity,image->colors,sizeof(DiversityPacket),
            PopularityCompare);
          /*
            Allocate colors.
          */
          p=colors;
          color.flags=DoRed | DoGreen | DoBlue;
          for (i=0; i < (long) image->colors; i++)
          {
            colormap_index=diversity[i].index;
            color.red=
              ScaleQuantumToShort(MagickXRedGamma(image->colormap[colormap_index].red));
            color.green=
              ScaleQuantumToShort(MagickXGreenGamma(image->colormap[colormap_index].green));
            color.blue=
              ScaleQuantumToShort(MagickXBlueGamma(image->colormap[colormap_index].blue));
            if (visual_info->class != PseudoColor)
              {
                gray_value=(unsigned short) PixelIntensity(&color);
                color.red=gray_value;
                color.green=gray_value;
                color.blue=gray_value;
              }
            status=XAllocColor(display,colormap,&color);
            if (status == 0)
              break;
            pixel->pixels[colormap_index]=color.pixel;
            *p++=color;
          }
          /*
            Read X server colormap.
          */
          server_colors=MagickAllocateArray(XColor *,
                                            visual_info->colormap_size,
                                            sizeof(XColor));
          if (server_colors == (XColor *) NULL)
            MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
              UnableToCreateColormap);
          for (x=0; x < visual_info->colormap_size; x++)
            server_colors[x].pixel=(unsigned long) x;
          (void) XQueryColors(display,colormap,server_colors,
            (int) Min(visual_info->colormap_size,256));
          /*
            Select remaining colors from X server colormap.
          */
          for (; i < (long) image->colors; i++)
          {
            colormap_index=diversity[i].index;
            color.red=
              ScaleQuantumToShort(MagickXRedGamma(image->colormap[colormap_index].red));
            color.green=
              ScaleQuantumToShort(MagickXGreenGamma(image->colormap[colormap_index].green));
            color.blue=
              ScaleQuantumToShort(MagickXBlueGamma(image->colormap[colormap_index].blue));
            if (visual_info->class != PseudoColor)
              {
                gray_value=(unsigned short) PixelIntensity(&color);
                color.red=gray_value;
                color.green=gray_value;
                color.blue=gray_value;
              }
            MagickXBestPixel(display,colormap,server_colors,(unsigned int)
              visual_info->colormap_size,&color);
            pixel->pixels[colormap_index]=color.pixel;
            *p++=color;
          }
          if ((int) image->colors < visual_info->colormap_size)
            {
              /*
                Fill up colors array-- more choices for pen colors.
              */
              retain_colors=Min(visual_info->colormap_size-image->colors,256);
              for (i=0; i < (long) retain_colors; i++)
                *p++=server_colors[i];
              number_colors+=retain_colors;
            }
          MagickFreeMemory(server_colors);
          MagickFreeMemory(diversity);
          break;
        }
      /*
        Define Standard colormap for private GrayScale or PseudoColor visual.
      */
      if (status == 0)
        {
          /*
            Not enough colormap entries in the colormap-- Create a new colormap.
          */
          colormap=XCreateColormap(display,
            XRootWindow(display,visual_info->screen),visual_info->visual,
            AllocNone);
          if (colormap == (Colormap) NULL)
            MagickFatalError3(ResourceLimitError,MemoryAllocationFailed,
              UnableToCreateColormap);
          map_info->colormap=colormap;
          if ((int) image->colors < visual_info->colormap_size)
            {
              /*
                Retain colors from the default colormap to help lessens the
                effects of colormap flashing.
              */
              retain_colors=Min(visual_info->colormap_size-image->colors,256);
              p=colors+image->colors;
              for (i=0; i < (long) retain_colors; i++)
              {
                p->pixel=(unsigned long) i;
                p++;
              }
              (void) XQueryColors(display,
                XDefaultColormap(display,visual_info->screen),
                colors+image->colors,(int) retain_colors);
              /*
                Transfer colors from default to private colormap.
              */
              (void) XAllocColorCells(display,colormap,False,(unsigned long *)
                NULL,0,pixel->pixels,(int) retain_colors);
              p=colors+image->colors;
              for (i=0; i < (long) retain_colors; i++)
              {
                p->pixel=pixel->pixels[i];
                p++;
              }
              (void) XStoreColors(display,colormap,colors+image->colors,
                (int) retain_colors);
              number_colors+=retain_colors;
            }
          (void) XAllocColorCells(display,colormap,False,(unsigned long *) NULL,
            0,pixel->pixels,(int) image->colors);
        }
      /*
        Store the image colormap.
      */
      p=colors;
      color.flags=DoRed | DoGreen | DoBlue;
      for (i=0; i < (long) image->colors; i++)
      {
        color.red=ScaleQuantumToShort(MagickXRedGamma(image->colormap[i].red));
        color.green=ScaleQuantumToShort(MagickXGreenGamma(image->colormap[i].green));
        color.blue=ScaleQuantumToShort(MagickXBlueGamma(image->colormap[i].blue));
        if (visual_info->class != PseudoColor)
          {
            gray_value=(unsigned short) PixelIntensity(&color);
            color.red=gray_value;
            color.green=gray_value;
            color.blue=gray_value;
          }
        color.pixel=pixel->pixels[i];
        *p++=color;
      }
      (void) XStoreColors(display,colormap,colors,(int) image->colors);
      break;
    }
    case TrueColor:
    case DirectColor:
    default:
    {
      unsigned int
        linear_colormap;

      /*
        Define Standard Colormap for TrueColor or DirectColor visual.
      */
      number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
        (map_info->green_max*map_info->green_mult)+
        (map_info->blue_max*map_info->blue_mult)+1);
      linear_colormap=(number_colors > 4096) ||
        (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
         ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
         ((int) (map_info->blue_max+1) == visual_info->colormap_size));
      if (linear_colormap)
        number_colors=visual_info->colormap_size;
      /*
        Allocate color array.
      */
      colors=MagickAllocateArray(XColor *,number_colors,sizeof(XColor));
      if (colors == (XColor *) NULL)
        MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
          UnableToCreateColormap);
      /*
        Initialize linear color ramp.
      */
      p=colors;
      color.flags=DoRed | DoGreen | DoBlue;
      if (linear_colormap)
        for (i=0; i < (long) number_colors; i++)
        {
          color.blue=(unsigned short) 0;
          if (map_info->blue_max != 0)
            color.blue=(unsigned short) ((unsigned long)
              ((65535L*(i % map_info->green_mult))/map_info->blue_max));
          color.green=color.blue;
          color.red=color.blue;
          color.pixel=MagickXStandardPixel(map_info,&color);
          *p++=color;
        }
      else
        for (i=0; i < (long) number_colors; i++)
        {
          color.red=(unsigned short) 0;
          if (map_info->red_max != 0)
            color.red=(unsigned short) ((unsigned long)
              ((65535L*(i/map_info->red_mult))/map_info->red_max));
          color.green=(unsigned int) 0;
          if (map_info->green_max != 0)
            color.green=(unsigned short) ((unsigned long)
              ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
                map_info->green_max));
          color.blue=(unsigned short) 0;
          if (map_info->blue_max != 0)
            color.blue=(unsigned short) ((unsigned long)
              ((65535L*(i % map_info->green_mult))/map_info->blue_max));
          color.pixel=MagickXStandardPixel(map_info,&color);
          *p++=color;
        }
      if ((visual_info->class == DirectColor) &&
          (colormap != XDefaultColormap(display,visual_info->screen)))
        (void) XStoreColors(display,colormap,colors,(int) number_colors);
      else
        for (i=0; i < (long) number_colors; i++)
          (void) XAllocColor(display,colormap,&colors[i]);
      break;
    }
  }
  if ((visual_info->class != DirectColor) &&
      (visual_info->class != TrueColor))
    {
      /*
        Set foreground, background, border, etc. pixels.
      */
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->foreground_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->background_color);
      if (pixel->background_color.pixel == pixel->foreground_color.pixel)
        {
          /*
            Foreground and background colors must differ.
          */
          pixel->background_color.red=(~pixel->foreground_color.red);
          pixel->background_color.green=
            (~pixel->foreground_color.green);
          pixel->background_color.blue=
            (~pixel->foreground_color.blue);
          MagickXBestPixel(display,colormap,colors,(int) number_colors,
            &pixel->background_color);
        }
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->border_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->matte_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->highlight_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->shadow_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->depth_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->trough_color);
      for (i=0; i < MaxNumberPens; i++)
      {
        MagickXBestPixel(display,colormap,colors,(int) number_colors,
          &pixel->pen_colors[i]);
        pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
      }
      pixel->colors=image->colors+MaxNumberPens;
    }
  MagickFreeMemory(colors);
  if (IsEventLogging())
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
        map_info->colormap);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  red, green, blue max: %lu %lu %lu",map_info->red_max,
        map_info->green_max,map_info->blue_max);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
        map_info->green_mult,map_info->blue_mult);
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e W i n d o w                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeWindow creates an X11 window.
%
%  The format of the MagickXMakeWindow method is:
%
%      void MagickXMakeWindow(Display *display,Window parent,char **argv,
%        int argc,XClassHint *class_hint,XWMHints *manager_hints,
%        MagickXWindowInfo *window_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o parent: Specifies the parent window_info.
%
%    o argv: Specifies the application's argument list.
%
%    o argc: Specifies the number of arguments.
%
%    o class_hint: Specifies a pointer to a X11 XClassHint structure.
%
%    o manager_hints: Specifies a pointer to a X11 XWMHints structure.
%
%    o window_info: Specifies a pointer to a X11 MagickXWindowInfo structure.
%
%
*/
MagickExport void
MagickXMakeWindow(Display *display,Window parent,char **argv,
                  int argc,XClassHint *class_hint,XWMHints *manager_hints,
                  MagickXWindowInfo *window_info)
{
#define MinWindowSize  64

  Atom
    atom_list[2];

  int
    gravity,
    status;

  static XTextProperty
    icon_name,
    window_name;

  XSizeHints
    *size_hints;

  /*
    Set window info hints.
  */
  assert(display != (Display *) NULL);
  assert(window_info != (MagickXWindowInfo *) NULL);
  size_hints=XAllocSizeHints();
  if (size_hints == (XSizeHints *) NULL)
    MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
      MagickMsg(XServerFatalError,UnableToMakeXWindow));
  size_hints->flags=(long) window_info->flags;
  size_hints->x=window_info->x;
  size_hints->y=window_info->y;
  size_hints->width=window_info->width;
  size_hints->height=window_info->height;
  if (window_info->immutable)
    {
      /*
        Window size cannot be changed.
      */
      size_hints->min_width=size_hints->width;
      size_hints->min_height=size_hints->height;
      size_hints->max_width=size_hints->width;
      size_hints->max_height=size_hints->height;
      size_hints->flags|=PMinSize;
      size_hints->flags|=PMaxSize;
    }
  else
    {
      /*
        Window size can be changed.
      */
      size_hints->min_width=window_info->min_width;
      size_hints->min_height=window_info->min_height;
      size_hints->flags|=PResizeInc;
      size_hints->width_inc=window_info->width_inc;
      size_hints->height_inc=window_info->height_inc;
#if !defined(PRE_R4_ICCCM)
      size_hints->flags|=PBaseSize;
      size_hints->base_width=size_hints->width_inc;
      size_hints->base_height=size_hints->height_inc;
#endif
    }
  gravity=NorthWestGravity;
  if (window_info->geometry != (char *) NULL)
    {
      char
        default_geometry[MaxTextExtent],
        geometry[MaxTextExtent];

      int
        flags;

      register char
        *p;

      /*
        User specified geometry.
      */
      FormatString(default_geometry,"%dx%d",size_hints->width,
        size_hints->height);
      (void) strlcpy(geometry,window_info->geometry,MaxTextExtent);
      p=geometry;
      while (strlen(p) != 0)
      {
        if (!isspace((int) (*p)) && (*p != '%'))
          p++;
        else
          (void) strcpy(p,p+1);
      }
      flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
        window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
        &size_hints->width,&size_hints->height,&gravity);
      if ((flags & WidthValue) && (flags & HeightValue))
        size_hints->flags|=USSize;
      if ((flags & XValue) && (flags & YValue))
        {
          size_hints->flags|=USPosition;
          window_info->x=size_hints->x;
          window_info->y=size_hints->y;
        }
    }
#if !defined(PRE_R4_ICCCM)
  size_hints->win_gravity=gravity;
  size_hints->flags|=PWinGravity;
#endif
  if (window_info->id == (Window) NULL)
    window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
      window_info->width,window_info->height,window_info->border_width,
      window_info->depth,InputOutput,window_info->visual,window_info->mask,
      &window_info->attributes);
  else
    {
      unsigned int
        mask;

      XEvent
        sans_event;

      XWindowChanges
        window_changes;

      /*
        Window already exists;  change relevant attributes.
      */
      (void) XChangeWindowAttributes(display,window_info->id,window_info->mask,
        &window_info->attributes);
      mask=ConfigureNotify;
      while (XCheckTypedWindowEvent(display,window_info->id,mask,&sans_event));
      window_changes.x=window_info->x;
      window_changes.y=window_info->y;
      window_changes.width=window_info->width;
      window_changes.height=window_info->height;
      mask=CWWidth | CWHeight;
      if (window_info->flags & USPosition)
        mask|=CWX | CWY;
      (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
        mask,&window_changes);
    }
  if (window_info->id == (Window) NULL)
    MagickFatalError(XServerFatalError,UnableToCreateXWindow,
      window_info->name);
  status=XStringListToTextProperty(&window_info->name,1,&window_name);
  if (status == 0)
    MagickFatalError(XServerFatalError,UnableToCreateTextProperty,
      window_info->name);
  status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
  if (status == 0)
    MagickFatalError(XServerFatalError,UnableToCreateTextProperty,
      window_info->icon_name);
  if (window_info->icon_geometry != (char *) NULL)
    {
      int
        flags,
        height,
        width;

      /*
        User specified icon geometry.
      */
      size_hints->flags|=USPosition;
      flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
        (char *) NULL,0,size_hints,&manager_hints->icon_x,
        &manager_hints->icon_y,&width,&height,&gravity);
      if ((flags & XValue) && (flags & YValue))
        manager_hints->flags|=IconPositionHint;
    }
  XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
    size_hints,manager_hints,class_hint);
  if (window_name.value != NULL)
    {
      (void) XFree((void *) window_name.value);
      window_name.value = NULL;
      window_name.nitems=0;
    }
  if (icon_name.value != NULL)
    {
      (void) XFree((void *) icon_name.value);
      icon_name.value = NULL;
      icon_name.nitems=0;
    }
  atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",False);
  atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",False);
  (void) XSetWMProtocols(display,window_info->id,atom_list,2);
  (void) XFree((void *) size_hints);
  if (window_info->shape)
    {
#if defined(HasShape)
      int
        error_base=0,
        event_base=0;

      /*
        Can we apply a non-rectangular shaping mask?
      */
      window_info->shape&=XShapeQueryExtension(display,&error_base,&event_base);
#else
      window_info->shape=False;
#endif
    }
  if (window_info->shared_memory)
    {
#if defined(HasSharedMemory)
      /*
        Can we we use shared memory with this window?
      */
      window_info->shared_memory&=XShmQueryExtension(display);
#else
      window_info->shared_memory=False;
#endif
    }
  window_info->image=(Image *) NULL;
  window_info->destroy=False;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X P r o g r e s s M o n i t o r                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMagickMonitor displays the progress a task is making in
%  completing a task.
%
%  The format of the MagickXMagickMonitor method is:
%
%      unsigned int MagickXMagickMonitor(const char *task,
%        const magick_int64_t quantum,const magick_uint64_t span,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o task: Identifies the task in progress.
%
%    o quantum: Specifies the quantum position within the span which represents
%      how much progress has been made in completing a task.
%
%    o span: Specifies the span relative to completing a task.
%
%    o exception: Return any errors or warnings in this structure.
%
*/
MagickExport unsigned int
MagickXMagickMonitor(const char *task,
                     const magick_int64_t quantum,const magick_uint64_t span,
                     ExceptionInfo *ARGUNUSED(exception))
{
  MagickXWindows
    *windows;

  windows=MagickXSetWindows((MagickXWindows *) ~0);
  if (windows == (MagickXWindows *) NULL)
    return(True);
  MagickXMonitorWidget(windows->display,windows,task,quantum,span);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X Q u e r y C o l o r D a t a b a s e                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXQueryColorDatabase looks up a RGB values for a color given
%  in the target string.
%
%  The format of the MagickXQueryColorDatabase method is:
%
%      unsigned int MagickXQueryColorDatabase(const char *target,XColor *color)
%
%  A description of each parameter follows:
%
%    o status:  Method MagickXQueryColorDatabase returns True if the RGB values
%      of the target color is defined, otherwise False is returned.
%
%    o target: Specifies the color to lookup in the X color database.
%
%    o color: A pointer to an PixelPacket structure.  The RGB value of the target
%      color is returned as this value.
%
%
*/
MagickExport unsigned int
MagickXQueryColorDatabase(const char *target,XColor *color)
{
  Colormap
    colormap;

  int
    status;

  static Display
    *display = (Display *) NULL;

  XColor
    xcolor;

  /*
    Initialize color return value.
  */
  assert(color != (XColor *) NULL);
  color->red=0;
  color->green=0;
  color->blue=0;
  color->flags=DoRed | DoGreen | DoBlue;
  if ((target == (char *) NULL) || (*target == '\0'))
    target="#ffffffffffff";
  /*
    Let the X server define the color for us.
  */
  if (display == (Display *) NULL)
    display=XOpenDisplay((char *) NULL);
  if (display == (Display *) NULL)
    {
      MagickError(XServerError,ColorIsNotKnownToServer,target);
      return(False);
    }
  colormap=XDefaultColormap(display,XDefaultScreen(display));
  status=XParseColor(display,colormap,(char *) target,&xcolor);
  if (status == False)
    MagickError(XServerError,ColorIsNotKnownToServer,target);
  else
    {
      color->red=xcolor.red;
      color->green=xcolor.green;
      color->blue=xcolor.blue;
      color->flags=xcolor.flags;
    }
  return(status != 0);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X Q u e r y P o s i t i o n                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXQueryPosition gets the pointer coordinates relative to a
%  window.
%
%  The format of the MagickXQueryPosition method is:
%
%      void MagickXQueryPosition(Display *display,const Window window,
%                                int *x,int *y)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window.
%
%    o x: Return the x coordinate of the pointer relative to the origin of the
%      window.
%
%    o y: Return the y coordinate of the pointer relative to the origin of the
%      window.
%
%
*/
MagickExport void 
MagickXQueryPosition(Display *display,const Window window,int *x,int *y)
{
  int
    x_root,
    y_root;

  unsigned int
    mask;

  Window
    root_window;

  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(x != (int *) NULL);
  assert(y != (int *) NULL);
  (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
    x,y,&mask);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X R e f r e s h W i n d o w                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXRefreshWindow refreshes an image in a X window.
%
%  The format of the MagickXRefreshWindow method is:
%
%      void MagickXRefreshWindow(Display *display,
%        const MagickXWindowInfo *window,const XEvent *event)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%    o event: Specifies a pointer to a XEvent structure.  If it is NULL,
%      the entire image is refreshed.
%
%
*/
MagickExport void
MagickXRefreshWindow(Display *display,const MagickXWindowInfo *window,
                     const XEvent *event)
{
  int
    x,
    y;

  unsigned int
    height,
    width;

  assert(display != (Display *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  if (window->ximage == (XImage *) NULL)
    return;
  if (event != (XEvent *) NULL)
    {
      /*
        Determine geometry from expose event.
      */
      x=event->xexpose.x;
      y=event->xexpose.y;
      width=event->xexpose.width;
      height=event->xexpose.height;
    }
  else
    {
      XEvent
        sans_event;

      /*
        Refresh entire window; discard outstanding expose events.
      */
      x=0;
      y=0;
      width=window->width;
      height=window->height;
      while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event));
    }
  /*
    Check boundary conditions.
  */
  if ((window->ximage->width-(x+window->x)) < (int) width)
    width=window->ximage->width-(x+window->x);
  if ((window->ximage->height-(y+window->y)) < (int) height)
    height=window->ximage->height-(y+window->y);
  /*
    Refresh image.
  */
  (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
  if (window->pixmap != (Pixmap) NULL)
    {
      if (window->depth > 1)
        (void) XCopyArea(display,window->pixmap,window->id,
          window->annotate_context,x+window->x,y+window->y,width,height,x,y);
      else
        (void) XCopyPlane(display,window->pixmap,window->id,
          window->highlight_context,x+window->x,y+window->y,width,height,
          x,y,1L);
    }
  else
    {
#if defined(HasSharedMemory)
      if (window->shared_memory)
        (void) XShmPutImage(display,window->id,window->annotate_context,
          window->ximage,x+window->x,y+window->y,x,y,width,height,True);
#endif /* defined(HasSharedMemory) */
      if (!window->shared_memory)
        (void) XPutImage(display,window->id,window->annotate_context,
          window->ximage,x+window->x,y+window->y,x,y,width,height);
    }
  (void) XSetClipMask(display,window->annotate_context,None);
  (void) XFlush(display);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X R e m o t e C o m m a n d                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MagickXRemoteCommand() forces a remote display(1) to display the specified
%  image filename.
%
%  The format of the MagickXRemoteCommand method is:
%
%      unsigned int MagickXRemoteCommand(Display *display,const char *window,
%        const char *filename)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies the name or id of an X window.
%
%    o filename: The name of the image filename to display.
%
%
*/
MagickExport unsigned int
MagickXRemoteCommand(Display *display,const char *window,
                     const char *filename)
{
  Atom
    remote_atom;

  Window
    remote_window,
    root_window;

  assert(filename != (char *) NULL);
  if (display == (Display *) NULL)
    display=XOpenDisplay((char *) NULL);
  if (display == (Display *) NULL)
    {
      MagickError(XServerError,UnableToOpenXServer,(char *) NULL);
      return(False);
    }
  remote_atom=XInternAtom(display,"IM_PROTOCOLS",False);
  remote_window=(Window) NULL;
  root_window=XRootWindow(display,XDefaultScreen(display));
  if (window != (char *) NULL)
    {
      /*
        Search window hierarchy and identify any clients by name or ID.
      */
      if (isdigit((int) (*window)))
        remote_window=MagickXWindowByID(display,root_window,(Window)
          strtol((char *) window,(char **) NULL,0));
      if (remote_window == (Window) NULL)
        remote_window=MagickXWindowByName(display,root_window,window);
    }
  if (remote_window == (Window) NULL)
    remote_window=MagickXWindowByProperty(display,root_window,remote_atom);
  if (remote_window == (Window) NULL)
    {
      MagickError(XServerError,UnableToConnectToRemoteDisplay,(char *) NULL);
      return(False);
    }
  /*
    Send remote command.
  */
  remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",False);
  (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
    PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
  (void) XSync(display,False);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X R e t a i n W i n d o w C o l o r s                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXRetainWindowColors sets X11 color resources on a window.
%  This preserves the colors associated with an image displayed on the window.
%
%  The format of the MagickXRetainWindowColors method is:
%
%      void MagickXRetainWindowColors(Display *display,const Window window)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%
*/
MagickExport void
MagickXRetainWindowColors(Display *display,const Window window)
{
  Atom
    property;

  Pixmap
    pixmap;

  /*
    Put property on the window.
  */
  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  property=XInternAtom(display,"_XSETROOT_ID",False);
  if (property == (Atom) NULL)
    {
      MagickError(XServerError,UnableToCreateProperty,"_XSETROOT_ID");
      return;
    }
  pixmap=XCreatePixmap(display,window,1,1,1);
  if (pixmap == (Pixmap) NULL)
    {
      MagickError(XServerError,UnableToCreatePixmap,(char *) NULL);
      return;
    }
  (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
    (unsigned char *) &pixmap,1);
  (void) XSetCloseDownMode(display,RetainPermanent);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X S e l e c t W i n d o w                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXSelectWindow allows a user to select a window using the
%  mouse.  If the mouse moves, a cropping rectangle is drawn and the extents
%  of the rectangle is returned in the crop_info structure.
%
%  The format of the MagickXSelectWindow function is:
%
%      target_window=MagickXSelectWindow(display,crop_info)
%
%  A description of each parameter follows:
%
%    o window: MagickXSelectWindow returns the window id.
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o crop_info: Specifies a pointer to a RectangleInfo structure.  It
%      contains the extents of any cropping rectangle.
%
%
*/
static Window
MagickXSelectWindow(Display *display,RectangleInfo *crop_info)
{
#define MinimumCropArea  (unsigned int) 9

  Cursor
    target_cursor;

  GC
    annotate_context;

  int
    presses,
    status,
    x_offset,
    y_offset;

  Window
    root_window,
    target_window;

  XEvent
    event;

  XGCValues
    context_values;

  /*
    Initialize graphic context.
  */
  assert(display != (Display *) NULL);
  assert(crop_info != (RectangleInfo *) NULL);
  root_window=XRootWindow(display,XDefaultScreen(display));
  context_values.background=XBlackPixel(display,XDefaultScreen(display));
  context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
  context_values.function=GXinvert;
  context_values.plane_mask=
    context_values.background ^ context_values.foreground;
  context_values.subwindow_mode=IncludeInferiors;
  annotate_context=XCreateGC(display,root_window,GCBackground | GCForeground |
    GCFunction | GCSubwindowMode,&context_values);
  if (annotate_context == (GC) NULL)
    return(False);
  /*
    Grab the pointer using target cursor.
  */
  target_cursor=MagickXMakeCursor(display,root_window,XDefaultColormap(display,
    XDefaultScreen(display)),(char *) "white",(char *) "black");
  status=XGrabPointer(display,root_window,False,(unsigned int)
    (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
    GrabModeAsync,root_window,target_cursor,CurrentTime);
  if (status != GrabSuccess)
    {
      MagickError(XServerError,UnableToGrabMouse,(char *) NULL);
      return(False);
    }
  /*
    Select a window.
  */
  crop_info->width=0;
  crop_info->height=0;
  presses=0;
  target_window=(Window) NULL;
  x_offset=0;
  y_offset=0;
  do
  {
    if ((crop_info->width*crop_info->height) >= MinimumCropArea)
      (void) XDrawRectangle(display,root_window,annotate_context,
        (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
        (unsigned int) crop_info->height-1);
    /*
      Allow another event.
    */
    (void) XAllowEvents(display,SyncPointer,CurrentTime);
    (void) XWindowEvent(display,root_window,ButtonPressMask |
      ButtonReleaseMask | ButtonMotionMask,&event);
    if ((crop_info->width*crop_info->height) >= MinimumCropArea)
      (void) XDrawRectangle(display,root_window,annotate_context,
        (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
        (unsigned int) crop_info->height-1);
    switch (event.type)
    {
      case ButtonPress:
      {
        target_window=MagickXGetSubwindow(display,event.xbutton.subwindow,
          event.xbutton.x,event.xbutton.y);
        if (target_window == (Window) NULL)
          target_window=root_window;
        x_offset=event.xbutton.x_root;
        y_offset=event.xbutton.y_root;
        crop_info->x=x_offset;
        crop_info->y=y_offset;
        crop_info->width=0;
        crop_info->height=0;
        presses++;
        break;
      }
      case ButtonRelease:
      {
        presses--;
        break;
      }
      case MotionNotify:
      {
        /*
          Discard pending button motion events.
        */
        while (XCheckMaskEvent(display,ButtonMotionMask,&event));
        crop_info->x=event.xmotion.x;
        crop_info->y=event.xmotion.y;
        /*
          Check boundary conditions.
        */
        if ((int) crop_info->x < x_offset)
          crop_info->width=(unsigned int) (x_offset-crop_info->x);
        else
          {
            crop_info->width=(unsigned int) (crop_info->x-x_offset);
            crop_info->x=x_offset;
          }
        if ((int) crop_info->y < y_offset)
          crop_info->height=(unsigned int) (y_offset-crop_info->y);
        else
          {
            crop_info->height=(unsigned int) (crop_info->y-y_offset);
            crop_info->y=y_offset;
          }
      }
      default:
        break;
    }
  }
  while ((target_window == (Window) NULL) || (presses > 0));
  (void) XUngrabPointer(display,CurrentTime);
  (void) XFreeCursor(display,target_cursor);
  (void) XFreeGC(display,annotate_context);
  if ((crop_info->width*crop_info->height) < MinimumCropArea)
    {
      crop_info->width=0;
      crop_info->height=0;
    }
  if ((crop_info->width != 0) && (crop_info->height != 0))
    target_window=root_window;
  return(target_window);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X S i g n a l H a n d l e r                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXSignalHandler is called if the program execution is
%  interrupted.
%
%  The format of the MagickXSignalHandler method is:
%
%      void MagickXSetCursorState(Display *display,MagickXWindows *windows,
%        const unsigned int state)
%
%
*/

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

MagickExport void
MagickXSignalHandler(int status)
{
  DestroyMagick();
  Exit(status);
}

#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X S e t C u r s o r S t a t e                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXSetCursorState sets the cursor state to busy, otherwise the
%  cursor are reset to their default.
%
%  The format of the XMagickXSetCursorState method is:
%
%      MagickXSetCursorState(display,windows,state)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%    o state: An unsigned integer greater than 0 sets the cursor state
%      to busy, otherwise the cursor are reset to their default.
%
%
*/
MagickExport void
MagickXSetCursorState(Display *display,
                      MagickXWindows *windows,
                      const unsigned int state)
{
  assert(display != (Display *) NULL);
  assert(windows != (MagickXWindows *) NULL);
  if (state)
    {
      (void) XDefineCursor(display,windows->image.id,
        windows->image.busy_cursor);
      (void) XDefineCursor(display,windows->pan.id,windows->pan.busy_cursor);
      (void) XDefineCursor(display,windows->magnify.id,
        windows->magnify.busy_cursor);
      (void) XDefineCursor(display,windows->command.id,
        windows->command.busy_cursor);
    }
  else
    {
      (void) XDefineCursor(display,windows->image.id,windows->image.cursor);
      (void) XDefineCursor(display,windows->pan.id,windows->pan.cursor);
      (void) XDefineCursor(display,windows->magnify.id,windows->magnify.cursor);
      (void) XDefineCursor(display,windows->command.id,windows->command.cursor);
      (void) XDefineCursor(display,windows->command.id,windows->widget.cursor);
      (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
    }
  windows->info.mapped=False;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X S e t W i n d o w s                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXSetWindows sets the X windows structure if the windows info
%  is specified.  Otherwise the current windows structure is returned.
%
%  The format of the MagickXSetWindows method is:
%
%      MagickXWindows *MagickXSetWindows(MagickXWindows *windows_info)
%
%  A description of each parameter follows:
%
%    o windows: Method MagickXSetWindows returns a pointer to the
%      MagickXWindows structure.
%
%    o windows_info: Initialize the Windows structure with this information.
%
*/
MagickExport MagickXWindows *
MagickXSetWindows(MagickXWindows *windows_info)
{
  static MagickXWindows
    *windows = (MagickXWindows *) NULL;

  if (windows_info != (MagickXWindows *) ~0)
    {
      MagickFreeMemory(windows);
      windows=windows_info;
    }
  return(windows);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X U s e r P r e f e r e n c e s                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXUserPreferences saves the preferences in a configuration
%  file in the users' home directory.
%
%  The format of the MagickXUserPreferences method is:
%
%      void MagickXUserPreferences(MagickXResourceInfo *resource_info)
%
%  A description of each parameter follows:
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%
*/
MagickExport void
MagickXUserPreferences(MagickXResourceInfo *resource_info)
{
#if defined(PreferencesDefaults)
  const char
    *client_name;

  char
    cache[MaxTextExtent],
    filename[MaxTextExtent],
    specifier[MaxTextExtent];

  const char
    *value;

  XrmDatabase
    preferences_database;

  /*
    Save user preferences to the client configuration file.
  */
  assert(resource_info != (MagickXResourceInfo *) NULL);
  client_name=GetClientName();
  preferences_database=XrmGetStringDatabase("");
  FormatString(specifier,"%.1024s.backdrop",client_name);
  value=MagickBoolToString(resource_info->backdrop);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.colormap",client_name);
  value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.confirmExit",client_name);
  value=MagickBoolToString(resource_info->confirm_exit);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.displayWarnings",client_name);
  value=MagickBoolToString(resource_info->display_warnings);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.dither",client_name);
  value=MagickBoolToString(resource_info->quantize_info->dither);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.gammaCorrect",client_name);
  value=MagickBoolToString(resource_info->gamma_correct);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.undoCache",client_name);
  FormatString(cache,"%lu",resource_info->undo_cache);
  XrmPutStringResource(&preferences_database,specifier,cache);
  FormatString(specifier,"%.1024s.usePixmap",client_name);
  value=MagickBoolToString(resource_info->use_pixmap);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(filename,"%.1024s%.1024src",PreferencesDefaults,client_name);
  ExpandFilename(filename);
  XrmPutFileDatabase(preferences_database,filename);
#endif /* defined(PreferencesDefaults) */
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X V i s u a l C l a s s N a m e                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXVisualClassName returns the visual class name as a character
%  string.
%
%  The format of the MagickXVisualClassName method is:
%
%      char *MagickXVisualClassName(const int visual_class)
%
%  A description of each parameter follows:
%
%    o visual_type: MagickXVisualClassName returns the visual class as a
%      character string.
%
%    o class: Specifies the visual class.
%
%
*/
static char *
MagickXVisualClassName(const int visual_class)
{
  switch (visual_class)
  {
    case StaticGray: return((char *) "StaticGray");
    case GrayScale: return((char *) "GrayScale");
    case StaticColor: return((char *) "StaticColor");
    case PseudoColor: return((char *) "PseudoColor");
    case TrueColor: return((char *) "TrueColor");
    case DirectColor: return((char *) "DirectColor");
  }
  return((char *) "unknown visual class");
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X W a r n i n g                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXWarning displays a warning reason in a Notice widget.
%
%  The format of the MagickXWarning method is:
%
%      void MagickXWarning(const unsigned int warning,const char *reason,
%        const char *description)
%
%  A description of each parameter follows:
%
%    o warning: Specifies the numeric warning category.
%
%    o reason: Specifies the reason to display before terminating the
%      program.
%
%    o description: Specifies any description to the reason.
%
%
*/
MagickExport void
MagickXWarning(const ExceptionType ARGUNUSED(warning),
               const char *reason,const char *description)
{
  char
    text[MaxTextExtent];

  MagickXWindows
    *windows;

  if (reason == (char *) NULL)
    return;
  (void) strlcpy(text,reason,MaxTextExtent);
  (void) strlcat(text,":",MaxTextExtent);
  windows=MagickXSetWindows((MagickXWindows *) ~0);
  MagickXNoticeWidget(windows->display,windows,text,(char *) description);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X W i n d o w B y I D                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXWindowByID locates a child window with a given ID.  If not
%  window with the given name is found, 0 is returned.   Only the window
%  specified and its subwindows are searched.
%
%  The format of the MagickXWindowByID function is:
%
%      child=MagickXWindowByID(display,window,id)
%
%  A description of each parameter follows:
%
%    o child: MagickXWindowByID returns the window with the specified
%      id.  If no windows are found, MagickXWindowByID returns 0.
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o id: Specifies the id of the window to locate.
%
%
*/
MagickExport Window
MagickXWindowByID(Display *display,const Window root_window,
                  const unsigned long id)
{
  RectangleInfo
    rectangle_info;

  register int
    i;

  unsigned int
    number_children;

  Window
    child,
    *children,
    window;

  assert(display != (Display *) NULL);
  assert(root_window != (Window) NULL);
  if (id == 0)
    return(MagickXSelectWindow(display,&rectangle_info));
  if (root_window == id)
    return(id);
  if (!XQueryTree(display,root_window,&child,&child,&children,&number_children))
    return((Window) NULL);
  window=(Window) NULL;
  for (i=0; i < (int) number_children; i++)
  {
    /*
      Search each child and their children.
    */
    window=MagickXWindowByID(display,children[i],id);
    if (window != (Window) NULL)
      break;
  }
  if (children != (Window *) NULL)
    (void) XFree((void *) children);
  return(window);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X W i n d o w B y N a m e                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXWindowByName locates a window with a given name on a display.
%  If no window with the given name is found, 0 is returned. If more than
%  one window has the given name, the first one is returned.  Only root and
%  its children are searched.
%
%  The format of the MagickXWindowByName function is:
%
%      window=MagickXWindowByName(display,root_window,name)
%
%  A description of each parameter follows:
%
%    o window: MagickXWindowByName returns the window id.
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o root_window: Specifies the id of the root window.
%
%    o name: Specifies the name of the window to locate.
%
%
*/
MagickExport Window
MagickXWindowByName(Display *display,const Window root_window,
                    const char *name)
{
  register int
    i;

  unsigned int
    number_children;

  Window
    *children,
    child,
    window;

  XTextProperty
    window_name;

  assert(display != (Display *) NULL);
  assert(root_window != (Window) NULL);
  assert(name != (char *) NULL);
  if (XGetWMName(display,root_window,&window_name) != 0)
    if (LocaleCompare((char *) window_name.value,name) == 0)
      return(root_window);
  if (!XQueryTree(display,root_window,&child,&child,&children,&number_children))
    return((Window) NULL);
  window=(Window) NULL;
  for (i=0; i < (int) number_children; i++)
  {
    /*
      Search each child and their children.
    */
    window=MagickXWindowByName(display,children[i],name);
    if (window != (Window) NULL)
      break;
  }
  if (children != (Window *) NULL)
    (void) XFree((void *) children);
  return(window);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X W i n d o w B y P r o p e r y                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXWindowByProperty locates a child window with a given property.
%  If no window with the given name is found, 0 is returned.  If more than
%  one window has the given property, the first one is returned.  Only the
%  window specified and its subwindows are searched.
%
%  The format of the MagickXWindowByProperty function is:
%
%      child=MagickXWindowByProperty(display,window,property)
%
%  A description of each parameter follows:
%
%    o child: MagickXWindowByProperty returns the window id with the specified
%      property.  If no windows are found, MagickXWindowByProperty returns 0.
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o property: Specifies the property of the window to locate.
%
%
*/
MagickExport Window
MagickXWindowByProperty(Display *display,const Window window,
                        const Atom property)
{
  Atom
    type;

  int
    format,
    status;

  unsigned char
    *data;

  unsigned int
    i,
    number_children;

  unsigned long
    after,
    number_items;

  Window
    child,
    *children,
    parent,
    root;

  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(property != (Atom) NULL);
  status=XQueryTree(display,window,&root,&parent,&children,&number_children);
  if (status == 0)
    return((Window) NULL);
  type=(Atom) NULL;
  child=(Window) NULL;
  for (i=0; (i < number_children) && (child == (Window) NULL); i++)
  {
    status=XGetWindowProperty(display,children[i],property,0L,0L,False,
      (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
    if (data != NULL)
      (void) XFree((void *) data);
    if ((status == Success) && (type != (Atom) NULL))
      child=children[i];
  }
  for (i=0; (i < number_children) && (child == (Window) NULL); i++)
    child=MagickXWindowByProperty(display,children[i],property);
  if (children != (Window *) NULL)
    (void) XFree((void *) children);
  return(child);
}
#endif /* HasX11 */

/* [<][>][^][v][top][bottom][index][help] */