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%                                                                             %
207ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy%  Copyright 1999-2016 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
1545463e2e01503c6cfe10c95ab1cfa3f85ff46de69cristystatic ssize_t CopyXPMColor(char *destination,const char *source,size_t length)
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
156bcbe6c82e26186780b29494789b93c209aee585bcristy  register const char
157dd12db54df58041276651900743c280114886406cristy    *p;
158dd12db54df58041276651900743c280114886406cristy
159dd12db54df58041276651900743c280114886406cristy  p=source;
16026f64583b667398ca0a12bfd7a560b15567b76b8cristy  while (length-- && (*p != '\0'))
161dd12db54df58041276651900743c280114886406cristy    *destination++=(*p++);
1626f1d4197adb5c45d716ce2957826101e8da5f136cristy  if (length != 0)
1636f1d4197adb5c45d716ce2957826101e8da5f136cristy    *destination='\0';
1645463e2e01503c6cfe10c95ab1cfa3f85ff46de69cristy  return((ssize_t) (p-source));
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic char *NextXPMLine(char *p)
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
169f432c635c526259b858c9aad3d409c5c44545686cristy  assert(p != (char *) NULL);
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=strchr(p,'\n');
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (p != (char *) NULL)
1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p++;
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(p);
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
176785a7231a4419ac9e5853e72bb2bb839cad8b2efdirkstatic char *ParseXPMColor(char *color,MagickBooleanType search_start)
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define NumberTargets  6
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const char
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
187bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const char
191629f80558ba1e82b0317a3d778deaf195c8e37e5Cristy    *const targets[NumberTargets] = { "c ", "g ", "g4 ", "m ", "b ", "s " };
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
193785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk  if (search_start != MagickFalse)
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
195785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk      for (i=0; i < NumberTargets; i++)
196785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk      {
197785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk        p=color;
198785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk        for (q=targets[i]; *p != '\0'; p++)
199785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk        {
200785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          if (*p == '\n')
201785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk            break;
202785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          if (*p != *q)
203785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk            continue;
204785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          if (isspace((int) ((unsigned char) (*(p-1)))) == 0)
205785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk            continue;
206785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          r=p;
207785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          for ( ; ; )
208785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          {
209785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk            if (*q == '\0')
210785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk              return(p);
211785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk            if (*r++ != *q++)
212785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk              break;
213785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          }
214785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk          q=targets[i];
215785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk        }
216785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk      }
217785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk      return((char *) NULL);
218785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    }
21976d045a787b16952e2111c248713e72de2f593dacristy  for (p=color+1; *p != '\0'; p++)
22076d045a787b16952e2111c248713e72de2f593dacristy  {
22176d045a787b16952e2111c248713e72de2f593dacristy    if (*p == '\n')
22276d045a787b16952e2111c248713e72de2f593dacristy      break;
22376d045a787b16952e2111c248713e72de2f593dacristy    if (isspace((int) ((unsigned char) (*(p-1)))) == 0)
22476d045a787b16952e2111c248713e72de2f593dacristy      continue;
22576d045a787b16952e2111c248713e72de2f593dacristy    if (isspace((int) ((unsigned char) (*p))) != 0)
22676d045a787b16952e2111c248713e72de2f593dacristy      continue;
22776d045a787b16952e2111c248713e72de2f593dacristy    for (i=0; i < NumberTargets; i++)
228785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    {
22976d045a787b16952e2111c248713e72de2f593dacristy      if ((*p == *targets[i]) && (*(p+1) == *(targets[i]+1)))
23076d045a787b16952e2111c248713e72de2f593dacristy        return(p);
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
23276d045a787b16952e2111c248713e72de2f593dacristy  }
23376d045a787b16952e2111c248713e72de2f593dacristy  return(p);
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception)
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
239785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    *grey,
240151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    key[MagickPathExtent],
241151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    target[MagickPathExtent],
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *xpm_buffer;
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    active,
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
252785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    *next,
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
254785a7231a4419ac9e5853e72bb2bb839cad8b2efdirk    *q;
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
256bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2594c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *r;
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length;
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SplayTreeInfo
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *xpm_colors;
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ssize_t
269c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    count,
270c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    j,
271c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    y;
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
273d8af19d72fd93dfd2e42eb0b266cac384a6ae833cristy  unsigned long
274f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    colors,
275f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    columns,
276f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    rows,
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width;
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image file.
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
283e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
288e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
2899950d57e1124b73f684fb5946e206994cefda628cristy  image=AcquireImage(image_info,exception);
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Read XPM file.
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
299151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  length=MagickPathExtent;
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  xpm_buffer=(char *) AcquireQuantumMemory((size_t) length,sizeof(*xpm_buffer));
301dd12db54df58041276651900743c280114886406cristy  if (xpm_buffer == (char *) NULL)
302dd12db54df58041276651900743c280114886406cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
303dd12db54df58041276651900743c280114886406cristy  *xpm_buffer='\0';
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=xpm_buffer;
305dd12db54df58041276651900743c280114886406cristy  while (ReadBlobString(image,p) != (char *) NULL)
306dd12db54df58041276651900743c280114886406cristy  {
307dd12db54df58041276651900743c280114886406cristy    if ((*p == '#') && ((p == xpm_buffer) || (*(p-1) == '\n')))
308dd12db54df58041276651900743c280114886406cristy      continue;
309dd12db54df58041276651900743c280114886406cristy    if ((*p == '}') && (*(p+1) == ';'))
310dd12db54df58041276651900743c280114886406cristy      break;
311dd12db54df58041276651900743c280114886406cristy    p+=strlen(p);
312151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    if ((size_t) (p-xpm_buffer+MagickPathExtent) < length)
313dd12db54df58041276651900743c280114886406cristy      continue;
314dd12db54df58041276651900743c280114886406cristy    length<<=1;
315151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    xpm_buffer=(char *) ResizeQuantumMemory(xpm_buffer,length+MagickPathExtent,
316dd12db54df58041276651900743c280114886406cristy      sizeof(*xpm_buffer));
317dd12db54df58041276651900743c280114886406cristy    if (xpm_buffer == (char *) NULL)
318dd12db54df58041276651900743c280114886406cristy      break;
319dd12db54df58041276651900743c280114886406cristy    p=xpm_buffer+strlen(xpm_buffer);
320dd12db54df58041276651900743c280114886406cristy  }
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (xpm_buffer == (char *) NULL)
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Remove comments.
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  count=0;
32793b02b797c4127ce2b06dbd3b2d75ecc33fca759dirk  width=0;
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=xpm_buffer; *p != '\0'; p++)
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*p != '"')
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      continue;
332f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    count=(ssize_t) sscanf(p+1,"%lu %lu %lu %lu",&columns,&rows,&colors,&width);
333f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    image->columns=columns;
334f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    image->rows=rows;
335f2faecf9facdbbb14fcba373365f9f691a9658e0cristy    image->colors=colors;
336e6b6ece8afea47c6a48f0e189f8f0296606d40f2cristy    if (count == 4)
337e6b6ece8afea47c6a48f0e189f8f0296606d40f2cristy      break;
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
33976edbbafe01574ee2d6539f9b87e30a3f33ccd51Cristy  if ((count != 4) || (width == 0) || (width > 2) ||
34076edbbafe01574ee2d6539f9b87e30a3f33ccd51Cristy      (image->columns == 0) || (image->rows == 0) ||
34176edbbafe01574ee2d6539f9b87e30a3f33ccd51Cristy      (image->colors == 0) || (image->colors > MaxColormapSize))
34276edbbafe01574ee2d6539f9b87e30a3f33ccd51Cristy    {
34376edbbafe01574ee2d6539f9b87e30a3f33ccd51Cristy      xpm_buffer=DestroyString(xpm_buffer);
34476edbbafe01574ee2d6539f9b87e30a3f33ccd51Cristy      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
34576edbbafe01574ee2d6539f9b87e30a3f33ccd51Cristy    }
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Remove unquoted characters.
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  active=MagickFalse;
350e231b1b5ef66f92a09aae9e734139612fbee8a53Cristy  for (q=xpm_buffer; *p != '\0'; )
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*p++ == '"')
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (active != MagickFalse)
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *q++='\n';
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        active=active != MagickFalse ? MagickFalse : MagickTrue;
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (active != MagickFalse)
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *q++=(*p);
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *q='\0';
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize image structure.
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  xpm_colors=NewSplayTree(CompareXPMColor,RelinquishMagickMemory,
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void *(*)(void *)) NULL);
367018f07f7333b25743d0afff892450cebdb905c1acristy  if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
36812a5ddd446c6f93eb22cd829ce158b756417b677cristy    {
36912a5ddd446c6f93eb22cd829ce158b756417b677cristy      xpm_buffer=DestroyString(xpm_buffer);
37012a5ddd446c6f93eb22cd829ce158b756417b677cristy      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
37112a5ddd446c6f93eb22cd829ce158b756417b677cristy    }
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);
381151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    (void) CopyXPMColor(key,p,MagickMin((size_t) width,MagickPathExtent-1));
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=AddValueToSplayTree(xpm_colors,ConstantString(key),(void *) j);
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Parse color.
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
386151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    (void) CopyMagickString(target,"gray",MagickPathExtent);
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),
396151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy            MagickPathExtent-1));
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
398151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy          (void) CopyMagickString(target,q,MagickPathExtent);
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)
42012a5ddd446c6f93eb22cd829ce158b756417b677cristy    {
42112a5ddd446c6f93eb22cd829ce158b756417b677cristy      xpm_colors=DestroySplayTree(xpm_colors);
42212a5ddd446c6f93eb22cd829ce158b756417b677cristy      xpm_buffer=DestroyString(xpm_buffer);
42312a5ddd446c6f93eb22cd829ce158b756417b677cristy      ThrowReaderException(CorruptImageError,"CorruptImage");
42412a5ddd446c6f93eb22cd829ce158b756417b677cristy    }
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  j=0;
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->ping == MagickFalse)
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Read image pixels.
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
431acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy      status=SetImageExtent(image,image->columns,image->rows,exception);
432acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy      if (status == MagickFalse)
433acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy        return(DestroyImageList(image));
434bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (y=0; y < (ssize_t) image->rows; y++)
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=NextXPMLine(p);
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (p == (char *) NULL)
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        r=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
4404c08aed51c5899665ade97263692328eea4af106cristy        if (r == (Quantum *) NULL)
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
442bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (x=0; x < (ssize_t) image->columns; x++)
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
444151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy          ssize_t count=CopyXPMColor(key,p,MagickMin(width,MagickPathExtent-1));
4455463e2e01503c6cfe10c95ab1cfa3f85ff46de69cristy          if (count != (ssize_t) width)
4465463e2e01503c6cfe10c95ab1cfa3f85ff46de69cristy            break;
447bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          j=(ssize_t) GetValueFromSplayTree(xpm_colors,key);
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (image->storage_class == PseudoClass)
449dd12db54df58041276651900743c280114886406cristy            SetPixelIndex(image,(Quantum) j,r);
45011a06d3f2cac0f17af7963e83bc6e9ebd2a377c0cristy          SetPixelViaPixelInfo(image,image->colormap+j,r);
4515463e2e01503c6cfe10c95ab1cfa3f85ff46de69cristy          p+=count;
452ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy          r+=GetPixelChannels(image);
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
4545463e2e01503c6cfe10c95ab1cfa3f85ff46de69cristy        if (x < (ssize_t) image->columns)
4555463e2e01503c6cfe10c95ab1cfa3f85ff46de69cristy          break;
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (SyncAuthenticPixels(image,exception) == MagickFalse)
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
459bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      if (y < (ssize_t) image->rows)
46012a5ddd446c6f93eb22cd829ce158b756417b677cristy        {
46112a5ddd446c6f93eb22cd829ce158b756417b677cristy          xpm_colors=DestroySplayTree(xpm_colors);
46212a5ddd446c6f93eb22cd829ce158b756417b677cristy          xpm_buffer=DestroyString(xpm_buffer);
46312a5ddd446c6f93eb22cd829ce158b756417b677cristy          ThrowReaderException(CorruptImageError,"NotEnoughPixelData");
46412a5ddd446c6f93eb22cd829ce158b756417b677cristy        }
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
46912a5ddd446c6f93eb22cd829ce158b756417b677cristy  xpm_buffer=DestroyString(xpm_buffer);
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  xpm_colors=DestroySplayTree(xpm_colors);
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r X P M I m a g e                                           %
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterXPMImage() adds attributes for the XPM image format to
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the list of supported formats.  The attributes include the image format
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterXPMImage method is:
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
495bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterXPMImage(void)
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
498bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterXPMImage(void)
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
50306b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("XPM","PICON","Personal Icon");
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadXPMImage;
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WritePICONImage;
50608e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags^=CoderAdjoinFlag;
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
50806b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("XPM","PM","X Windows system pixmap (color)");
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadXPMImage;
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteXPMImage;
51108e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags^=CoderAdjoinFlag;
51208e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags|=CoderStealthFlag;
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
51406b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("XPM","XPM","X Windows system pixmap (color)");
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadXPMImage;
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteXPMImage;
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsXPM;
51808e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags^=CoderAdjoinFlag;
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r X P M I m a g e                                       %
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterXPMImage() removes format registrations made by the
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  XPM module from the list of supported formats.
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterXPMImage method is:
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterXPMImage(void)
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterXPMImage(void)
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PICON");
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("PM");
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("XPM");
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e P I C O N I m a g e                                             %
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
560a60c02075c4071dd1801b41db0b478f68683a6fecristy%  WritePICONImage() writes an image to a file in the Personal Icon format.
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WritePICONImage method is:
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType WritePICONImage(const ImageInfo *image_info,
5653a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%        Image *image,ExceptionInfo *exception)
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5733a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%    o exception: return any errors or warnings in this structure.
5743a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType WritePICONImage(const ImageInfo *image_info,
5773a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  Image *image,ExceptionInfo *exception)
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define ColormapExtent  155
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define GraymapExtent  95
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PiconGeometry  "48x48>"
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static unsigned char
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Colormap[]=
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x06, 0x00, 0x05, 0x00, 0xf4, 0x05,
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x00, 0x00, 0x2f, 0x4f, 0x4f, 0x70, 0x80, 0x90, 0x7e, 0x7e,
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x7e, 0xdc, 0xdc, 0xdc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00,
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xff, 0x1e, 0x90, 0xff, 0x87, 0xce, 0xeb, 0xe6, 0xe6, 0xfa, 0x00, 0xff,
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xff, 0x80, 0x00, 0x80, 0xb2, 0x22, 0x22, 0x2e, 0x8b, 0x57, 0x32, 0xcd,
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x32, 0x00, 0xff, 0x00, 0x98, 0xfb, 0x98, 0xff, 0x00, 0xff, 0xff, 0x00,
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0xff, 0x63, 0x47, 0xff, 0xa5, 0x00, 0xff, 0xd7, 0x00, 0xff, 0xff,
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0xee, 0x82, 0xee, 0xa0, 0x52, 0x2d, 0xcd, 0x85, 0x3f, 0xd2, 0xb4,
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x8c, 0xf5, 0xde, 0xb3, 0xff, 0xfa, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00,
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00,
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x05, 0x18, 0x20, 0x10, 0x08,
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x03, 0x51, 0x18, 0x07, 0x92, 0x28, 0x0b, 0xd3, 0x38, 0x0f, 0x14, 0x49,
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x13, 0x55, 0x59, 0x17, 0x96, 0x69, 0x1b, 0xd7, 0x85, 0x00, 0x3b,
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    },
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Graymap[]=
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x04, 0x00, 0xf3, 0x0f,
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x21, 0x21, 0x21, 0x33, 0x33,
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x33, 0x45, 0x45, 0x45, 0x54, 0x54, 0x54, 0x66, 0x66, 0x66, 0x78, 0x78,
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x78, 0x87, 0x87, 0x87, 0x99, 0x99, 0x99, 0xab, 0xab, 0xab, 0xba, 0xba,
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xba, 0xcc, 0xcc, 0xcc, 0xde, 0xde, 0xde, 0xed, 0xed, 0xed, 0xff, 0xff,
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0xff, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00,
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x0c, 0x10, 0x04, 0x31,
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0x48, 0x31, 0x07, 0x25, 0xb5, 0x58, 0x73, 0x4f, 0x04, 0x00, 0x3b,
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    };
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MaxCixels  92
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const char
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk"
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                         "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
619151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    buffer[MagickPathExtent],
620151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    basename[MagickPathExtent],
621151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    name[MagickPathExtent],
622151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    symbol[MagickPathExtent];
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *affinity_image,
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *picon;
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImageInfo
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *blob_info;
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status,
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    transparent;
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6354c08aed51c5899665ade97263692328eea4af106cristy  PixelInfo
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel;
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  QuantizeInfo
6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *quantize_info;
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RectangleInfo
6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry;
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6444c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
647bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6514c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
654bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel,
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    colors;
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
658c6da28e61bb609d2b2cfdcc7752106c973415edbcristy  ssize_t
659c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    j,
660c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    k,
661c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    y;
662c6da28e61bb609d2b2cfdcc7752106c973415edbcristy
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
667e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
669e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6723a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception != (ExceptionInfo *) NULL);
673e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
6743a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
677af8d391906d11f0a1f2bbf4e2adbc4995c852d33cristy  (void) TransformImageColorspace(image,sRGBColorspace,exception);
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetGeometry(image,&geometry);
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ParseMetaGeometry(PiconGeometry,&geometry.x,&geometry.y,
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    &geometry.width,&geometry.height);
681aa2c16cb5e695053aa78e40f66bc36fbef4b1ed1cristy  picon=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,
6823a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    exception);
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  blob_info=CloneImageInfo(image_info);
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) AcquireUniqueFilename(blob_info->filename);
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((image_info->type != TrueColorType) &&
686f1d8548abecaf5ca89d453fd9fc0cde77d20672bdirk      (SetImageGray(image,exception) != MagickFalse))
6873a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    affinity_image=BlobToImage(blob_info,Graymap,GraymapExtent,exception);
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6893a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    affinity_image=BlobToImage(blob_info,Colormap,ColormapExtent,exception);
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RelinquishUniqueFileResource(blob_info->filename);
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  blob_info=DestroyImageInfo(blob_info);
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((picon == (Image *) NULL) || (affinity_image == (Image *) NULL))
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  quantize_info=AcquireQuantizeInfo(image_info);
695018f07f7333b25743d0afff892450cebdb905c1acristy  status=RemapImage(quantize_info,picon,affinity_image,exception);
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  quantize_info=DestroyQuantizeInfo(quantize_info);
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affinity_image=DestroyImage(affinity_image);
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  transparent=MagickFalse;
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (picon->storage_class == PseudoClass)
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
701018f07f7333b25743d0afff892450cebdb905c1acristy      (void) CompressImageColormap(picon,exception);
70217f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      if (picon->alpha_trait != UndefinedPixelTrait)
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        transparent=MagickTrue;
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Convert DirectClass to PseudoClass picon.
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
71017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      if (picon->alpha_trait != UndefinedPixelTrait)
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Map all the transparent pixels.
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
715bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (y=0; y < (ssize_t) picon->rows; y++)
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception);
718acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy            if (q == (Quantum *) NULL)
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
720bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy            for (x=0; x < (ssize_t) picon->columns; x++)
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7224c08aed51c5899665ade97263692328eea4af106cristy              if (GetPixelAlpha(image,q) == (Quantum) TransparentAlpha)
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                transparent=MagickTrue;
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else
7254c08aed51c5899665ade97263692328eea4af106cristy                SetPixelAlpha(picon,OpaqueAlpha,q);
726ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy              q+=GetPixelChannels(picon);
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (SyncAuthenticPixels(picon,exception) == MagickFalse)
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
732018f07f7333b25743d0afff892450cebdb905c1acristy      (void) SetImageType(picon,PaletteType,exception);
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  colors=picon->colors;
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (transparent != MagickFalse)
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      colors++;
738101ab708b0574518ac5715da4d3915400e9df79acristy      picon->colormap=(PixelInfo *) ResizeQuantumMemory((void **)
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        picon->colormap,(size_t) colors,sizeof(*picon->colormap));
740101ab708b0574518ac5715da4d3915400e9df79acristy      if (picon->colormap == (PixelInfo *) NULL)
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowWriterException(ResourceLimitError,"MemoryAllocationError");
742bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (y=0; y < (ssize_t) picon->rows; y++)
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception);
745acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy        if (q == (Quantum *) NULL)
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
747bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (x=0; x < (ssize_t) picon->columns; x++)
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7494c08aed51c5899665ade97263692328eea4af106cristy          if (GetPixelAlpha(image,q) == (Quantum) TransparentAlpha)
750dd12db54df58041276651900743c280114886406cristy            SetPixelIndex(picon,(Quantum) picon->colors,q);
751ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy          q+=GetPixelChannels(picon);
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (SyncAuthenticPixels(picon,exception) == MagickFalse)
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Compute the character per pixel.
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  characters_per_pixel=1;
761bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels)
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel++;
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    XPM header.
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* XPM */\n");
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GetPathComponent(picon->filename,BasePath,basename);
768151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  (void) FormatLocaleString(buffer,MagickPathExtent,
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "static char *%s[] = {\n",basename);
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n");
772151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  (void) FormatLocaleString(buffer,MagickPathExtent,
773e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    "\"%.20g %.20g %.20g %.20g\",\n",(double) picon->columns,(double)
774e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    picon->rows,(double) colors,(double) characters_per_pixel);
7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
7764c08aed51c5899665ade97263692328eea4af106cristy  GetPixelInfo(image,&pixel);
777bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) colors; i++)
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Define XPM color.
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
7829d8c8ce096b3b8b2b1df1aec061f17eabba22b1dcristy    pixel=picon->colormap[i];
7837020ae6594690c03a4f73784fd41a7131a5b22c6cristy    pixel.colorspace=sRGBColorspace;
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel.depth=8;
785a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy    pixel.alpha=(double) OpaqueAlpha;
786269c9413034627692b2a7d0a352f9dee4e8eada8cristy    (void) QueryColorname(image,&pixel,XPMCompliance,name,exception);
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (transparent != MagickFalse)
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
789bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        if (i == (ssize_t) (colors-1))
790151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy          (void) CopyMagickString(name,"grey75",MagickPathExtent);
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Write XPM color.
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    k=i % MaxCixels;
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[0]=Cixel[k];
797bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (j=1; j < (ssize_t) characters_per_pixel; j++)
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      k=((i-k)/MaxCixels) % MaxCixels;
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]=Cixel[k];
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[j]='\0';
803151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    (void) FormatLocaleString(buffer,MagickPathExtent,"\"%s c %s\",\n",
804e6b6ece8afea47c6a48f0e189f8f0296606d40f2cristy       symbol,name);
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Define XPM pixels.
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* pixels */\n");
811bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) picon->rows; y++)
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
8133a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    p=GetVirtualPixels(picon,0,y,picon->columns,1,exception);
8144c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,"\"");
817bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) picon->columns; x++)
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8194c08aed51c5899665ade97263692328eea4af106cristy      k=((ssize_t) GetPixelIndex(picon,p) % MaxCixels);
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[0]=Cixel[k];
821bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (j=1; j < (ssize_t) characters_per_pixel; j++)
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8234c08aed51c5899665ade97263692328eea4af106cristy        k=(((int) GetPixelIndex(picon,p)-k)/MaxCixels) % MaxCixels;
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        symbol[j]=Cixel[k];
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]='\0';
827151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy      (void) CopyMagickString(buffer,symbol,MagickPathExtent);
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobString(image,buffer);
829ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
831151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    (void) FormatLocaleString(buffer,MagickPathExtent,"\"%s\n",
832bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      y == (ssize_t) (picon->rows-1) ? "" : ",");
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
8344cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
8354cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy      picon->rows);
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  picon=DestroyImage(picon);
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"};\n");
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e X P M I m a g e                                                 %
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
856a60c02075c4071dd1801b41db0b478f68683a6fecristy%  WriteXPMImage() writes an image to a file in the X pixmap format.
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WriteXPMImage method is:
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8603a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%      MagickBooleanType WriteXPMImage(const ImageInfo *image_info,
8613a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%        Image *image,ExceptionInfo *exception)
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8693a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%    o exception: return any errors or warnings in this structure.
8703a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy%
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8723a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristystatic MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image,
8733a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  ExceptionInfo *exception)
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define MaxCixels  92
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const char
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk"
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                         "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
882151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    buffer[MagickPathExtent],
883151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    basename[MagickPathExtent],
884151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    name[MagickPathExtent],
885151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    symbol[MagickPathExtent];
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8904c08aed51c5899665ade97263692328eea4af106cristy  PixelInfo
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel;
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8934c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
896bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i,
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
900bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel;
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
903c6da28e61bb609d2b2cfdcc7752106c973415edbcristy  ssize_t
904c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    j,
905c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    k,
906c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    opacity,
907c6da28e61bb609d2b2cfdcc7752106c973415edbcristy    y;
908c6da28e61bb609d2b2cfdcc7752106c973415edbcristy
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
913e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
915e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
9183a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception != (ExceptionInfo *) NULL);
919e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
9203a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
9233d9f5ba107b160e1819bb6baeeb3a9f521e9f450cristy  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
9248d95109eca7aee289423a1ee81c232e309b383aecristy    (void) TransformImageColorspace(image,sRGBColorspace,exception);
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  opacity=(-1);
92617f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy  if (image->alpha_trait == UndefinedPixelTrait)
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((image->storage_class == DirectClass) || (image->colors > 256))
929018f07f7333b25743d0afff892450cebdb905c1acristy        (void) SetImageType(image,PaletteType,exception);
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
933a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      double
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha,
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        beta;
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Identify transparent colormap index.
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((image->storage_class == DirectClass) || (image->colors > 256))
941def23e5d7331b1a13ed593b6d6aca516da382328cristy        (void) SetImageType(image,PaletteBilevelAlphaType,exception);
942bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (i=0; i < (ssize_t) image->colors; i++)
9434c08aed51c5899665ade97263692328eea4af106cristy        if (image->colormap[i].alpha != OpaqueAlpha)
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (opacity < 0)
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                opacity=i;
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                continue;
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
950a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy            alpha=(double) TransparentAlpha-(double)
9514c08aed51c5899665ade97263692328eea4af106cristy              image->colormap[i].alpha;
952a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy            beta=(double) TransparentAlpha-(double)
9534c08aed51c5899665ade97263692328eea4af106cristy              image->colormap[opacity].alpha;
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (alpha < beta)
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              opacity=i;
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (opacity == -1)
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
959def23e5d7331b1a13ed593b6d6aca516da382328cristy          (void) SetImageType(image,PaletteBilevelAlphaType,exception);
960bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (i=0; i < (ssize_t) image->colors; i++)
9614c08aed51c5899665ade97263692328eea4af106cristy            if (image->colormap[i].alpha != OpaqueAlpha)
9623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
9633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (opacity < 0)
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  {
9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    opacity=i;
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    continue;
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  }
968a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy                alpha=(Quantum) TransparentAlpha-(double)
9694c08aed51c5899665ade97263692328eea4af106cristy                  image->colormap[i].alpha;
970a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy                beta=(Quantum) TransparentAlpha-(double)
9714c08aed51c5899665ade97263692328eea4af106cristy                  image->colormap[opacity].alpha;
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                if (alpha < beta)
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  opacity=i;
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (opacity >= 0)
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colormap[opacity].red=image->transparent_color.red;
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colormap[opacity].green=image->transparent_color.green;
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->colormap[opacity].blue=image->transparent_color.blue;
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Compute the character per pixel.
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  characters_per_pixel=1;
987bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (k=MaxCixels; (ssize_t) image->colors > k; k*=MaxCixels)
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    characters_per_pixel++;
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    XPM header.
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* XPM */\n");
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GetPathComponent(image->filename,BasePath,basename);
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (isalnum((int) ((unsigned char) *basename)) == 0)
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
996151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy      (void) FormatLocaleString(buffer,MagickPathExtent,"xpm_%s",basename);
997151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy      (void) CopyMagickString(basename,buffer,MagickPathExtent);
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9992f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy  if (isalpha((int) ((unsigned char) basename[0])) == 0)
10002f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy    basename[0]='_';
10012f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy  for (i=1; basename[i] != '\0'; i++)
10022f4741f1afab21ed9cdbf40a20d3f6e8e00a0b69cristy    if (isalnum((int) ((unsigned char) basename[i])) == 0)
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      basename[i]='_';
1004151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  (void) FormatLocaleString(buffer,MagickPathExtent,
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "static char *%s[] = {\n",basename);
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n");
1008151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  (void) FormatLocaleString(buffer,MagickPathExtent,
1009e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    "\"%.20g %.20g %.20g %.20g \",\n",(double) image->columns,(double)
1010e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    image->rows,(double) image->colors,(double) characters_per_pixel);
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,buffer);
10124c08aed51c5899665ade97263692328eea4af106cristy  GetPixelInfo(image,&pixel);
1013bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) image->colors; i++)
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Define XPM color.
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
10189d8c8ce096b3b8b2b1df1aec061f17eabba22b1dcristy    pixel=image->colormap[i];
10197020ae6594690c03a4f73784fd41a7131a5b22c6cristy    pixel.colorspace=sRGBColorspace;
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel.depth=8;
1021a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy    pixel.alpha=(double) OpaqueAlpha;
1022269c9413034627692b2a7d0a352f9dee4e8eada8cristy    (void) QueryColorname(image,&pixel,XPMCompliance,name,exception);
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (i == opacity)
1024151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy      (void) CopyMagickString(name,"None",MagickPathExtent);
10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Write XPM color.
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    k=i % MaxCixels;
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[0]=Cixel[k];
1030bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (j=1; j < (ssize_t) characters_per_pixel; j++)
10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      k=((i-k)/MaxCixels) % MaxCixels;
10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]=Cixel[k];
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    symbol[j]='\0';
1036151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    (void) FormatLocaleString(buffer,MagickPathExtent,"\"%s c %s\",\n",symbol,
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      name);
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Define XPM pixels.
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"/* pixels */\n");
1044bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
10463a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
10474c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,"\"");
1050bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10524c08aed51c5899665ade97263692328eea4af106cristy      k=((ssize_t) GetPixelIndex(image,p) % MaxCixels);
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[0]=Cixel[k];
1054bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (j=1; j < (ssize_t) characters_per_pixel; j++)
10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
10564c08aed51c5899665ade97263692328eea4af106cristy        k=(((int) GetPixelIndex(image,p)-k)/MaxCixels) % MaxCixels;
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        symbol[j]=Cixel[k];
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      symbol[j]='\0';
1060151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy      (void) CopyMagickString(buffer,symbol,MagickPathExtent);
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) WriteBlobString(image,buffer);
1062ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1064151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    (void) FormatLocaleString(buffer,MagickPathExtent,"\"%s\n",
1065bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      (y == (ssize_t) (image->rows-1) ? "" : ","));
10663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) WriteBlobString(image,buffer);
10678b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy    if (image->previous == (Image *) NULL)
10688b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy      {
10694cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy        status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
10704cb162a81b4dfaf673e94c9dea88ad0a92f0a3d7cristy          image->rows);
10718b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy        if (status == MagickFalse)
10728b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy          break;
10738b27a6dc4e1e93c0583226a4351c00af1829b5bdcristy      }
10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) WriteBlobString(image,"};\n");
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1079