xpm.c revision 17f11b056210f082a6d0e54ac5d68e6d72fa76b2
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%                                                                             %
20b56bb24a985ca4366713bcd8ffdfacbb48a98a2fcristy%  Copyright 1999-2015 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
154dd12db54df58041276651900743c280114886406cristystatic size_t CopyXPMColor(char *destination,const char *source,size_t length)
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
156bcbe6c82e26186780b29494789b93c209aee585bcristy  register const char
157dd12db54df58041276651900743c280114886406cristy    *p;
158dd12db54df58041276651900743c280114886406cristy
159dd12db54df58041276651900743c280114886406cristy  p=source;
160216e0330eee93ba2fa460b8f52bbfa199b381799cristy  while (--length && (*p != '\0'))
161dd12db54df58041276651900743c280114886406cristy    *destination++=(*p++);
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *destination='\0';
163dd12db54df58041276651900743c280114886406cristy  return((size_t) (p-source));
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic char *NextXPMLine(char *p)
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
168f432c635c526259b858c9aad3d409c5c44545686cristy  assert(p != (char *) NULL);
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=strchr(p,'\n');
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (p != (char *) NULL)
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p++;
1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(p);
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline size_t MagickMin(const size_t x,const size_t y)
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x < y)
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
182785a7231a4419ac9e5853e72bb2bb839cad8b2efdirkstatic char *ParseXPMColor(char *color,MagickBooleanType search_start)
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define NumberTargets  6
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const char
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
193bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const char
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *targets[NumberTargets] = { "c ", "g ", "g4 ", "m ", "b ", "s " };
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
199785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk  if (search_start != MagickFalse)
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
201785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk      for (i=0; i < NumberTargets; i++)
202785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk      {
203785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk        p=color;
204785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk        for (q=targets[i]; *p != '\0'; p++)
205785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk        {
206785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          if (*p == '\n')
207785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk            break;
208785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          if (*p != *q)
209785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk            continue;
210785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          if (isspace((int) ((unsigned char) (*(p-1)))) == 0)
211785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk            continue;
212785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          r=p;
213785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          for ( ; ; )
214785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          {
215785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk            if (*q == '\0')
216785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk              return(p);
217785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk            if (*r++ != *q++)
218785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk              break;
219785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          }
220785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          q=targets[i];
221785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk        }
222785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk      }
223785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk      return((char *) NULL);
224785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    }
22576d045a787b16952e2111c248713e72de2f593dacristy  for (p=color+1; *p != '\0'; p++)
22676d045a787b16952e2111c248713e72de2f593dacristy  {
22776d045a787b16952e2111c248713e72de2f593dacristy    if (*p == '\n')
22876d045a787b16952e2111c248713e72de2f593dacristy      break;
22976d045a787b16952e2111c248713e72de2f593dacristy    if (isspace((int) ((unsigned char) (*(p-1)))) == 0)
23076d045a787b16952e2111c248713e72de2f593dacristy      continue;
23176d045a787b16952e2111c248713e72de2f593dacristy    if (isspace((int) ((unsigned char) (*p))) != 0)
23276d045a787b16952e2111c248713e72de2f593dacristy      continue;
23376d045a787b16952e2111c248713e72de2f593dacristy    for (i=0; i < NumberTargets; i++)
234785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    {
23576d045a787b16952e2111c248713e72de2f593dacristy      if ((*p == *targets[i]) && (*(p+1) == *(targets[i]+1)))
23676d045a787b16952e2111c248713e72de2f593dacristy        return(p);
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
23876d045a787b16952e2111c248713e72de2f593dacristy  }
23976d045a787b16952e2111c248713e72de2f593dacristy  return(p);
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception)
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
245785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    *grey,
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    key[MaxTextExtent],
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    target[MaxTextExtent],
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *xpm_buffer;
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    active,
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
258785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    *next,
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
260785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    *q;
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
262bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2654c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length;
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SplayTreeInfo
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *xpm_colors;
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ssize_t
275c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    count,
276c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    j,
277c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    y;
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
279d8af19d72fd93dfd2e42eb0b266cac384a6ae833cristy  unsigned long
280f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    colors,
281f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    columns,
282f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    rows,
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width;
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
2959950d57e1124b73f684fb5946e206994cefda628cristy  image=AcquireImage(image_info,exception);
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read XPM file.
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  length=MaxTextExtent;
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  xpm_buffer=(char *) AcquireQuantumMemory((size_t) length,sizeof(*xpm_buffer));
307dd12db54df58041276651900743c280114886406cristy  if (xpm_buffer == (char *) NULL)
308dd12db54df58041276651900743c280114886406cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
309dd12db54df58041276651900743c280114886406cristy  *xpm_buffer='\0';
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=xpm_buffer;
311dd12db54df58041276651900743c280114886406cristy  while (ReadBlobString(image,p) != (char *) NULL)
312dd12db54df58041276651900743c280114886406cristy  {
313dd12db54df58041276651900743c280114886406cristy    if ((*p == '#') && ((p == xpm_buffer) || (*(p-1) == '\n')))
314dd12db54df58041276651900743c280114886406cristy      continue;
315dd12db54df58041276651900743c280114886406cristy    if ((*p == '}') && (*(p+1) == ';'))
316dd12db54df58041276651900743c280114886406cristy      break;
317dd12db54df58041276651900743c280114886406cristy    p+=strlen(p);
318dd12db54df58041276651900743c280114886406cristy    if ((size_t) (p-xpm_buffer+MaxTextExtent) < length)
319dd12db54df58041276651900743c280114886406cristy      continue;
320dd12db54df58041276651900743c280114886406cristy    length<<=1;
321dd12db54df58041276651900743c280114886406cristy    xpm_buffer=(char *) ResizeQuantumMemory(xpm_buffer,length+MaxTextExtent,
322dd12db54df58041276651900743c280114886406cristy      sizeof(*xpm_buffer));
323dd12db54df58041276651900743c280114886406cristy    if (xpm_buffer == (char *) NULL)
324dd12db54df58041276651900743c280114886406cristy      break;
325dd12db54df58041276651900743c280114886406cristy    p=xpm_buffer+strlen(xpm_buffer);
326dd12db54df58041276651900743c280114886406cristy  }
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (xpm_buffer == (char *) NULL)
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Remove comments.
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=0;
33393b02b797c4127ce2b06dbd3b2d75ecc33fca759dirk  width=0;
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=xpm_buffer; *p != '\0'; p++)
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*p != '"')
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      continue;
338f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    count=(ssize_t) sscanf(p+1,"%lu %lu %lu %lu",&columns,&rows,&colors,&width);
339f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    image->columns=columns;
340f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    image->rows=rows;
341f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    image->colors=colors;
342e6b6ece8afea47c6a48f0e189f8f0296606d40f2cristy    if (count == 4)
343e6b6ece8afea47c6a48f0e189f8f0296606d40f2cristy      break;
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((count != 4) || (width > 10) || (image->columns == 0) ||
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (image->rows == 0) || (image->colors == 0))
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Remove unquoted characters.
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  active=MagickFalse;
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=xpm_buffer;
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  while (*p != '\0')
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*p++ == '"')
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (active != MagickFalse)
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *q++='\n';
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        active=active != MagickFalse ? MagickFalse : MagickTrue;
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (active != MagickFalse)
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *q++=(*p);
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *q='\0';
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize image structure.
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  xpm_colors=NewSplayTree(CompareXPMColor,RelinquishMagickMemory,
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void *(*)(void *)) NULL);
370018f07f7333b25743d0afff892450cebdb905c1acristy  if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read image colormap.
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3751d92f7952ace182649f73e84b7ecbba1798e8fffcristy  image->depth=1;
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  next=NextXPMLine(xpm_buffer);
37776d045a787b16952e2111c248713e72de2f593dacristy  for (j=0; (j < (ssize_t) image->colors) && (next != (char *) NULL); j++)
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=next;
3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    next=NextXPMLine(p);
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) CopyXPMColor(key,p,MagickMin((size_t) width,MaxTextExtent));
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=AddValueToSplayTree(xpm_colors,ConstantString(key),(void *) j);
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Parse color.
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) CopyMagickString(target,"gray",MaxTextExtent);
387785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    q=ParseXPMColor(p+width,MagickTrue);
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (q != (char *) NULL)
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((isspace((int) ((unsigned char) *q)) == 0) && (*q != '\0'))
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          q++;
392f432c635c526259b858c9aad3d409c5c44545686cristy        if ((next-q) < 0)
393f432c635c526259b858c9aad3d409c5c44545686cristy          break;
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (next != (char *) NULL)
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyXPMColor(target,q,MagickMin((size_t) (next-q),
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            MaxTextExtent));
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyMagickString(target,q,MaxTextExtent);
399785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk        q=ParseXPMColor(target,MagickFalse);
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (q != (char *) NULL)
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *q='\0';
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    StripString(target);
404785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    grey=strstr(target,"grey");
405785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    if (grey != (char *) NULL)
4068695d953715611a38ca9050ae987f855db6a5b3fdirk      grey[2]='a';
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (LocaleCompare(target,"none") == 0)
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->storage_class=DirectClass;
4108a46d827a124555f0c48fb2368ec1bba8e079ab6cristy        image->alpha_trait=BlendPixelTrait;
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
412fc502a1bd2f6e35346f02b0b7c466ac4e280d976cristy    status=QueryColorCompliance(target,XPMCompliance,&image->colormap[j],
413a60c02075c4071dd1801b41db0b478f68683a6fecristy      exception);
414a60c02075c4071dd1801b41db0b478f68683a6fecristy    if (status == MagickFalse)
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
4161d92f7952ace182649f73e84b7ecbba1798e8fffcristy    if (image->depth < image->colormap[j].depth)
4171d92f7952ace182649f73e84b7ecbba1798e8fffcristy      image->depth=image->colormap[j].depth;
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
419bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  if (j < (ssize_t) image->colors)
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(CorruptImageError,"CorruptImage");
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  j=0;
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->ping == MagickFalse)
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Read image pixels.
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
427acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy      status=SetImageExtent(image,image->columns,image->rows,exception);
428acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy      if (status == MagickFalse)
429acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy        return(DestroyImageList(image));
430bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (y=0; y < (ssize_t) image->rows; y++)
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=NextXPMLine(p);
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (p == (char *) NULL)
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        r=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
4364c08aed51c5899665ade97263692328eea4af106cristy        if (r == (Quantum *) NULL)
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
438bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (x=0; x < (ssize_t) image->columns; x++)
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
440dd12db54df58041276651900743c280114886406cristy          p+=CopyXPMColor(key,p,MagickMin(width,MaxTextExtent));
441bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          j=(ssize_t) GetValueFromSplayTree(xpm_colors,key);
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (image->storage_class == PseudoClass)
443dd12db54df58041276651900743c280114886406cristy            SetPixelIndex(image,(Quantum) j,r);
444803640d20a6a664315eddfff6f8531d0c5e0871dcristy          SetPixelInfoPixel(image,image->colormap+j,r);
445ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy          r+=GetPixelChannels(image);
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (SyncAuthenticPixels(image,exception) == MagickFalse)
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
450bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      if (y < (ssize_t) image->rows)
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowReaderException(CorruptImageError,"NotEnoughPixelData");
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  xpm_colors=DestroySplayTree(xpm_colors);
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
4623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r X P M I m a g e                                           %
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterXPMImage() adds attributes for the XPM image format to
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterXPMImage method is:
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
481bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterXPMImage(void)
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
484bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterXPMImage(void)
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PICON");
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadXPMImage;
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePICONImage;
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("Personal Icon");
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("XPM");
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("PM");
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadXPMImage;
4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteXPMImage;
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->stealth=MagickTrue;
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("X Windows system pixmap (color)");
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("XPM");
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry=SetMagickInfo("XPM");
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadXPMImage;
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteXPMImage;
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsXPM;
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->adjoin=MagickFalse;
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->description=ConstantString("X Windows system pixmap (color)");
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->module=ConstantString("XPM");
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r X P M I m a g e                                       %
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterXPMImage() removes format registrations made by the
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  XPM module from the list of supported formats.
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterXPMImage method is:
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterXPMImage(void)
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterXPMImage(void)
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PICON");
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PM");
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("XPM");
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e P I C O N I m a g e                                             %
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
552a60c02075c4071dd1801b41db0b478f68683a6fecristy%  WritePICONImage() writes an image to a file in the Personal Icon format.
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WritePICONImage method is:
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WritePICONImage(const ImageInfo *image_info,
5573a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%        Image *image,ExceptionInfo *exception)
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5653a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%    o exception: return any errors or warnings in this structure.
5663a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePICONImage(const ImageInfo *image_info,
5693a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  Image *image,ExceptionInfo *exception)
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define ColormapExtent  155
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define GraymapExtent  95
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PiconGeometry  "48x48>"
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static unsigned char
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Colormap[]=
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x06, 0x00, 0x05, 0x00, 0xf4, 0x05,
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x00, 0x00, 0x2f, 0x4f, 0x4f, 0x70, 0x80, 0x90, 0x7e, 0x7e,
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x7e, 0xdc, 0xdc, 0xdc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00,
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xff, 0x1e, 0x90, 0xff, 0x87, 0xce, 0xeb, 0xe6, 0xe6, 0xfa, 0x00, 0xff,
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xff, 0x80, 0x00, 0x80, 0xb2, 0x22, 0x22, 0x2e, 0x8b, 0x57, 0x32, 0xcd,
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x32, 0x00, 0xff, 0x00, 0x98, 0xfb, 0x98, 0xff, 0x00, 0xff, 0xff, 0x00,
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0xff, 0x63, 0x47, 0xff, 0xa5, 0x00, 0xff, 0xd7, 0x00, 0xff, 0xff,
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0xee, 0x82, 0xee, 0xa0, 0x52, 0x2d, 0xcd, 0x85, 0x3f, 0xd2, 0xb4,
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x8c, 0xf5, 0xde, 0xb3, 0xff, 0xfa, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00,
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00,
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x05, 0x18, 0x20, 0x10, 0x08,
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x03, 0x51, 0x18, 0x07, 0x92, 0x28, 0x0b, 0xd3, 0x38, 0x0f, 0x14, 0x49,
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x13, 0x55, 0x59, 0x17, 0x96, 0x69, 0x1b, 0xd7, 0x85, 0x00, 0x3b,
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    },
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Graymap[]=
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x04, 0x00, 0xf3, 0x0f,
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x21, 0x21, 0x21, 0x33, 0x33,
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x33, 0x45, 0x45, 0x45, 0x54, 0x54, 0x54, 0x66, 0x66, 0x66, 0x78, 0x78,
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x78, 0x87, 0x87, 0x87, 0x99, 0x99, 0x99, 0xab, 0xab, 0xab, 0xba, 0xba,
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xba, 0xcc, 0xcc, 0xcc, 0xde, 0xde, 0xde, 0xed, 0xed, 0xed, 0xff, 0xff,
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xff, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00,
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x0c, 0x10, 0x04, 0x31,
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x48, 0x31, 0x07, 0x25, 0xb5, 0x58, 0x73, 0x4f, 0x04, 0x00, 0x3b,
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    };
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MaxCixels  92
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const char
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk"
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                         "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    buffer[MaxTextExtent],
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basename[MaxTextExtent],
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    name[MaxTextExtent],
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[MaxTextExtent];
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *affinity_image,
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *picon;
6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImageInfo
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *blob_info;
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status,
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    transparent;
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6274c08aed51c5899665ade97263692328eea4af106cristy  PixelInfo
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel;
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  QuantizeInfo
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *quantize_info;
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RectangleInfo
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry;
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6364c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
639bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6434c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
646bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel,
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    colors;
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
650c6da28e61bb609d2b2cfdcc7752106c973415edbcristy  ssize_t
651c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    j,
652c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    k,
653c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    y;
654c6da28e61bb609d2b2cfdcc7752106c973415edbcristy
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6643a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception != (ExceptionInfo *) NULL);
6653a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception->signature == MagickSignature);
6663a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
669af8d391906d11f0a1f2bbf4e2adbc4995c852d33cristy  (void) TransformImageColorspace(image,sRGBColorspace,exception);
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetGeometry(image,&geometry);
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ParseMetaGeometry(PiconGeometry,&geometry.x,&geometry.y,
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    &geometry.width,&geometry.height);
673aa2c16cb5e695053aa78e40f66bc36fbef4b1ed1cristy  picon=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,
6743a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    exception);
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  blob_info=CloneImageInfo(image_info);
6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) AcquireUniqueFilename(blob_info->filename);
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image_info->type != TrueColorType) &&
6783a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy      (IsImageGray(image,exception) != MagickFalse))
6793a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    affinity_image=BlobToImage(blob_info,Graymap,GraymapExtent,exception);
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6813a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    affinity_image=BlobToImage(blob_info,Colormap,ColormapExtent,exception);
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RelinquishUniqueFileResource(blob_info->filename);
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  blob_info=DestroyImageInfo(blob_info);
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((picon == (Image *) NULL) || (affinity_image == (Image *) NULL))
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  quantize_info=AcquireQuantizeInfo(image_info);
687018f07f7333b25743d0afff892450cebdb905c1acristy  status=RemapImage(quantize_info,picon,affinity_image,exception);
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  quantize_info=DestroyQuantizeInfo(quantize_info);
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affinity_image=DestroyImage(affinity_image);
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  transparent=MagickFalse;
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (picon->storage_class == PseudoClass)
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
693018f07f7333b25743d0afff892450cebdb905c1acristy      (void) CompressImageColormap(picon,exception);
69417f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      if (picon->alpha_trait != UndefinedPixelTrait)
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        transparent=MagickTrue;
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Convert DirectClass to PseudoClass picon.
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
70217f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      if (picon->alpha_trait != UndefinedPixelTrait)
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Map all the transparent pixels.
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
707bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (y=0; y < (ssize_t) picon->rows; y++)
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception);
710acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy            if (q == (Quantum *) NULL)
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
712bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (x=0; x < (ssize_t) picon->columns; x++)
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7144c08aed51c5899665ade97263692328eea4af106cristy              if (GetPixelAlpha(image,q) == (Quantum) TransparentAlpha)
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                transparent=MagickTrue;
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else
7174c08aed51c5899665ade97263692328eea4af106cristy                SetPixelAlpha(picon,OpaqueAlpha,q);
718ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy              q+=GetPixelChannels(picon);
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (SyncAuthenticPixels(picon,exception) == MagickFalse)
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
724018f07f7333b25743d0afff892450cebdb905c1acristy      (void) SetImageType(picon,PaletteType,exception);
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  colors=picon->colors;
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (transparent != MagickFalse)
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      colors++;
730101ab708b0574518ac5715da4d3915400e9df79acristy      picon->colormap=(PixelInfo *) ResizeQuantumMemory((void **)
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        picon->colormap,(size_t) colors,sizeof(*picon->colormap));
732101ab708b0574518ac5715da4d3915400e9df79acristy      if (picon->colormap == (PixelInfo *) NULL)
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowWriterException(ResourceLimitError,"MemoryAllocationError");
734bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (y=0; y < (ssize_t) picon->rows; y++)
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception);
737acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy        if (q == (Quantum *) NULL)
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
739bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (x=0; x < (ssize_t) picon->columns; x++)
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7414c08aed51c5899665ade97263692328eea4af106cristy          if (GetPixelAlpha(image,q) == (Quantum) TransparentAlpha)
742dd12db54df58041276651900743c280114886406cristy            SetPixelIndex(picon,(Quantum) picon->colors,q);
743ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy          q+=GetPixelChannels(picon);
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (SyncAuthenticPixels(picon,exception) == MagickFalse)
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Compute the character per pixel.
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  characters_per_pixel=1;
753bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels)
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel++;
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    XPM header.
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* XPM */\n");
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GetPathComponent(picon->filename,BasePath,basename);
760b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(buffer,MaxTextExtent,
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "static char *%s[] = {\n",basename);
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n");
764b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(buffer,MaxTextExtent,
765e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    "\"%.20g %.20g %.20g %.20g\",\n",(double) picon->columns,(double)
766e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    picon->rows,(double) colors,(double) characters_per_pixel);
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
7684c08aed51c5899665ade97263692328eea4af106cristy  GetPixelInfo(image,&pixel);
769bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) colors; i++)
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Define XPM color.
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
7749d8c8ce096b3b8b2b1df1aec061f17eabba22b1dcristy    pixel=picon->colormap[i];
7757020ae6594690c03a4f73784fd41a7131a5b22c6cristy    pixel.colorspace=sRGBColorspace;
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel.depth=8;
777a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy    pixel.alpha=(double) OpaqueAlpha;
778269c9413034627692b2a7d0a352f9dee4e8eada8cristy    (void) QueryColorname(image,&pixel,XPMCompliance,name,exception);
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (transparent != MagickFalse)
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
781bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        if (i == (ssize_t) (colors-1))
7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CopyMagickString(name,"grey75",MaxTextExtent);
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Write XPM color.
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    k=i % MaxCixels;
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[0]=Cixel[k];
789bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (j=1; j < (ssize_t) characters_per_pixel; j++)
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      k=((i-k)/MaxCixels) % MaxCixels;
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]=Cixel[k];
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[j]='\0';
795b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s c %s\",\n",
796e6b6ece8afea47c6a48f0e189f8f0296606d40f2cristy       symbol,name);
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Define XPM pixels.
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* pixels */\n");
803bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) picon->rows; y++)
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
8053a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    p=GetVirtualPixels(picon,0,y,picon->columns,1,exception);
8064c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,"\"");
809bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) picon->columns; x++)
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8114c08aed51c5899665ade97263692328eea4af106cristy      k=((ssize_t) GetPixelIndex(picon,p) % MaxCixels);
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[0]=Cixel[k];
813bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (j=1; j < (ssize_t) characters_per_pixel; j++)
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8154c08aed51c5899665ade97263692328eea4af106cristy        k=(((int) GetPixelIndex(picon,p)-k)/MaxCixels) % MaxCixels;
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        symbol[j]=Cixel[k];
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]='\0';
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CopyMagickString(buffer,symbol,MaxTextExtent);
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobString(image,buffer);
821ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
823b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s\n",
824bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      y == (ssize_t) (picon->rows-1) ? "" : ",");
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
8264cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
8274cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy      picon->rows);
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  picon=DestroyImage(picon);
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"};\n");
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e X P M I m a g e                                                 %
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
848a60c02075c4071dd1801b41db0b478f68683a6fecristy%  WriteXPMImage() writes an image to a file in the X pixmap format.
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WriteXPMImage method is:
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8523a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%      MagickBooleanType WriteXPMImage(const ImageInfo *image_info,
8533a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%        Image *image,ExceptionInfo *exception)
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8613a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%    o exception: return any errors or warnings in this structure.
8623a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8643a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristystatic MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image,
8653a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  ExceptionInfo *exception)
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MaxCixels  92
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const char
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk"
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                         "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    buffer[MaxTextExtent],
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    basename[MaxTextExtent],
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    name[MaxTextExtent],
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[MaxTextExtent];
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8824c08aed51c5899665ade97263692328eea4af106cristy  PixelInfo
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel;
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8854c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
888bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
892bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel;
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
895c6da28e61bb609d2b2cfdcc7752106c973415edbcristy  ssize_t
896c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    j,
897c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    k,
898c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    opacity,
899c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    y;
900c6da28e61bb609d2b2cfdcc7752106c973415edbcristy
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info->signature == MagickSignature);
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
9103a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception != (ExceptionInfo *) NULL);
9113a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception->signature == MagickSignature);
9123a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
9153d9f5ba107b160e1819bb6baeeb3a9f521e9f450cristy  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
9168d95109eca7aee289423a1ee81c232e309b383aecristy    (void) TransformImageColorspace(image,sRGBColorspace,exception);
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  opacity=(-1);
91817f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy  if (image->alpha_trait == UndefinedPixelTrait)
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((image->storage_class == DirectClass) || (image->colors > 256))
921018f07f7333b25743d0afff892450cebdb905c1acristy        (void) SetImageType(image,PaletteType,exception);
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
925a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      double
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha,
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        beta;
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Identify transparent colormap index.
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((image->storage_class == DirectClass) || (image->colors > 256))
933018f07f7333b25743d0afff892450cebdb905c1acristy        (void) SetImageType(image,PaletteBilevelMatteType,exception);
934bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (i=0; i < (ssize_t) image->colors; i++)
9354c08aed51c5899665ade97263692328eea4af106cristy        if (image->colormap[i].alpha != OpaqueAlpha)
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (opacity < 0)
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                opacity=i;
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                continue;
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
942a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy            alpha=(double) TransparentAlpha-(double)
9434c08aed51c5899665ade97263692328eea4af106cristy              image->colormap[i].alpha;
944a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy            beta=(double) TransparentAlpha-(double)
9454c08aed51c5899665ade97263692328eea4af106cristy              image->colormap[opacity].alpha;
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (alpha < beta)
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              opacity=i;
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (opacity == -1)
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
951018f07f7333b25743d0afff892450cebdb905c1acristy          (void) SetImageType(image,PaletteBilevelMatteType,exception);
952bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (i=0; i < (ssize_t) image->colors; i++)
9534c08aed51c5899665ade97263692328eea4af106cristy            if (image->colormap[i].alpha != OpaqueAlpha)
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (opacity < 0)
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    opacity=i;
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    continue;
9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
960a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy                alpha=(Quantum) TransparentAlpha-(double)
9614c08aed51c5899665ade97263692328eea4af106cristy                  image->colormap[i].alpha;
962a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy                beta=(Quantum) TransparentAlpha-(double)
9634c08aed51c5899665ade97263692328eea4af106cristy                  image->colormap[opacity].alpha;
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (alpha < beta)
9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  opacity=i;
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (opacity >= 0)
9693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colormap[opacity].red=image->transparent_color.red;
9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colormap[opacity].green=image->transparent_color.green;
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colormap[opacity].blue=image->transparent_color.blue;
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Compute the character per pixel.
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  characters_per_pixel=1;
979bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (k=MaxCixels; (ssize_t) image->colors > k; k*=MaxCixels)
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel++;
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    XPM header.
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* XPM */\n");
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GetPathComponent(image->filename,BasePath,basename);
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (isalnum((int) ((unsigned char) *basename)) == 0)
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
988b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      (void) FormatLocaleString(buffer,MaxTextExtent,"xpm_%s",basename);
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CopyMagickString(basename,buffer,MaxTextExtent);
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9912f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy  if (isalpha((int) ((unsigned char) basename[0])) == 0)
9922f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy    basename[0]='_';
9932f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy  for (i=1; basename[i] != '\0'; i++)
9942f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy    if (isalnum((int) ((unsigned char) basename[i])) == 0)
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      basename[i]='_';
996b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(buffer,MaxTextExtent,
9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "static char *%s[] = {\n",basename);
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n");
1000b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(buffer,MaxTextExtent,
1001e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    "\"%.20g %.20g %.20g %.20g \",\n",(double) image->columns,(double)
1002e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    image->rows,(double) image->colors,(double) characters_per_pixel);
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
10044c08aed51c5899665ade97263692328eea4af106cristy  GetPixelInfo(image,&pixel);
1005bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) image->colors; i++)
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Define XPM color.
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
10109d8c8ce096b3b8b2b1df1aec061f17eabba22b1dcristy    pixel=image->colormap[i];
10117020ae6594690c03a4f73784fd41a7131a5b22c6cristy    pixel.colorspace=sRGBColorspace;
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel.depth=8;
1013a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy    pixel.alpha=(double) OpaqueAlpha;
1014269c9413034627692b2a7d0a352f9dee4e8eada8cristy    (void) QueryColorname(image,&pixel,XPMCompliance,name,exception);
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (i == opacity)
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CopyMagickString(name,"None",MaxTextExtent);
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Write XPM color.
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    k=i % MaxCixels;
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[0]=Cixel[k];
1022bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (j=1; j < (ssize_t) characters_per_pixel; j++)
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      k=((i-k)/MaxCixels) % MaxCixels;
10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]=Cixel[k];
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[j]='\0';
1028b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s c %s\",\n",symbol,
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      name);
10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Define XPM pixels.
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* pixels */\n");
1036bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
10383a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
10394c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,"\"");
1042bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10444c08aed51c5899665ade97263692328eea4af106cristy      k=((ssize_t) GetPixelIndex(image,p) % MaxCixels);
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[0]=Cixel[k];
1046bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (j=1; j < (ssize_t) characters_per_pixel; j++)
10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
10484c08aed51c5899665ade97263692328eea4af106cristy        k=(((int) GetPixelIndex(image,p)-k)/MaxCixels) % MaxCixels;
10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        symbol[j]=Cixel[k];
10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]='\0';
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CopyMagickString(buffer,symbol,MaxTextExtent);
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobString(image,buffer);
1054ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1056b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s\n",
1057bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      (y == (ssize_t) (image->rows-1) ? "" : ","));
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
10598b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy    if (image->previous == (Image *) NULL)
10608b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy      {
10614cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy        status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
10624cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy          image->rows);
10638b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy        if (status == MagickFalse)
10648b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy          break;
10658b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy      }
10663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"};\n");
10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1071