xpm.c revision de984cdc3631106b1cbbb8d3972b76a0fc27e8e8
13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            X   X  PPPP   M   M                              %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                             X X   P   P  MM MM                              %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              X    PPPP   M M M                              %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                             X X   P      M   M                              %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            X   X  P      M   M                              %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                  Read/Write X Windows system Pixmap Format                  %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 July 1992                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
20fe676ee3a9cf43404bdc9ba8b27f597b5e4e28f7cristy%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
424c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/attribute.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color-private.h"
494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colormap.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace.h"
51510d06a3f7063e91993e13d546d5685048248074cristy#include "MagickCore/colorspace-private.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/geometry.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantize.h"
644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resize.h"
664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resource_.h"
674c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/splay-tree.h"
684c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/static.h"
694c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
704c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h"
714c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/threshold.h"
724c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h"
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declarations.
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
783a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  WritePICONImage(const ImageInfo *,Image *,ExceptionInfo *),
793a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  WriteXPMImage(const ImageInfo *,Image *,ExceptionInfo *);
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I s X P M                                                                 %
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  IsXPM() returns MagickTrue if the image format type, identified by the
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  magick string, is XPM.
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the IsXPM method is:
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType IsXPM(const unsigned char *magick,const size_t length)
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o magick: compare image format pattern against these bytes. or
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      blob.
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o length: Specifies the length of the magick string.
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType IsXPM(const unsigned char *magick,const size_t length)
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length < 9)
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleNCompare((char *) magick+1,"* XPM *",7) == 0)
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d X P M I m a g e                                                   %
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadXPMImage() reads an X11 pixmap image file and returns it.  It
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  allocates the memory necessary for the new Image structure and returns a
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  pointer to the new image.
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadXPMImage method is:
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception)
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic int CompareXPMColor(const void *target,const void *source)
1442f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy{
1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
1482f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=(const char *) target;
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=(const char *) source;
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(strcmp(p,q));
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic char *CopyXPMColor(char *destination,const char *source,size_t length)
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (length-- && (*source != '\0'))
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *destination++=(*source++);
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *destination='\0';
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(destination-length);
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic char *NextXPMLine(char *p)
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(p != (char*)NULL);
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=strchr(p,'\n');
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (p != (char *) NULL)
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p++;
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(p);
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline size_t MagickMin(const size_t x,const size_t y)
1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x < y)
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic char *ParseXPMColor(char *color)
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define NumberTargets  6
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const char
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
189bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const char
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *targets[NumberTargets] = { "c ", "g ", "g4 ", "m ", "b ", "s " };
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; i < NumberTargets; i++)
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=color;
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (q=targets[i]; *p != '\0'; p++)
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (*p == '\n')
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (*p != *q)
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (isspace((int) ((unsigned char) (*(p-1)))) == 0)
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r=p;
2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for ( ; ; )
2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (*q == '\0')
2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(p);
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (*r++ != *q++)
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q=targets[i];
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return((char *) NULL);
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception)
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    key[MaxTextExtent],
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    target[MaxTextExtent],
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *xpm_buffer;
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    active,
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q,
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *next;
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
239bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2424c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length;
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SplayTreeInfo
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *xpm_colors;
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ssize_t
252c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    count,
253c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    j,
254c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    y;
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
256d8af19d72fd93dfd2e42eb0b266cac384a6ae833cristy  unsigned long
257f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    colors,
258f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    columns,
259f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    rows,
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width;
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
2729950d57e1124b73f684fb5946e206994cefda628cristy  image=AcquireImage(image_info,exception);
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read XPM file.
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  length=MaxTextExtent;
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  xpm_buffer=(char *) AcquireQuantumMemory((size_t) length,sizeof(*xpm_buffer));
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=xpm_buffer;
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (xpm_buffer != (char *) NULL)
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    while (ReadBlobString(image,p) != (char *) NULL)
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((*p == '#') && ((p == xpm_buffer) || (*(p-1) == '\n')))
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((*p == '}') && (*(p+1) == ';'))
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p+=strlen(p);
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((size_t) (p-xpm_buffer+MaxTextExtent) < length)
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      length<<=1;
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      xpm_buffer=(char *) ResizeQuantumMemory(xpm_buffer,length+MaxTextExtent,
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        sizeof(*xpm_buffer));
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (xpm_buffer == (char *) NULL)
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=xpm_buffer+strlen(xpm_buffer);
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (xpm_buffer == (char *) NULL)
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Remove comments.
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=0;
30893b02b797c4127ce2b06dbd3b2d75ecc33fca759dirk  width=0;
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=xpm_buffer; *p != '\0'; p++)
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*p != '"')
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      continue;
313f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    count=(ssize_t) sscanf(p+1,"%lu %lu %lu %lu",&columns,&rows,&colors,&width);
314f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    image->columns=columns;
315f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    image->rows=rows;
316f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    image->colors=colors;
317e6b6ece8afea47c6a48f0e189f8f0296606d40f2cristy    if (count == 4)
318e6b6ece8afea47c6a48f0e189f8f0296606d40f2cristy      break;
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((count != 4) || (width > 10) || (image->columns == 0) ||
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (image->rows == 0) || (image->colors == 0))
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Remove unquoted characters.
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  active=MagickFalse;
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=xpm_buffer;
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (*p != '\0')
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*p++ == '"')
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (active != MagickFalse)
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *q++='\n';
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        active=active != MagickFalse ? MagickFalse : MagickTrue;
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (active != MagickFalse)
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *q++=(*p);
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *q='\0';
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize image structure.
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  xpm_colors=NewSplayTree(CompareXPMColor,RelinquishMagickMemory,
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void *(*)(void *)) NULL);
345018f07f7333b25743d0afff892450cebdb905c1acristy  if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read image colormap.
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3501d92f7952ace182649f73e84b7ecbba1798e8fffcristy  image->depth=1;
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  next=NextXPMLine(xpm_buffer);
352bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (j=0; (j < (ssize_t) image->colors) && (next != (char*) NULL); j++)
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=next;
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    next=NextXPMLine(p);
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) CopyXPMColor(key,p,MagickMin((size_t) width,MaxTextExtent));
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=AddValueToSplayTree(xpm_colors,ConstantString(key),(void *) j);
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Parse color.
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) CopyMagickString(target,"gray",MaxTextExtent);
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=ParseXPMColor(p+width);
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (q != (char *) NULL)
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((isspace((int) ((unsigned char) *q)) == 0) && (*q != '\0'))
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          q++;
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (next != (char *) NULL)
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyXPMColor(target,q,MagickMin((size_t) (next-q),
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            MaxTextExtent));
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyMagickString(target,q,MaxTextExtent);
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        q=ParseXPMColor(target);
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (q != (char *) NULL)
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *q='\0';
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    StripString(target);
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleCompare(target,"none") == 0)
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->storage_class=DirectClass;
3808a46d827a124555f0c48fb2368ec1bba8e079ab6cristy        image->alpha_trait=BlendPixelTrait;
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
382fc502a1bd2f6e35346f02b0b7c466ac4e280d976cristy    status=QueryColorCompliance(target,XPMCompliance,&image->colormap[j],
383a60c02075c4071dd1801b41db0b478f68683a6fecristy      exception);
384a60c02075c4071dd1801b41db0b478f68683a6fecristy    if (status == MagickFalse)
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
3861d92f7952ace182649f73e84b7ecbba1798e8fffcristy    if (image->depth < image->colormap[j].depth)
3871d92f7952ace182649f73e84b7ecbba1798e8fffcristy      image->depth=image->colormap[j].depth;
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
389bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  if (j < (ssize_t) image->colors)
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"CorruptImage");
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  j=0;
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->ping == MagickFalse)
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Read image pixels.
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
397bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (y=0; y < (ssize_t) image->rows; y++)
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=NextXPMLine(p);
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (p == (char *) NULL)
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        r=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
4034c08aed51c5899665ade97263692328eea4af106cristy        if (r == (Quantum *) NULL)
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
405bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (x=0; x < (ssize_t) image->columns; x++)
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyXPMColor(key,p,(size_t) width);
408bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          j=(ssize_t) GetValueFromSplayTree(xpm_colors,key);
4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (image->storage_class == PseudoClass)
4104c08aed51c5899665ade97263692328eea4af106cristy            SetPixelIndex(image,j,r);
411803640d20a6a664315eddfff6f8531d0c5e0871dcristy          SetPixelInfoPixel(image,image->colormap+j,r);
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          p+=width;
413ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy          r+=GetPixelChannels(image);
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (SyncAuthenticPixels(image,exception) == MagickFalse)
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
418bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      if (y < (ssize_t) image->rows)
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowReaderException(CorruptImageError,"NotEnoughPixelData");
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  xpm_colors=DestroySplayTree(xpm_colors);
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r X P M I m a g e                                           %
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterXPMImage() adds attributes for the XPM image format to
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterXPMImage method is:
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
449bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterXPMImage(void)
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
452bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterXPMImage(void)
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PICON");
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadXPMImage;
4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePICONImage;
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Personal Icon");
4623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("XPM");
4633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PM");
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadXPMImage;
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteXPMImage;
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->stealth=MagickTrue;
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("X Windows system pixmap (color)");
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("XPM");
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("XPM");
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadXPMImage;
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteXPMImage;
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsXPM;
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("X Windows system pixmap (color)");
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("XPM");
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r X P M I m a g e                                       %
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterXPMImage() removes format registrations made by the
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  XPM module from the list of supported formats.
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterXPMImage method is:
4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterXPMImage(void)
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterXPMImage(void)
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PICON");
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PM");
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("XPM");
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e P I C O N I m a g e                                             %
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
520a60c02075c4071dd1801b41db0b478f68683a6fecristy%  WritePICONImage() writes an image to a file in the Personal Icon format.
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WritePICONImage method is:
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WritePICONImage(const ImageInfo *image_info,
5253a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%        Image *image,ExceptionInfo *exception)
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5333a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%    o exception: return any errors or warnings in this structure.
5343a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePICONImage(const ImageInfo *image_info,
5373a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  Image *image,ExceptionInfo *exception)
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define ColormapExtent  155
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define GraymapExtent  95
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PiconGeometry  "48x48>"
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static unsigned char
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Colormap[]=
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x06, 0x00, 0x05, 0x00, 0xf4, 0x05,
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x00, 0x00, 0x2f, 0x4f, 0x4f, 0x70, 0x80, 0x90, 0x7e, 0x7e,
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x7e, 0xdc, 0xdc, 0xdc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00,
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xff, 0x1e, 0x90, 0xff, 0x87, 0xce, 0xeb, 0xe6, 0xe6, 0xfa, 0x00, 0xff,
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xff, 0x80, 0x00, 0x80, 0xb2, 0x22, 0x22, 0x2e, 0x8b, 0x57, 0x32, 0xcd,
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x32, 0x00, 0xff, 0x00, 0x98, 0xfb, 0x98, 0xff, 0x00, 0xff, 0xff, 0x00,
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0xff, 0x63, 0x47, 0xff, 0xa5, 0x00, 0xff, 0xd7, 0x00, 0xff, 0xff,
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0xee, 0x82, 0xee, 0xa0, 0x52, 0x2d, 0xcd, 0x85, 0x3f, 0xd2, 0xb4,
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x8c, 0xf5, 0xde, 0xb3, 0xff, 0xfa, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00,
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00,
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x05, 0x18, 0x20, 0x10, 0x08,
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x03, 0x51, 0x18, 0x07, 0x92, 0x28, 0x0b, 0xd3, 0x38, 0x0f, 0x14, 0x49,
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x13, 0x55, 0x59, 0x17, 0x96, 0x69, 0x1b, 0xd7, 0x85, 0x00, 0x3b,
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    },
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Graymap[]=
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x04, 0x00, 0xf3, 0x0f,
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x21, 0x21, 0x21, 0x33, 0x33,
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x33, 0x45, 0x45, 0x45, 0x54, 0x54, 0x54, 0x66, 0x66, 0x66, 0x78, 0x78,
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x78, 0x87, 0x87, 0x87, 0x99, 0x99, 0x99, 0xab, 0xab, 0xab, 0xba, 0xba,
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xba, 0xcc, 0xcc, 0xcc, 0xde, 0xde, 0xde, 0xed, 0xed, 0xed, 0xff, 0xff,
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xff, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00,
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x0c, 0x10, 0x04, 0x31,
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x48, 0x31, 0x07, 0x25, 0xb5, 0x58, 0x73, 0x4f, 0x04, 0x00, 0x3b,
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    };
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MaxCixels  92
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const char
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk"
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                         "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    buffer[MaxTextExtent],
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basename[MaxTextExtent],
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    name[MaxTextExtent],
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[MaxTextExtent];
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *affinity_image,
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *picon;
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImageInfo
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *blob_info;
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status,
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    transparent;
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5954c08aed51c5899665ade97263692328eea4af106cristy  PixelInfo
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel;
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  QuantizeInfo
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *quantize_info;
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RectangleInfo
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry;
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6044c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
607bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6114c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
614bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel,
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    colors;
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
618c6da28e61bb609d2b2cfdcc7752106c973415edbcristy  ssize_t
619c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    j,
620c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    k,
621c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    y;
622c6da28e61bb609d2b2cfdcc7752106c973415edbcristy
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6323a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception != (ExceptionInfo *) NULL);
6333a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception->signature == MagickSignature);
6343a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
6373d9f5ba107b160e1819bb6baeeb3a9f521e9f450cristy  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
6388d95109eca7aee289423a1ee81c232e309b383aecristy    (void) TransformImageColorspace(image,sRGBColorspace,exception);
6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetGeometry(image,&geometry);
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ParseMetaGeometry(PiconGeometry,&geometry.x,&geometry.y,
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    &geometry.width,&geometry.height);
642aa2c16cb5e695053aa78e40f66bc36fbef4b1ed1cristy  picon=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,
6433a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    exception);
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  blob_info=CloneImageInfo(image_info);
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) AcquireUniqueFilename(blob_info->filename);
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image_info->type != TrueColorType) &&
6473a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy      (IsImageGray(image,exception) != MagickFalse))
6483a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    affinity_image=BlobToImage(blob_info,Graymap,GraymapExtent,exception);
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6503a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    affinity_image=BlobToImage(blob_info,Colormap,ColormapExtent,exception);
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RelinquishUniqueFileResource(blob_info->filename);
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  blob_info=DestroyImageInfo(blob_info);
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((picon == (Image *) NULL) || (affinity_image == (Image *) NULL))
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  quantize_info=AcquireQuantizeInfo(image_info);
656018f07f7333b25743d0afff892450cebdb905c1acristy  status=RemapImage(quantize_info,picon,affinity_image,exception);
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  quantize_info=DestroyQuantizeInfo(quantize_info);
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affinity_image=DestroyImage(affinity_image);
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  transparent=MagickFalse;
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (picon->storage_class == PseudoClass)
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
662018f07f7333b25743d0afff892450cebdb905c1acristy      (void) CompressImageColormap(picon,exception);
6638a46d827a124555f0c48fb2368ec1bba8e079ab6cristy      if (picon->alpha_trait == BlendPixelTrait)
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        transparent=MagickTrue;
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Convert DirectClass to PseudoClass picon.
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
6718a46d827a124555f0c48fb2368ec1bba8e079ab6cristy      if (picon->alpha_trait == BlendPixelTrait)
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Map all the transparent pixels.
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
676bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (y=0; y < (ssize_t) picon->rows; y++)
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception);
679acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy            if (q == (Quantum *) NULL)
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
681bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (x=0; x < (ssize_t) picon->columns; x++)
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6834c08aed51c5899665ade97263692328eea4af106cristy              if (GetPixelAlpha(image,q) == (Quantum) TransparentAlpha)
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                transparent=MagickTrue;
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else
6864c08aed51c5899665ade97263692328eea4af106cristy                SetPixelAlpha(picon,OpaqueAlpha,q);
687ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy              q+=GetPixelChannels(picon);
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (SyncAuthenticPixels(picon,exception) == MagickFalse)
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
693018f07f7333b25743d0afff892450cebdb905c1acristy      (void) SetImageType(picon,PaletteType,exception);
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  colors=picon->colors;
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (transparent != MagickFalse)
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      colors++;
699101ab708b0574518ac5715da4d3915400e9df79acristy      picon->colormap=(PixelInfo *) ResizeQuantumMemory((void **)
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        picon->colormap,(size_t) colors,sizeof(*picon->colormap));
701101ab708b0574518ac5715da4d3915400e9df79acristy      if (picon->colormap == (PixelInfo *) NULL)
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowWriterException(ResourceLimitError,"MemoryAllocationError");
703bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (y=0; y < (ssize_t) picon->rows; y++)
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception);
706acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy        if (q == (Quantum *) NULL)
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
708bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (x=0; x < (ssize_t) picon->columns; x++)
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7104c08aed51c5899665ade97263692328eea4af106cristy          if (GetPixelAlpha(image,q) == (Quantum) TransparentAlpha)
7114c08aed51c5899665ade97263692328eea4af106cristy            SetPixelIndex(picon,picon->colors,q);
712ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy          q+=GetPixelChannels(picon);
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (SyncAuthenticPixels(picon,exception) == MagickFalse)
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Compute the character per pixel.
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  characters_per_pixel=1;
722bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels)
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel++;
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    XPM header.
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* XPM */\n");
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GetPathComponent(picon->filename,BasePath,basename);
729b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(buffer,MaxTextExtent,
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "static char *%s[] = {\n",basename);
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n");
733b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(buffer,MaxTextExtent,
734e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    "\"%.20g %.20g %.20g %.20g\",\n",(double) picon->columns,(double)
735e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    picon->rows,(double) colors,(double) characters_per_pixel);
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
7374c08aed51c5899665ade97263692328eea4af106cristy  GetPixelInfo(image,&pixel);
738bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) colors; i++)
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Define XPM color.
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
7439d8c8ce096b3b8b2b1df1aec061f17eabba22b1dcristy    pixel=picon->colormap[i];
7447020ae6594690c03a4f73784fd41a7131a5b22c6cristy    pixel.colorspace=sRGBColorspace;
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel.depth=8;
746a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy    pixel.alpha=(double) OpaqueAlpha;
747269c9413034627692b2a7d0a352f9dee4e8eada8cristy    (void) QueryColorname(image,&pixel,XPMCompliance,name,exception);
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (transparent != MagickFalse)
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
750bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        if (i == (ssize_t) (colors-1))
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyMagickString(name,"grey75",MaxTextExtent);
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Write XPM color.
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    k=i % MaxCixels;
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[0]=Cixel[k];
758bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (j=1; j < (ssize_t) characters_per_pixel; j++)
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      k=((i-k)/MaxCixels) % MaxCixels;
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]=Cixel[k];
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[j]='\0';
764b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s c %s\",\n",
765e6b6ece8afea47c6a48f0e189f8f0296606d40f2cristy       symbol,name);
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Define XPM pixels.
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* pixels */\n");
772bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) picon->rows; y++)
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7743a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    p=GetVirtualPixels(picon,0,y,picon->columns,1,exception);
7754c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,"\"");
778bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) picon->columns; x++)
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7804c08aed51c5899665ade97263692328eea4af106cristy      k=((ssize_t) GetPixelIndex(picon,p) % MaxCixels);
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[0]=Cixel[k];
782bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (j=1; j < (ssize_t) characters_per_pixel; j++)
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7844c08aed51c5899665ade97263692328eea4af106cristy        k=(((int) GetPixelIndex(picon,p)-k)/MaxCixels) % MaxCixels;
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        symbol[j]=Cixel[k];
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]='\0';
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CopyMagickString(buffer,symbol,MaxTextExtent);
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobString(image,buffer);
790ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
792b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s\n",
793bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      y == (ssize_t) (picon->rows-1) ? "" : ",");
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
7954cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
7964cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy      picon->rows);
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  picon=DestroyImage(picon);
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"};\n");
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e X P M I m a g e                                                 %
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
817a60c02075c4071dd1801b41db0b478f68683a6fecristy%  WriteXPMImage() writes an image to a file in the X pixmap format.
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WriteXPMImage method is:
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8213a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%      MagickBooleanType WriteXPMImage(const ImageInfo *image_info,
8223a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%        Image *image,ExceptionInfo *exception)
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8303a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%    o exception: return any errors or warnings in this structure.
8313a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8333a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristystatic MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image,
8343a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  ExceptionInfo *exception)
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MaxCixels  92
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const char
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk"
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                         "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    buffer[MaxTextExtent],
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basename[MaxTextExtent],
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    name[MaxTextExtent],
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[MaxTextExtent];
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8514c08aed51c5899665ade97263692328eea4af106cristy  PixelInfo
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel;
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8544c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
857bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
861bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel;
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
864c6da28e61bb609d2b2cfdcc7752106c973415edbcristy  ssize_t
865c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    j,
866c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    k,
867c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    opacity,
868c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    y;
869c6da28e61bb609d2b2cfdcc7752106c973415edbcristy
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
8793a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception != (ExceptionInfo *) NULL);
8803a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception->signature == MagickSignature);
8813a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
8843d9f5ba107b160e1819bb6baeeb3a9f521e9f450cristy  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
8858d95109eca7aee289423a1ee81c232e309b383aecristy    (void) TransformImageColorspace(image,sRGBColorspace,exception);
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  opacity=(-1);
8878a46d827a124555f0c48fb2368ec1bba8e079ab6cristy  if (image->alpha_trait != BlendPixelTrait)
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((image->storage_class == DirectClass) || (image->colors > 256))
890018f07f7333b25743d0afff892450cebdb905c1acristy        (void) SetImageType(image,PaletteType,exception);
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
894a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      double
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha,
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        beta;
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Identify transparent colormap index.
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((image->storage_class == DirectClass) || (image->colors > 256))
902018f07f7333b25743d0afff892450cebdb905c1acristy        (void) SetImageType(image,PaletteBilevelMatteType,exception);
903bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (i=0; i < (ssize_t) image->colors; i++)
9044c08aed51c5899665ade97263692328eea4af106cristy        if (image->colormap[i].alpha != OpaqueAlpha)
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (opacity < 0)
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                opacity=i;
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                continue;
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
911a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy            alpha=(double) TransparentAlpha-(double)
9124c08aed51c5899665ade97263692328eea4af106cristy              image->colormap[i].alpha;
913a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy            beta=(double) TransparentAlpha-(double)
9144c08aed51c5899665ade97263692328eea4af106cristy              image->colormap[opacity].alpha;
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (alpha < beta)
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              opacity=i;
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (opacity == -1)
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
920018f07f7333b25743d0afff892450cebdb905c1acristy          (void) SetImageType(image,PaletteBilevelMatteType,exception);
921bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (i=0; i < (ssize_t) image->colors; i++)
9224c08aed51c5899665ade97263692328eea4af106cristy            if (image->colormap[i].alpha != OpaqueAlpha)
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (opacity < 0)
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    opacity=i;
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    continue;
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
929a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy                alpha=(Quantum) TransparentAlpha-(double)
9304c08aed51c5899665ade97263692328eea4af106cristy                  image->colormap[i].alpha;
931a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy                beta=(Quantum) TransparentAlpha-(double)
9324c08aed51c5899665ade97263692328eea4af106cristy                  image->colormap[opacity].alpha;
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (alpha < beta)
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  opacity=i;
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (opacity >= 0)
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colormap[opacity].red=image->transparent_color.red;
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colormap[opacity].green=image->transparent_color.green;
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colormap[opacity].blue=image->transparent_color.blue;
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Compute the character per pixel.
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  characters_per_pixel=1;
948bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (k=MaxCixels; (ssize_t) image->colors > k; k*=MaxCixels)
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel++;
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    XPM header.
9523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* XPM */\n");
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GetPathComponent(image->filename,BasePath,basename);
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (isalnum((int) ((unsigned char) *basename)) == 0)
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
957b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      (void) FormatLocaleString(buffer,MaxTextExtent,"xpm_%s",basename);
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CopyMagickString(basename,buffer,MaxTextExtent);
9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9602f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy  if (isalpha((int) ((unsigned char) basename[0])) == 0)
9612f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy    basename[0]='_';
9622f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy  for (i=1; basename[i] != '\0'; i++)
9632f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy    if (isalnum((int) ((unsigned char) basename[i])) == 0)
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      basename[i]='_';
965b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(buffer,MaxTextExtent,
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "static char *%s[] = {\n",basename);
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n");
969b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(buffer,MaxTextExtent,
970e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    "\"%.20g %.20g %.20g %.20g \",\n",(double) image->columns,(double)
971e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    image->rows,(double) image->colors,(double) characters_per_pixel);
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
9734c08aed51c5899665ade97263692328eea4af106cristy  GetPixelInfo(image,&pixel);
974bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) image->colors; i++)
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Define XPM color.
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
9799d8c8ce096b3b8b2b1df1aec061f17eabba22b1dcristy    pixel=image->colormap[i];
9807020ae6594690c03a4f73784fd41a7131a5b22c6cristy    pixel.colorspace=sRGBColorspace;
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel.depth=8;
982a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy    pixel.alpha=(double) OpaqueAlpha;
983269c9413034627692b2a7d0a352f9dee4e8eada8cristy    (void) QueryColorname(image,&pixel,XPMCompliance,name,exception);
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (i == opacity)
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CopyMagickString(name,"None",MaxTextExtent);
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Write XPM color.
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    k=i % MaxCixels;
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[0]=Cixel[k];
991bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (j=1; j < (ssize_t) characters_per_pixel; j++)
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      k=((i-k)/MaxCixels) % MaxCixels;
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]=Cixel[k];
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[j]='\0';
997b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s c %s\",\n",symbol,
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      name);
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Define XPM pixels.
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* pixels */\n");
1005bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
10073a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
10084c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,"\"");
1011bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10134c08aed51c5899665ade97263692328eea4af106cristy      k=((ssize_t) GetPixelIndex(image,p) % MaxCixels);
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[0]=Cixel[k];
1015bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (j=1; j < (ssize_t) characters_per_pixel; j++)
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
10174c08aed51c5899665ade97263692328eea4af106cristy        k=(((int) GetPixelIndex(image,p)-k)/MaxCixels) % MaxCixels;
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        symbol[j]=Cixel[k];
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]='\0';
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CopyMagickString(buffer,symbol,MaxTextExtent);
10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobString(image,buffer);
1023ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1025b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s\n",
1026bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      (y == (ssize_t) (image->rows-1) ? "" : ","));
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
10288b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy    if (image->previous == (Image *) NULL)
10298b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy      {
10304cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy        status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
10314cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy          image->rows);
10328b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy        if (status == MagickFalse)
10338b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy          break;
10348b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy      }
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"};\n");
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1040