msl.c revision 9dc4c51125c7242f63ea032e209ea65fe855f82f
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                             M   M  SSSSS  L                                 %
7%                             MM MM  SS     L                                 %
8%                             M M M   SSS   L                                 %
9%                             M   M     SS  L                                 %
10%                             M   M  SSSSS  LLLLL                             %
11%                                                                             %
12%                                                                             %
13%                    Execute Magick Scripting Language Scripts.               %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                             Leonard Rosenthol                               %
18%                             William Radcliffe                               %
19%                               December 2001                                 %
20%                                                                             %
21%                                                                             %
22%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
23%  dedicated to making software imaging solutions freely available.           %
24%                                                                             %
25%  You may not use this file except in compliance with the License.  You may  %
26%  obtain a copy of the License at                                            %
27%                                                                             %
28%    http://www.imagemagick.org/script/license.php                            %
29%                                                                             %
30%  Unless required by applicable law or agreed to in writing, software        %
31%  distributed under the License is distributed on an "AS IS" BASIS,          %
32%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
33%  See the License for the specific language governing permissions and        %
34%  limitations under the License.                                             %
35%                                                                             %
36%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37%
38%
39*/
40
41/*
42  Include declarations.
43*/
44#include "MagickCore/studio.h"
45#include "MagickCore/annotate.h"
46#include "MagickCore/artifact.h"
47#include "MagickCore/attribute.h"
48#include "MagickCore/blob.h"
49#include "MagickCore/blob-private.h"
50#include "MagickCore/cache.h"
51#include "MagickCore/cache-view.h"
52#include "MagickCore/color.h"
53#include "MagickCore/color-private.h"
54#include "MagickCore/colormap.h"
55#include "MagickCore/composite.h"
56#include "MagickCore/constitute.h"
57#include "MagickCore/decorate.h"
58#include "MagickCore/display.h"
59#include "MagickCore/distort.h"
60#include "MagickCore/draw.h"
61#include "MagickCore/effect.h"
62#include "MagickCore/enhance.h"
63#include "MagickCore/exception.h"
64#include "MagickCore/exception-private.h"
65#include "MagickCore/fx.h"
66#include "MagickCore/geometry.h"
67#include "MagickCore/image.h"
68#include "MagickCore/image-private.h"
69#include "MagickCore/list.h"
70#include "MagickCore/log.h"
71#include "MagickCore/magick.h"
72#include "MagickCore/memory_.h"
73#include "MagickCore/module.h"
74#include "MagickCore/option.h"
75#include "MagickCore/paint.h"
76#include "MagickCore/pixel-accessor.h"
77#include "MagickCore/profile.h"
78#include "MagickCore/property.h"
79#include "MagickCore/quantize.h"
80#include "MagickCore/quantum-private.h"
81#include "MagickCore/registry.h"
82#include "MagickCore/resize.h"
83#include "MagickCore/resource_.h"
84#include "MagickCore/segment.h"
85#include "MagickCore/shear.h"
86#include "MagickCore/signature.h"
87#include "MagickCore/statistic.h"
88#include "MagickCore/static.h"
89#include "MagickCore/string_.h"
90#include "MagickCore/string-private.h"
91#include "MagickCore/transform.h"
92#include "MagickCore/threshold.h"
93#include "MagickCore/utility.h"
94#if defined(MAGICKCORE_XML_DELEGATE)
95#  if defined(MAGICKCORE_WINDOWS_SUPPORT)
96#    if defined(__MINGW32__) || defined(__MINGW64__)
97#      define _MSC_VER
98#    else
99#      include <win32config.h>
100#    endif
101#  endif
102#  include <libxml/parser.h>
103#  include <libxml/xmlmemory.h>
104#  include <libxml/parserInternals.h>
105#  include <libxml/xmlerror.h>
106#endif
107
108/*
109  Define Declatations.
110*/
111#define ThrowMSLException(severity,tag,reason) \
112  (void) ThrowMagickException(msl_info->exception,GetMagickModule(),severity, \
113    tag,"`%s'",reason);
114
115/*
116  Typedef declaractions.
117*/
118typedef struct _MSLGroupInfo
119{
120  size_t
121    numImages;  /* how many images are in this group */
122} MSLGroupInfo;
123
124typedef struct _MSLInfo
125{
126  ExceptionInfo
127    *exception;
128
129  ssize_t
130    n,
131    number_groups;
132
133  ImageInfo
134    **image_info;
135
136  DrawInfo
137   **draw_info;
138
139  Image
140    **attributes,
141    **image;
142
143  char
144    *content;
145
146  MSLGroupInfo
147    *group_info;
148
149#if defined(MAGICKCORE_XML_DELEGATE)
150  xmlParserCtxtPtr
151    parser;
152
153  xmlDocPtr
154    document;
155#endif
156} MSLInfo;
157
158/*
159  Forward declarations.
160*/
161#if defined(MAGICKCORE_XML_DELEGATE)
162static MagickBooleanType
163  WriteMSLImage(const ImageInfo *,Image *,ExceptionInfo *);
164
165static MagickBooleanType
166  SetMSLAttributes(MSLInfo *,const char *,const char *);
167#endif
168
169#if defined(MAGICKCORE_XML_DELEGATE)
170
171/*
172%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173%                                                                             %
174%                                                                             %
175%                                                                             %
176%   R e a d M S L I m a g e                                                   %
177%                                                                             %
178%                                                                             %
179%                                                                             %
180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181%
182%  ReadMSLImage() reads a Magick Scripting Language file and returns it.
183%  It allocates the memory necessary for the new Image structure and returns a
184%  pointer to the new image.
185%
186%  The format of the ReadMSLImage method is:
187%
188%      Image *ReadMSLImage(const ImageInfo *image_info,ExceptionInfo *exception)
189%
190%  A description of each parameter follows:
191%
192%    o image_info: the image info.
193%
194%    o exception: return any errors or warnings in this structure.
195%
196*/
197
198#if defined(__cplusplus) || defined(c_plusplus)
199extern "C" {
200#endif
201
202static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
203  ExceptionInfo *exception)
204{
205  char
206    key[MaxTextExtent];
207
208  ExceptionInfo
209    *sans_exception;
210
211  Image
212    *image;
213
214  ImageInfo
215    *read_info;
216
217  (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
218  sans_exception=AcquireExceptionInfo();
219  image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
220  sans_exception=DestroyExceptionInfo(sans_exception);
221  if (image != (Image *) NULL)
222    return(image);
223  read_info=CloneImageInfo(image_info);
224  (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
225  image=ReadImage(read_info,exception);
226  read_info=DestroyImageInfo(read_info);
227  if (image != (Image *) NULL)
228    (void) SetImageRegistry(ImageRegistryType,key,image,exception);
229  return(image);
230}
231
232static int IsPathDirectory(const char *path)
233{
234  MagickBooleanType
235    status;
236
237  struct stat
238    attributes;
239
240  if ((path == (const char *) NULL) || (*path == '\0'))
241    return(MagickFalse);
242  status=GetPathAttributes(path,&attributes);
243  if (status == MagickFalse)
244    return(-1);
245  if (S_ISDIR(attributes.st_mode) == 0)
246    return(0);
247  return(1);
248}
249
250static int MSLIsStandalone(void *context)
251{
252  MSLInfo
253    *msl_info;
254
255  /*
256    Is this document tagged standalone?
257  */
258  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  SAX.MSLIsStandalone()");
259  msl_info=(MSLInfo *) context;
260  return(msl_info->document->standalone == 1);
261}
262
263static int MSLHasInternalSubset(void *context)
264{
265  MSLInfo
266    *msl_info;
267
268  /*
269    Does this document has an internal subset?
270  */
271  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
272    "  SAX.MSLHasInternalSubset()");
273  msl_info=(MSLInfo *) context;
274  return(msl_info->document->intSubset != NULL);
275}
276
277static int MSLHasExternalSubset(void *context)
278{
279  MSLInfo
280    *msl_info;
281
282  /*
283    Does this document has an external subset?
284  */
285  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
286    "  SAX.MSLHasExternalSubset()");
287  msl_info=(MSLInfo *) context;
288  return(msl_info->document->extSubset != NULL);
289}
290
291static void MSLInternalSubset(void *context,const xmlChar *name,
292  const xmlChar *external_id,const xmlChar *system_id)
293{
294  MSLInfo
295    *msl_info;
296
297  /*
298    Does this document has an internal subset?
299  */
300  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
301    "  SAX.internalSubset(%s %s %s)",name,
302    (external_id != (const xmlChar *) NULL ? (const char *) external_id : " "),
303    (system_id != (const xmlChar *) NULL ? (const char *) system_id : " "));
304  msl_info=(MSLInfo *) context;
305  (void) xmlCreateIntSubset(msl_info->document,name,external_id,system_id);
306}
307
308static xmlParserInputPtr MSLResolveEntity(void *context,
309  const xmlChar *public_id,const xmlChar *system_id)
310{
311  MSLInfo
312    *msl_info;
313
314  xmlParserInputPtr
315    stream;
316
317  /*
318    Special entity resolver, better left to the parser, it has more
319    context than the application layer.  The default behaviour is to
320    not resolve the entities, in that case the ENTITY_REF nodes are
321    built in the structure (and the parameter values).
322  */
323  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
324    "  SAX.resolveEntity(%s, %s)",
325    (public_id != (const xmlChar *) NULL ? (const char *) public_id : "none"),
326    (system_id != (const xmlChar *) NULL ? (const char *) system_id : "none"));
327  msl_info=(MSLInfo *) context;
328  stream=xmlLoadExternalEntity((const char *) system_id,(const char *)
329    public_id,msl_info->parser);
330  return(stream);
331}
332
333static xmlEntityPtr MSLGetEntity(void *context,const xmlChar *name)
334{
335  MSLInfo
336    *msl_info;
337
338  /*
339    Get an entity by name.
340  */
341  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
342    "  SAX.MSLGetEntity(%s)",(const char *) name);
343  msl_info=(MSLInfo *) context;
344  return(xmlGetDocEntity(msl_info->document,name));
345}
346
347static xmlEntityPtr MSLGetParameterEntity(void *context,const xmlChar *name)
348{
349  MSLInfo
350    *msl_info;
351
352  /*
353    Get a parameter entity by name.
354  */
355  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
356    "  SAX.getParameterEntity(%s)",(const char *) name);
357  msl_info=(MSLInfo *) context;
358  return(xmlGetParameterEntity(msl_info->document,name));
359}
360
361static void MSLEntityDeclaration(void *context,const xmlChar *name,int type,
362  const xmlChar *public_id,const xmlChar *system_id,xmlChar *content)
363{
364  MSLInfo
365    *msl_info;
366
367  /*
368    An entity definition has been parsed.
369  */
370  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
371    "  SAX.entityDecl(%s, %d, %s, %s, %s)",name,type,
372    public_id != (const xmlChar *) NULL ? (const char *) public_id : "none",
373    system_id != (const xmlChar *) NULL ? (const char *) system_id : "none",
374    content);
375  msl_info=(MSLInfo *) context;
376  if (msl_info->parser->inSubset == 1)
377    (void) xmlAddDocEntity(msl_info->document,name,type,public_id,system_id,
378      content);
379  else
380    if (msl_info->parser->inSubset == 2)
381      (void) xmlAddDtdEntity(msl_info->document,name,type,public_id,system_id,
382        content);
383}
384
385static void MSLAttributeDeclaration(void *context,const xmlChar *element,
386  const xmlChar *name,int type,int value,const xmlChar *default_value,
387  xmlEnumerationPtr tree)
388{
389  MSLInfo
390    *msl_info;
391
392  xmlChar
393    *fullname,
394    *prefix;
395
396  xmlParserCtxtPtr
397    parser;
398
399  /*
400    An attribute definition has been parsed.
401  */
402  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
403    "  SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",element,name,type,value,
404    default_value);
405  msl_info=(MSLInfo *) context;
406  fullname=(xmlChar *) NULL;
407  prefix=(xmlChar *) NULL;
408  parser=msl_info->parser;
409  fullname=(xmlChar *) xmlSplitQName(parser,name,&prefix);
410  if (parser->inSubset == 1)
411    (void) xmlAddAttributeDecl(&parser->vctxt,msl_info->document->intSubset,
412      element,fullname,prefix,(xmlAttributeType) type,
413      (xmlAttributeDefault) value,default_value,tree);
414  else
415    if (parser->inSubset == 2)
416      (void) xmlAddAttributeDecl(&parser->vctxt,msl_info->document->extSubset,
417        element,fullname,prefix,(xmlAttributeType) type,
418        (xmlAttributeDefault) value,default_value,tree);
419  if (prefix != (xmlChar *) NULL)
420    xmlFree(prefix);
421  if (fullname != (xmlChar *) NULL)
422    xmlFree(fullname);
423}
424
425static void MSLElementDeclaration(void *context,const xmlChar *name,int type,
426  xmlElementContentPtr content)
427{
428  MSLInfo
429    *msl_info;
430
431  xmlParserCtxtPtr
432    parser;
433
434  /*
435    An element definition has been parsed.
436  */
437  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
438    "  SAX.elementDecl(%s, %d, ...)",name,type);
439  msl_info=(MSLInfo *) context;
440  parser=msl_info->parser;
441  if (parser->inSubset == 1)
442    (void) xmlAddElementDecl(&parser->vctxt,msl_info->document->intSubset,
443      name,(xmlElementTypeVal) type,content);
444  else
445    if (parser->inSubset == 2)
446      (void) xmlAddElementDecl(&parser->vctxt,msl_info->document->extSubset,
447        name,(xmlElementTypeVal) type,content);
448}
449
450static void MSLNotationDeclaration(void *context,const xmlChar *name,
451  const xmlChar *public_id,const xmlChar *system_id)
452{
453  MSLInfo
454    *msl_info;
455
456  xmlParserCtxtPtr
457    parser;
458
459  /*
460    What to do when a notation declaration has been parsed.
461  */
462  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
463    "  SAX.notationDecl(%s, %s, %s)",name,
464    public_id != (const xmlChar *) NULL ? (const char *) public_id : "none",
465    system_id != (const xmlChar *) NULL ? (const char *) system_id : "none");
466  msl_info=(MSLInfo *) context;
467  parser=msl_info->parser;
468  if (parser->inSubset == 1)
469    (void) xmlAddNotationDecl(&parser->vctxt,msl_info->document->intSubset,
470      name,public_id,system_id);
471  else
472    if (parser->inSubset == 2)
473      (void) xmlAddNotationDecl(&parser->vctxt,msl_info->document->intSubset,
474        name,public_id,system_id);
475}
476
477static void MSLUnparsedEntityDeclaration(void *context,const xmlChar *name,
478  const xmlChar *public_id,const xmlChar *system_id,const xmlChar *notation)
479{
480  MSLInfo
481    *msl_info;
482
483  /*
484    What to do when an unparsed entity declaration is parsed.
485  */
486  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
487    "  SAX.unparsedEntityDecl(%s, %s, %s, %s)",name,
488    public_id != (const xmlChar *) NULL ? (const char *) public_id : "none",
489    system_id != (const xmlChar *) NULL ? (const char *) system_id : "none",
490    notation);
491  msl_info=(MSLInfo *) context;
492  (void) xmlAddDocEntity(msl_info->document,name,
493    XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,public_id,system_id,notation);
494
495}
496
497static void MSLSetDocumentLocator(void *context,xmlSAXLocatorPtr location)
498{
499  MSLInfo
500    *msl_info;
501
502  /*
503    Receive the document locator at startup, actually xmlDefaultSAXLocator.
504  */
505  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
506    "  SAX.setDocumentLocator()\n");
507  (void) location;
508  msl_info=(MSLInfo *) context;
509  (void) msl_info;
510}
511
512static void MSLStartDocument(void *context)
513{
514  MSLInfo
515    *msl_info;
516
517  xmlParserCtxtPtr
518    parser;
519
520  /*
521    Called when the document start being processed.
522  */
523  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
524    "  SAX.startDocument()");
525  msl_info=(MSLInfo *) context;
526  parser=msl_info->parser;
527  msl_info->document=xmlNewDoc(parser->version);
528  if (msl_info->document == (xmlDocPtr) NULL)
529    return;
530  if (parser->encoding == NULL)
531    msl_info->document->encoding=NULL;
532  else
533    msl_info->document->encoding=xmlStrdup(parser->encoding);
534  msl_info->document->standalone=parser->standalone;
535}
536
537static void MSLEndDocument(void *context)
538{
539  MSLInfo
540    *msl_info;
541
542  /*
543    Called when the document end has been detected.
544  */
545  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  SAX.endDocument()");
546  msl_info=(MSLInfo *) context;
547  if (msl_info->content != (char *) NULL)
548    msl_info->content=DestroyString(msl_info->content);
549}
550
551static void MSLPushImage(MSLInfo *msl_info,Image *image)
552{
553  ssize_t
554    n;
555
556  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
557  assert(msl_info != (MSLInfo *) NULL);
558  msl_info->n++;
559  n=msl_info->n;
560  msl_info->image_info=(ImageInfo **) ResizeQuantumMemory(msl_info->image_info,
561    (n+1),sizeof(*msl_info->image_info));
562  msl_info->draw_info=(DrawInfo **) ResizeQuantumMemory(msl_info->draw_info,
563    (n+1),sizeof(*msl_info->draw_info));
564  msl_info->attributes=(Image **) ResizeQuantumMemory(msl_info->attributes,
565    (n+1),sizeof(*msl_info->attributes));
566  msl_info->image=(Image **) ResizeQuantumMemory(msl_info->image,(n+1),
567    sizeof(*msl_info->image));
568  if ((msl_info->image_info == (ImageInfo **) NULL) ||
569    (msl_info->draw_info == (DrawInfo **) NULL) ||
570    (msl_info->attributes == (Image **) NULL) ||
571    (msl_info->image == (Image **) NULL))
572      ThrowMSLException(ResourceLimitFatalError,"MemoryAllocationFailed","msl");
573  msl_info->image_info[n]=CloneImageInfo(msl_info->image_info[n-1]);
574  msl_info->draw_info[n]=CloneDrawInfo(msl_info->image_info[n-1],
575    msl_info->draw_info[n-1]);
576  if (image == (Image *) NULL)
577    msl_info->attributes[n]=AcquireImage(msl_info->image_info[n],
578      msl_info->exception);
579  else
580    msl_info->attributes[n]=CloneImage(image,0,0,MagickTrue,
581      msl_info->exception);
582  msl_info->image[n]=(Image *) image;
583  if ((msl_info->image_info[n] == (ImageInfo *) NULL) ||
584    (msl_info->attributes[n] == (Image *) NULL))
585    ThrowMSLException(ResourceLimitFatalError,"MemoryAllocationFailed","msl");
586  if (msl_info->number_groups != 0)
587    msl_info->group_info[msl_info->number_groups-1].numImages++;
588}
589
590static void MSLPopImage(MSLInfo *msl_info)
591{
592  if (msl_info->number_groups != 0)
593    return;
594  if (msl_info->image[msl_info->n] != (Image *) NULL)
595    msl_info->image[msl_info->n]=DestroyImage(msl_info->image[msl_info->n]);
596  msl_info->attributes[msl_info->n]=DestroyImage(
597    msl_info->attributes[msl_info->n]);
598  msl_info->image_info[msl_info->n]=DestroyImageInfo(
599    msl_info->image_info[msl_info->n]);
600  msl_info->n--;
601}
602
603static void MSLStartElement(void *context,const xmlChar *tag,
604  const xmlChar **attributes)
605{
606  AffineMatrix
607    affine,
608    current;
609
610  ChannelType
611    channel;
612
613  ChannelType
614    channel_mask;
615
616  char
617    key[MaxTextExtent],
618    *value;
619
620  const char
621    *attribute,
622    *keyword;
623
624  double
625    angle;
626
627  DrawInfo
628    *draw_info;
629
630  ExceptionInfo
631    exception;
632
633  GeometryInfo
634    geometry_info;
635
636  Image
637    *image;
638
639  int
640    flags;
641
642  ssize_t
643    option,
644    j,
645    n,
646    x,
647    y;
648
649  MSLInfo
650    *msl_info;
651
652  RectangleInfo
653    geometry;
654
655  register ssize_t
656    i;
657
658  size_t
659    height,
660    width;
661
662  /*
663    Called when an opening tag has been processed.
664  */
665  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
666    "  SAX.startElement(%s",tag);
667  GetExceptionInfo(&exception);
668  msl_info=(MSLInfo *) context;
669  n=msl_info->n;
670  keyword=(const char *) NULL;
671  value=(char *) NULL;
672  SetGeometryInfo(&geometry_info);
673  channel=DefaultChannels;
674  switch (*tag)
675  {
676    case 'A':
677    case 'a':
678    {
679      if (LocaleCompare((const char *) tag,"add-noise") == 0)
680        {
681          Image
682            *noise_image;
683
684          NoiseType
685            noise;
686
687          /*
688            Add noise image.
689          */
690          if (msl_info->image[n] == (Image *) NULL)
691            {
692              ThrowMSLException(OptionError,"NoImagesDefined",
693                (const char *) tag);
694              break;
695            }
696          noise=UniformNoise;
697          if (attributes != (const xmlChar **) NULL)
698            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
699            {
700              keyword=(const char *) attributes[i++];
701              attribute=InterpretImageProperties(msl_info->image_info[n],
702                msl_info->attributes[n],(const char *) attributes[i],
703                &exception);
704              CloneString(&value,attribute);
705              switch (*keyword)
706              {
707                case 'C':
708                case 'c':
709                {
710                  if (LocaleCompare(keyword,"channel") == 0)
711                    {
712                      option=ParseChannelOption(value);
713                      if (option < 0)
714                        ThrowMSLException(OptionError,"UnrecognizedChannelType",
715                          value);
716                      channel=(ChannelType) option;
717                      break;
718                    }
719                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
720                    keyword);
721                  break;
722                }
723                case 'N':
724                case 'n':
725                {
726                  if (LocaleCompare(keyword,"noise") == 0)
727                    {
728                      option=ParseCommandOption(MagickNoiseOptions,MagickFalse,
729                        value);
730                      if (option < 0)
731                        ThrowMSLException(OptionError,"UnrecognizedNoiseType",
732                          value);
733                      noise=(NoiseType) option;
734                      break;
735                    }
736                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
737                    keyword);
738                  break;
739                }
740                default:
741                {
742                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
743                    keyword);
744                  break;
745                }
746              }
747            }
748          channel_mask=SetImageChannelMask(msl_info->image[n],channel);
749          noise_image=AddNoiseImage(msl_info->image[n],noise,1.0,
750            msl_info->exception);
751          (void) SetPixelChannelMask(msl_info->image[n],channel_mask);
752          if (noise_image == (Image *) NULL)
753            break;
754          msl_info->image[n]=DestroyImage(msl_info->image[n]);
755          msl_info->image[n]=noise_image;
756          break;
757        }
758      if (LocaleCompare((const char *) tag,"annotate") == 0)
759        {
760          char
761            text[MaxTextExtent];
762
763          /*
764            Annotate image.
765          */
766          if (msl_info->image[n] == (Image *) NULL)
767            {
768              ThrowMSLException(OptionError,"NoImagesDefined",
769                (const char *) tag);
770              break;
771            }
772          draw_info=CloneDrawInfo(msl_info->image_info[n],
773            msl_info->draw_info[n]);
774          angle=0.0;
775          current=draw_info->affine;
776          GetAffineMatrix(&affine);
777          if (attributes != (const xmlChar **) NULL)
778            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
779            {
780              keyword=(const char *) attributes[i++];
781              attribute=InterpretImageProperties(msl_info->image_info[n],
782                msl_info->attributes[n],(const char *) attributes[i],
783                &exception);
784              CloneString(&value,attribute);
785              switch (*keyword)
786              {
787                case 'A':
788                case 'a':
789                {
790                  if (LocaleCompare(keyword,"affine") == 0)
791                    {
792                      char
793                        *p;
794
795                      p=value;
796                      draw_info->affine.sx=StringToDouble(p,&p);
797                      if (*p ==',')
798                        p++;
799                      draw_info->affine.rx=StringToDouble(p,&p);
800                      if (*p ==',')
801                        p++;
802                      draw_info->affine.ry=StringToDouble(p,&p);
803                      if (*p ==',')
804                        p++;
805                      draw_info->affine.sy=StringToDouble(p,&p);
806                      if (*p ==',')
807                        p++;
808                      draw_info->affine.tx=StringToDouble(p,&p);
809                      if (*p ==',')
810                        p++;
811                      draw_info->affine.ty=StringToDouble(p,&p);
812                      break;
813                    }
814                  if (LocaleCompare(keyword,"align") == 0)
815                    {
816                      option=ParseCommandOption(MagickAlignOptions,MagickFalse,
817                        value);
818                      if (option < 0)
819                        ThrowMSLException(OptionError,"UnrecognizedAlignType",
820                          value);
821                      draw_info->align=(AlignType) option;
822                      break;
823                    }
824                  if (LocaleCompare(keyword,"antialias") == 0)
825                    {
826                      option=ParseCommandOption(MagickBooleanOptions,
827                        MagickFalse,value);
828                      if (option < 0)
829                        ThrowMSLException(OptionError,"UnrecognizedBooleanType",
830                          value);
831                      draw_info->stroke_antialias=(MagickBooleanType) option;
832                      draw_info->text_antialias=(MagickBooleanType) option;
833                      break;
834                    }
835                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
836                    keyword);
837                  break;
838                }
839                case 'D':
840                case 'd':
841                {
842                  if (LocaleCompare(keyword,"density") == 0)
843                    {
844                      CloneString(&draw_info->density,value);
845                      break;
846                    }
847                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
848                    keyword);
849                  break;
850                }
851                case 'E':
852                case 'e':
853                {
854                  if (LocaleCompare(keyword,"encoding") == 0)
855                    {
856                      CloneString(&draw_info->encoding,value);
857                      break;
858                    }
859                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
860                    keyword);
861                  break;
862                }
863                case 'F':
864                case 'f':
865                {
866                  if (LocaleCompare(keyword, "fill") == 0)
867                    {
868                      (void) QueryColorCompliance(value,AllCompliance,
869                        &draw_info->fill,&exception);
870                      break;
871                    }
872                  if (LocaleCompare(keyword,"family") == 0)
873                    {
874                      CloneString(&draw_info->family,value);
875                      break;
876                    }
877                  if (LocaleCompare(keyword,"font") == 0)
878                    {
879                      CloneString(&draw_info->font,value);
880                      break;
881                    }
882                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
883                    keyword);
884                  break;
885                }
886                case 'G':
887                case 'g':
888                {
889                  if (LocaleCompare(keyword,"geometry") == 0)
890                    {
891                      flags=ParseGravityGeometry(msl_info->image[n],value,
892                        &geometry,&exception);
893                      break;
894                    }
895                  if (LocaleCompare(keyword,"gravity") == 0)
896                    {
897                      option=ParseCommandOption(MagickGravityOptions,
898                        MagickFalse,value);
899                      if (option < 0)
900                        ThrowMSLException(OptionError,"UnrecognizedGravityType",
901                          value);
902                      draw_info->gravity=(GravityType) option;
903                      break;
904                    }
905                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
906                    keyword);
907                  break;
908                }
909                case 'P':
910                case 'p':
911                {
912                  if (LocaleCompare(keyword,"pointsize") == 0)
913                    {
914                      draw_info->pointsize=StringToDouble(value,(char **) NULL);
915                      break;
916                    }
917                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
918                    keyword);
919                  break;
920                }
921                case 'R':
922                case 'r':
923                {
924                  if (LocaleCompare(keyword,"rotate") == 0)
925                    {
926                      angle=StringToDouble(value,(char **) NULL);
927                      affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
928                      affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
929                      affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
930                      affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
931                      break;
932                    }
933                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
934                    keyword);
935                  break;
936                }
937                case 'S':
938                case 's':
939                {
940                  if (LocaleCompare(keyword,"scale") == 0)
941                    {
942                      flags=ParseGeometry(value,&geometry_info);
943                      if ((flags & SigmaValue) == 0)
944                        geometry_info.sigma=1.0;
945                      affine.sx=geometry_info.rho;
946                      affine.sy=geometry_info.sigma;
947                      break;
948                    }
949                  if (LocaleCompare(keyword,"skewX") == 0)
950                    {
951                      angle=StringToDouble(value,(char **) NULL);
952                      affine.ry=tan(DegreesToRadians(fmod((double) angle,
953                        360.0)));
954                      break;
955                    }
956                  if (LocaleCompare(keyword,"skewY") == 0)
957                    {
958                      angle=StringToDouble(value,(char **) NULL);
959                      affine.rx=tan(DegreesToRadians(fmod((double) angle,
960                        360.0)));
961                      break;
962                    }
963                  if (LocaleCompare(keyword,"stretch") == 0)
964                    {
965                      option=ParseCommandOption(MagickStretchOptions,
966                        MagickFalse,value);
967                      if (option < 0)
968                        ThrowMSLException(OptionError,"UnrecognizedStretchType",
969                          value);
970                      draw_info->stretch=(StretchType) option;
971                      break;
972                    }
973                  if (LocaleCompare(keyword, "stroke") == 0)
974                    {
975                      (void) QueryColorCompliance(value,AllCompliance,
976                        &draw_info->stroke,&exception);
977                      break;
978                    }
979                  if (LocaleCompare(keyword,"strokewidth") == 0)
980                    {
981                      draw_info->stroke_width=StringToLong(value);
982                      break;
983                    }
984                  if (LocaleCompare(keyword,"style") == 0)
985                    {
986                      option=ParseCommandOption(MagickStyleOptions,MagickFalse,
987                        value);
988                      if (option < 0)
989                        ThrowMSLException(OptionError,"UnrecognizedStyleType",
990                          value);
991                      draw_info->style=(StyleType) option;
992                      break;
993                    }
994                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
995                    keyword);
996                  break;
997                }
998                case 'T':
999                case 't':
1000                {
1001                  if (LocaleCompare(keyword,"text") == 0)
1002                    {
1003                      CloneString(&draw_info->text,value);
1004                      break;
1005                    }
1006                  if (LocaleCompare(keyword,"translate") == 0)
1007                    {
1008                      flags=ParseGeometry(value,&geometry_info);
1009                      if ((flags & SigmaValue) == 0)
1010                        geometry_info.sigma=1.0;
1011                      affine.tx=geometry_info.rho;
1012                      affine.ty=geometry_info.sigma;
1013                      break;
1014                    }
1015                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1016                    keyword);
1017                  break;
1018                }
1019                case 'U':
1020                case 'u':
1021                {
1022                  if (LocaleCompare(keyword, "undercolor") == 0)
1023                    {
1024                      (void) QueryColorCompliance(value,AllCompliance,
1025                        &draw_info->undercolor,&exception);
1026                      break;
1027                    }
1028                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1029                    keyword);
1030                  break;
1031                }
1032                case 'W':
1033                case 'w':
1034                {
1035                  if (LocaleCompare(keyword,"weight") == 0)
1036                    {
1037                      draw_info->weight=StringToLong(value);
1038                      break;
1039                    }
1040                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1041                    keyword);
1042                  break;
1043                }
1044                case 'X':
1045                case 'x':
1046                {
1047                  if (LocaleCompare(keyword,"x") == 0)
1048                    {
1049                      geometry.x=StringToLong(value);
1050                      break;
1051                    }
1052                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1053                    keyword);
1054                  break;
1055                }
1056                case 'Y':
1057                case 'y':
1058                {
1059                  if (LocaleCompare(keyword,"y") == 0)
1060                    {
1061                      geometry.y=StringToLong(value);
1062                      break;
1063                    }
1064                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1065                    keyword);
1066                  break;
1067                }
1068                default:
1069                {
1070                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1071                    keyword);
1072                  break;
1073                }
1074              }
1075            }
1076          (void) FormatLocaleString(text,MaxTextExtent,
1077            "%.20gx%.20g%+.20g%+.20g",(double) geometry.width,(double)
1078            geometry.height,(double) geometry.x,(double) geometry.y);
1079          CloneString(&draw_info->geometry,text);
1080          draw_info->affine.sx=affine.sx*current.sx+affine.ry*current.rx;
1081          draw_info->affine.rx=affine.rx*current.sx+affine.sy*current.rx;
1082          draw_info->affine.ry=affine.sx*current.ry+affine.ry*current.sy;
1083          draw_info->affine.sy=affine.rx*current.ry+affine.sy*current.sy;
1084          draw_info->affine.tx=affine.sx*current.tx+affine.ry*current.ty+
1085            affine.tx;
1086          draw_info->affine.ty=affine.rx*current.tx+affine.sy*current.ty+
1087            affine.ty;
1088          (void) AnnotateImage(msl_info->image[n],draw_info,
1089            msl_info->exception);
1090          draw_info=DestroyDrawInfo(draw_info);
1091          break;
1092        }
1093      if (LocaleCompare((const char *) tag,"append") == 0)
1094        {
1095          Image
1096            *append_image;
1097
1098          MagickBooleanType
1099            stack;
1100
1101          if (msl_info->image[n] == (Image *) NULL)
1102            {
1103              ThrowMSLException(OptionError,"NoImagesDefined",
1104                (const char *) tag);
1105              break;
1106            }
1107          stack=MagickFalse;
1108          if (attributes != (const xmlChar **) NULL)
1109            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
1110            {
1111              keyword=(const char *) attributes[i++];
1112              attribute=InterpretImageProperties(msl_info->image_info[n],
1113                msl_info->attributes[n],(const char *) attributes[i],
1114                &exception);
1115              CloneString(&value,attribute);
1116              switch (*keyword)
1117              {
1118                case 'S':
1119                case 's':
1120                {
1121                  if (LocaleCompare(keyword,"stack") == 0)
1122                    {
1123                      option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
1124                        value);
1125                      if (option < 0)
1126                        ThrowMSLException(OptionError,"UnrecognizedBooleanType",
1127                          value);
1128                      stack=(MagickBooleanType) option;
1129                      break;
1130                    }
1131                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1132                    keyword);
1133                  break;
1134                }
1135                default:
1136                {
1137                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1138                    keyword);
1139                  break;
1140                }
1141              }
1142            }
1143          append_image=AppendImages(msl_info->image[n],stack,
1144            msl_info->exception);
1145          if (append_image == (Image *) NULL)
1146            break;
1147          msl_info->image[n]=DestroyImage(msl_info->image[n]);
1148          msl_info->image[n]=append_image;
1149          break;
1150        }
1151      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
1152      break;
1153    }
1154    case 'B':
1155    case 'b':
1156    {
1157      if (LocaleCompare((const char *) tag,"blur") == 0)
1158        {
1159          Image
1160            *blur_image;
1161
1162          /*
1163            Blur image.
1164          */
1165          if (msl_info->image[n] == (Image *) NULL)
1166            {
1167              ThrowMSLException(OptionError,"NoImagesDefined",
1168                (const char *) tag);
1169              break;
1170            }
1171          if (attributes != (const xmlChar **) NULL)
1172            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
1173            {
1174              keyword=(const char *) attributes[i++];
1175              attribute=InterpretImageProperties(msl_info->image_info[n],
1176                msl_info->attributes[n],(const char *) attributes[i],
1177                &exception);
1178              CloneString(&value,attribute);
1179              switch (*keyword)
1180              {
1181                case 'C':
1182                case 'c':
1183                {
1184                  if (LocaleCompare(keyword,"channel") == 0)
1185                    {
1186                      option=ParseChannelOption(value);
1187                      if (option < 0)
1188                        ThrowMSLException(OptionError,"UnrecognizedChannelType",
1189                          value);
1190                      channel=(ChannelType) option;
1191                      break;
1192                    }
1193                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1194                    keyword);
1195                  break;
1196                }
1197                case 'G':
1198                case 'g':
1199                {
1200                  if (LocaleCompare(keyword,"geometry") == 0)
1201                    {
1202                      flags=ParseGeometry(value,&geometry_info);
1203                      if ((flags & SigmaValue) == 0)
1204                        geometry_info.sigma=1.0;
1205                      break;
1206                    }
1207                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1208                    keyword);
1209                  break;
1210                }
1211                case 'R':
1212                case 'r':
1213                {
1214                  if (LocaleCompare(keyword,"radius") == 0)
1215                    {
1216                      geometry_info.rho=StringToDouble(value,(char **) NULL);
1217                      break;
1218                    }
1219                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1220                    keyword);
1221                  break;
1222                }
1223                case 'S':
1224                case 's':
1225                {
1226                  if (LocaleCompare(keyword,"sigma") == 0)
1227                    {
1228                      geometry_info.sigma=StringToLong(value);
1229                      break;
1230                    }
1231                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1232                    keyword);
1233                  break;
1234                }
1235                default:
1236                {
1237                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1238                    keyword);
1239                  break;
1240                }
1241              }
1242            }
1243          channel_mask=SetImageChannelMask(msl_info->image[n],channel);
1244          blur_image=BlurImage(msl_info->image[n],geometry_info.rho,
1245            geometry_info.sigma,msl_info->exception);
1246          (void) SetPixelChannelMask(msl_info->image[n],channel_mask);
1247          if (blur_image == (Image *) NULL)
1248            break;
1249          msl_info->image[n]=DestroyImage(msl_info->image[n]);
1250          msl_info->image[n]=blur_image;
1251          break;
1252        }
1253      if (LocaleCompare((const char *) tag,"border") == 0)
1254        {
1255          Image
1256            *border_image;
1257
1258          /*
1259            Border image.
1260          */
1261          if (msl_info->image[n] == (Image *) NULL)
1262            {
1263              ThrowMSLException(OptionError,"NoImagesDefined",
1264                (const char *) tag);
1265              break;
1266            }
1267          SetGeometry(msl_info->image[n],&geometry);
1268          if (attributes != (const xmlChar **) NULL)
1269            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
1270            {
1271              keyword=(const char *) attributes[i++];
1272              attribute=InterpretImageProperties(msl_info->image_info[n],
1273                msl_info->attributes[n],(const char *) attributes[i],
1274                &exception);
1275              CloneString(&value,attribute);
1276              switch (*keyword)
1277              {
1278                case 'C':
1279                case 'c':
1280                {
1281                  if (LocaleCompare(keyword,"compose") == 0)
1282                    {
1283                      option=ParseCommandOption(MagickComposeOptions,MagickFalse,
1284                        value);
1285                      if (option < 0)
1286                        ThrowMSLException(OptionError,"UnrecognizedComposeType",
1287                          value);
1288                      msl_info->image[n]->compose=(CompositeOperator) option;
1289                      break;
1290                    }
1291                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1292                    keyword);
1293                  break;
1294                }
1295                case 'F':
1296                case 'f':
1297                {
1298                  if (LocaleCompare(keyword, "fill") == 0)
1299                    {
1300                      (void) QueryColorCompliance(value,AllCompliance,
1301                        &msl_info->image[n]->border_color,&exception);
1302                      break;
1303                    }
1304                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1305                    keyword);
1306                  break;
1307                }
1308                case 'G':
1309                case 'g':
1310                {
1311                  if (LocaleCompare(keyword,"geometry") == 0)
1312                    {
1313                      flags=ParsePageGeometry(msl_info->image[n],value,
1314                        &geometry,&exception);
1315                      if ((flags & HeightValue) == 0)
1316                        geometry.height=geometry.width;
1317                      break;
1318                    }
1319                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1320                    keyword);
1321                  break;
1322                }
1323                case 'H':
1324                case 'h':
1325                {
1326                  if (LocaleCompare(keyword,"height") == 0)
1327                    {
1328                      geometry.height=StringToLong(value);
1329                      break;
1330                    }
1331                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1332                    keyword);
1333                  break;
1334                }
1335                case 'W':
1336                case 'w':
1337                {
1338                  if (LocaleCompare(keyword,"width") == 0)
1339                    {
1340                      geometry.width=StringToLong(value);
1341                      break;
1342                    }
1343                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1344                    keyword);
1345                  break;
1346                }
1347                default:
1348                {
1349                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1350                    keyword);
1351                  break;
1352                }
1353              }
1354            }
1355          border_image=BorderImage(msl_info->image[n],&geometry,
1356            msl_info->image[n]->compose,msl_info->exception);
1357          if (border_image == (Image *) NULL)
1358            break;
1359          msl_info->image[n]=DestroyImage(msl_info->image[n]);
1360          msl_info->image[n]=border_image;
1361          break;
1362        }
1363      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
1364    }
1365    case 'C':
1366    case 'c':
1367    {
1368      if (LocaleCompare((const char *) tag,"colorize") == 0)
1369        {
1370          char
1371            blend[MaxTextExtent];
1372
1373          Image
1374            *colorize_image;
1375
1376          PixelInfo
1377            target;
1378
1379          /*
1380            Add noise image.
1381          */
1382          if (msl_info->image[n] == (Image *) NULL)
1383            {
1384              ThrowMSLException(OptionError,"NoImagesDefined",
1385                (const char *) tag);
1386              break;
1387            }
1388          GetPixelInfo(msl_info->image[n],&target);
1389          (void) CopyMagickString(blend,"100",MaxTextExtent);
1390          if (attributes != (const xmlChar **) NULL)
1391            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
1392            {
1393              keyword=(const char *) attributes[i++];
1394              attribute=InterpretImageProperties(msl_info->image_info[n],
1395                msl_info->attributes[n],(const char *) attributes[i],
1396                &exception);
1397              CloneString(&value,attribute);
1398              switch (*keyword)
1399              {
1400                case 'B':
1401                case 'b':
1402                {
1403                  if (LocaleCompare(keyword,"blend") == 0)
1404                    {
1405                      (void) CopyMagickString(blend,value,MaxTextExtent);
1406                      break;
1407                    }
1408                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1409                    keyword);
1410                  break;
1411                }
1412                case 'F':
1413                case 'f':
1414                {
1415                  if (LocaleCompare(keyword,"fill") == 0)
1416                    {
1417                      (void) QueryColorCompliance(value,AllCompliance,
1418                        &target,msl_info->exception);
1419                      break;
1420                    }
1421                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1422                    keyword);
1423                  break;
1424                }
1425                default:
1426                {
1427                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1428                    keyword);
1429                  break;
1430                }
1431              }
1432            }
1433          colorize_image=ColorizeImage(msl_info->image[n],blend,&target,
1434            msl_info->exception);
1435          if (colorize_image == (Image *) NULL)
1436            break;
1437          msl_info->image[n]=DestroyImage(msl_info->image[n]);
1438          msl_info->image[n]=colorize_image;
1439          break;
1440        }
1441      if (LocaleCompare((const char *) tag, "charcoal") == 0)
1442      {
1443        double
1444            radius = 0.0,
1445            sigma = 1.0;
1446
1447        if (msl_info->image[n] == (Image *) NULL)
1448        {
1449          ThrowMSLException(OptionError,"NoImagesDefined",
1450            (const char *) tag);
1451          break;
1452        }
1453        /*
1454        NOTE: charcoal can have no attributes, since we use all the defaults!
1455        */
1456        if (attributes != (const xmlChar **) NULL)
1457        {
1458          for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
1459          {
1460          keyword=(const char *) attributes[i++];
1461          CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
1462            msl_info->attributes[n],(const char *) attributes[i],&exception));
1463          switch (*keyword)
1464          {
1465            case 'R':
1466            case 'r':
1467            {
1468              if (LocaleCompare(keyword,"radius") == 0)
1469              {
1470                radius=StringToDouble(value,(char **) NULL);
1471                break;
1472              }
1473              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
1474              break;
1475            }
1476            case 'S':
1477            case 's':
1478            {
1479              if (LocaleCompare(keyword,"sigma") == 0)
1480              {
1481                sigma = StringToLong( value );
1482                break;
1483              }
1484              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
1485              break;
1486            }
1487            default:
1488            {
1489              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
1490              break;
1491            }
1492          }
1493          }
1494        }
1495
1496        /*
1497          charcoal image.
1498        */
1499        {
1500        Image
1501          *newImage;
1502
1503        newImage=CharcoalImage(msl_info->image[n],radius,sigma,
1504          msl_info->exception);
1505        if (newImage == (Image *) NULL)
1506          break;
1507        msl_info->image[n]=DestroyImage(msl_info->image[n]);
1508        msl_info->image[n]=newImage;
1509        break;
1510        }
1511      }
1512      if (LocaleCompare((const char *) tag,"chop") == 0)
1513        {
1514          Image
1515            *chop_image;
1516
1517          /*
1518            Chop image.
1519          */
1520          if (msl_info->image[n] == (Image *) NULL)
1521            {
1522              ThrowMSLException(OptionError,"NoImagesDefined",
1523                (const char *) tag);
1524              break;
1525            }
1526          SetGeometry(msl_info->image[n],&geometry);
1527          if (attributes != (const xmlChar **) NULL)
1528            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
1529            {
1530              keyword=(const char *) attributes[i++];
1531              attribute=InterpretImageProperties(msl_info->image_info[n],
1532                msl_info->attributes[n],(const char *) attributes[i],
1533                &exception);
1534              CloneString(&value,attribute);
1535              switch (*keyword)
1536              {
1537                case 'G':
1538                case 'g':
1539                {
1540                  if (LocaleCompare(keyword,"geometry") == 0)
1541                    {
1542                      flags=ParsePageGeometry(msl_info->image[n],value,
1543                        &geometry,&exception);
1544                      if ((flags & HeightValue) == 0)
1545                        geometry.height=geometry.width;
1546                      break;
1547                    }
1548                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1549                    keyword);
1550                  break;
1551                }
1552                case 'H':
1553                case 'h':
1554                {
1555                  if (LocaleCompare(keyword,"height") == 0)
1556                    {
1557                      geometry.height=StringToLong(value);
1558                      break;
1559                    }
1560                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1561                    keyword);
1562                  break;
1563                }
1564                case 'W':
1565                case 'w':
1566                {
1567                  if (LocaleCompare(keyword,"width") == 0)
1568                    {
1569                      geometry.width=StringToLong(value);
1570                      break;
1571                    }
1572                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1573                    keyword);
1574                  break;
1575                }
1576                case 'X':
1577                case 'x':
1578                {
1579                  if (LocaleCompare(keyword,"x") == 0)
1580                    {
1581                      geometry.x=StringToLong(value);
1582                      break;
1583                    }
1584                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1585                    keyword);
1586                  break;
1587                }
1588                case 'Y':
1589                case 'y':
1590                {
1591                  if (LocaleCompare(keyword,"y") == 0)
1592                    {
1593                      geometry.y=StringToLong(value);
1594                      break;
1595                    }
1596                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1597                    keyword);
1598                  break;
1599                }
1600                default:
1601                {
1602                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1603                    keyword);
1604                  break;
1605                }
1606              }
1607            }
1608          chop_image=ChopImage(msl_info->image[n],&geometry,
1609            msl_info->exception);
1610          if (chop_image == (Image *) NULL)
1611            break;
1612          msl_info->image[n]=DestroyImage(msl_info->image[n]);
1613          msl_info->image[n]=chop_image;
1614          break;
1615        }
1616      if (LocaleCompare((const char *) tag,"color-floodfill") == 0)
1617        {
1618          PaintMethod
1619            paint_method;
1620
1621          PixelInfo
1622            target;
1623
1624          /*
1625            Color floodfill image.
1626          */
1627          if (msl_info->image[n] == (Image *) NULL)
1628            {
1629              ThrowMSLException(OptionError,"NoImagesDefined",
1630                (const char *) tag);
1631              break;
1632            }
1633          draw_info=CloneDrawInfo(msl_info->image_info[n],
1634            msl_info->draw_info[n]);
1635          SetGeometry(msl_info->image[n],&geometry);
1636          paint_method=FloodfillMethod;
1637          if (attributes != (const xmlChar **) NULL)
1638            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
1639            {
1640              keyword=(const char *) attributes[i++];
1641              attribute=InterpretImageProperties(msl_info->image_info[n],
1642                msl_info->attributes[n],(const char *) attributes[i],
1643                &exception);
1644              CloneString(&value,attribute);
1645              switch (*keyword)
1646              {
1647                case 'B':
1648                case 'b':
1649                {
1650                  if (LocaleCompare(keyword,"bordercolor") == 0)
1651                    {
1652                      (void) QueryColorCompliance(value,AllCompliance,
1653                        &target,&exception);
1654                      paint_method=FillToBorderMethod;
1655                      break;
1656                    }
1657                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1658                    keyword);
1659                  break;
1660                }
1661                case 'F':
1662                case 'f':
1663                {
1664                  if (LocaleCompare(keyword,"fill") == 0)
1665                    {
1666                      (void) QueryColorCompliance(value,AllCompliance,
1667                        &draw_info->fill,&exception);
1668                      break;
1669                    }
1670                  if (LocaleCompare(keyword,"fuzz") == 0)
1671                    {
1672                      msl_info->image[n]->fuzz=StringToDouble(value,
1673                        (char **) NULL);
1674                      break;
1675                    }
1676                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1677                    keyword);
1678                  break;
1679                }
1680                case 'G':
1681                case 'g':
1682                {
1683                  if (LocaleCompare(keyword,"geometry") == 0)
1684                    {
1685                      flags=ParsePageGeometry(msl_info->image[n],value,
1686                        &geometry,&exception);
1687                      if ((flags & HeightValue) == 0)
1688                        geometry.height=geometry.width;
1689                      (void) GetOneVirtualPixelInfo(msl_info->image[n],
1690                        TileVirtualPixelMethod,geometry.x,geometry.y,&target,
1691                        &exception);
1692                      break;
1693                    }
1694                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1695                    keyword);
1696                  break;
1697                }
1698                case 'X':
1699                case 'x':
1700                {
1701                  if (LocaleCompare(keyword,"x") == 0)
1702                    {
1703                      geometry.x=StringToLong(value);
1704                      (void) GetOneVirtualPixelInfo(msl_info->image[n],
1705                        TileVirtualPixelMethod,geometry.x,geometry.y,&target,
1706                        &exception);
1707                      break;
1708                    }
1709                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1710                    keyword);
1711                  break;
1712                }
1713                case 'Y':
1714                case 'y':
1715                {
1716                  if (LocaleCompare(keyword,"y") == 0)
1717                    {
1718                      geometry.y=StringToLong(value);
1719                      (void) GetOneVirtualPixelInfo(msl_info->image[n],
1720                        TileVirtualPixelMethod,geometry.x,geometry.y,&target,
1721                        &exception);
1722                      break;
1723                    }
1724                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1725                    keyword);
1726                  break;
1727                }
1728                default:
1729                {
1730                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1731                    keyword);
1732                  break;
1733                }
1734              }
1735            }
1736          (void) FloodfillPaintImage(msl_info->image[n],draw_info,&target,
1737            geometry.x,geometry.y,paint_method == FloodfillMethod ?
1738            MagickFalse : MagickTrue,msl_info->exception);
1739          draw_info=DestroyDrawInfo(draw_info);
1740          break;
1741        }
1742      if (LocaleCompare((const char *) tag,"comment") == 0)
1743        break;
1744      if (LocaleCompare((const char *) tag,"composite") == 0)
1745        {
1746          char
1747            composite_geometry[MaxTextExtent];
1748
1749          CompositeOperator
1750            compose;
1751
1752          Image
1753            *composite_image,
1754            *rotate_image;
1755
1756          /*
1757            Composite image.
1758          */
1759          if (msl_info->image[n] == (Image *) NULL)
1760            {
1761              ThrowMSLException(OptionError,"NoImagesDefined",
1762                (const char *) tag);
1763              break;
1764            }
1765          composite_image=NewImageList();
1766          compose=OverCompositeOp;
1767          if (attributes != (const xmlChar **) NULL)
1768            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
1769            {
1770              keyword=(const char *) attributes[i++];
1771              attribute=InterpretImageProperties(msl_info->image_info[n],
1772                msl_info->attributes[n],(const char *) attributes[i],
1773                &exception);
1774              CloneString(&value,attribute);
1775              switch (*keyword)
1776              {
1777                case 'C':
1778                case 'c':
1779                {
1780                  if (LocaleCompare(keyword,"compose") == 0)
1781                    {
1782                      option=ParseCommandOption(MagickComposeOptions,
1783                        MagickFalse,value);
1784                      if (option < 0)
1785                        ThrowMSLException(OptionError,"UnrecognizedComposeType",
1786                          value);
1787                      compose=(CompositeOperator) option;
1788                      break;
1789                    }
1790                  break;
1791                }
1792                case 'I':
1793                case 'i':
1794                {
1795                  if (LocaleCompare(keyword,"image") == 0)
1796                    for (j=0; j < msl_info->n; j++)
1797                    {
1798                      const char
1799                        *attribute;
1800
1801                      attribute=GetImageProperty(msl_info->attributes[j],"id",
1802                        &exception);
1803                      if ((attribute != (const char *) NULL)  &&
1804                          (LocaleCompare(attribute,value) == 0))
1805                        {
1806                          composite_image=CloneImage(msl_info->image[j],0,0,
1807                            MagickFalse,&exception);
1808                          break;
1809                        }
1810                    }
1811                  break;
1812                }
1813                default:
1814                  break;
1815              }
1816            }
1817          if (composite_image == (Image *) NULL)
1818            break;
1819          rotate_image=NewImageList();
1820          SetGeometry(msl_info->image[n],&geometry);
1821          if (attributes != (const xmlChar **) NULL)
1822            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
1823            {
1824              keyword=(const char *) attributes[i++];
1825              attribute=InterpretImageProperties(msl_info->image_info[n],
1826                msl_info->attributes[n],(const char *) attributes[i],
1827                &exception);
1828              CloneString(&value,attribute);
1829              switch (*keyword)
1830              {
1831                case 'B':
1832                case 'b':
1833                {
1834                  if (LocaleCompare(keyword,"blend") == 0)
1835                    {
1836                      (void) SetImageArtifact(composite_image,
1837                                            "compose:args",value);
1838                      break;
1839                    }
1840                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1841                    keyword);
1842                  break;
1843                }
1844                case 'C':
1845                case 'c':
1846                {
1847                  if (LocaleCompare(keyword,"channel") == 0)
1848                    {
1849                      option=ParseChannelOption(value);
1850                      if (option < 0)
1851                        ThrowMSLException(OptionError,"UnrecognizedChannelType",
1852                          value);
1853                      channel=(ChannelType) option;
1854                      break;
1855                    }
1856                  if (LocaleCompare(keyword, "color") == 0)
1857                    {
1858                      (void) QueryColorCompliance(value,AllCompliance,
1859                        &composite_image->background_color,&exception);
1860                      break;
1861                    }
1862                  if (LocaleCompare(keyword,"compose") == 0)
1863                    break;
1864                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1865                    keyword);
1866                  break;
1867                }
1868                case 'G':
1869                case 'g':
1870                {
1871                  if (LocaleCompare(keyword,"geometry") == 0)
1872                    {
1873                      flags=ParsePageGeometry(msl_info->image[n],value,
1874                        &geometry,&exception);
1875                      if ((flags & HeightValue) == 0)
1876                        geometry.height=geometry.width;
1877                      break;
1878                    }
1879                  if (LocaleCompare(keyword,"gravity") == 0)
1880                    {
1881                      option=ParseCommandOption(MagickGravityOptions,
1882                        MagickFalse,value);
1883                      if (option < 0)
1884                        ThrowMSLException(OptionError,"UnrecognizedGravityType",
1885                          value);
1886                      msl_info->image[n]->gravity=(GravityType) option;
1887                      break;
1888                    }
1889                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1890                    keyword);
1891                  break;
1892                }
1893                case 'I':
1894                case 'i':
1895                {
1896                  if (LocaleCompare(keyword,"image") == 0)
1897                    break;
1898                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1899                    keyword);
1900                  break;
1901                }
1902                case 'M':
1903                case 'm':
1904                {
1905                  if (LocaleCompare(keyword,"mask") == 0)
1906                    for (j=0; j < msl_info->n; j++)
1907                    {
1908                      const char
1909                        *attribute;
1910
1911                      attribute=GetImageProperty(msl_info->attributes[j],"id",
1912                        &exception);
1913                      if ((attribute != (const char *) NULL)  &&
1914                          (LocaleCompare(value,value) == 0))
1915                        {
1916                          SetImageType(composite_image,TrueColorMatteType,
1917                            &exception);
1918                          (void) CompositeImage(composite_image,
1919                            msl_info->image[j],CopyAlphaCompositeOp,MagickTrue,
1920                            0,0,&exception);
1921                          break;
1922                        }
1923                    }
1924                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1925                    keyword);
1926                  break;
1927                }
1928                case 'O':
1929                case 'o':
1930                {
1931                  if (LocaleCompare(keyword,"opacity") == 0)
1932                    {
1933                      ssize_t
1934                        opacity,
1935                        y;
1936
1937                      register ssize_t
1938                        x;
1939
1940                      register Quantum
1941                        *q;
1942
1943                      CacheView
1944                        *composite_view;
1945
1946                      opacity=StringToLong(value);
1947                      if (compose != DissolveCompositeOp)
1948                        {
1949                          (void) SetImageAlpha(composite_image,(Quantum)
1950                            opacity,&exception);
1951                          break;
1952                        }
1953                      (void) SetImageArtifact(msl_info->image[n],
1954                                            "compose:args",value);
1955                      if (composite_image->alpha_trait == UndefinedPixelTrait)
1956                        (void) SetImageAlpha(composite_image,OpaqueAlpha,
1957                          &exception);
1958                      composite_view=AcquireAuthenticCacheView(composite_image,&exception);
1959                      for (y=0; y < (ssize_t) composite_image->rows ; y++)
1960                      {
1961                        q=GetCacheViewAuthenticPixels(composite_view,0,y,
1962                          (ssize_t) composite_image->columns,1,&exception);
1963                        for (x=0; x < (ssize_t) composite_image->columns; x++)
1964                        {
1965                          if (GetPixelAlpha(composite_image,q) == OpaqueAlpha)
1966                            SetPixelAlpha(composite_image,
1967                              ClampToQuantum(opacity),q);
1968                          q+=GetPixelChannels(composite_image);
1969                        }
1970                        if (SyncCacheViewAuthenticPixels(composite_view,&exception) == MagickFalse)
1971                          break;
1972                      }
1973                      composite_view=DestroyCacheView(composite_view);
1974                      break;
1975                    }
1976                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1977                    keyword);
1978                  break;
1979                }
1980                case 'R':
1981                case 'r':
1982                {
1983                  if (LocaleCompare(keyword,"rotate") == 0)
1984                    {
1985                      rotate_image=RotateImage(composite_image,
1986                        StringToDouble(value,(char **) NULL),&exception);
1987                      break;
1988                    }
1989                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
1990                    keyword);
1991                  break;
1992                }
1993                case 'T':
1994                case 't':
1995                {
1996                  if (LocaleCompare(keyword,"tile") == 0)
1997                    {
1998                      MagickBooleanType
1999                        tile;
2000
2001                      option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2002                        value);
2003                      if (option < 0)
2004                        ThrowMSLException(OptionError,"UnrecognizedBooleanType",
2005                          value);
2006                      tile=(MagickBooleanType) option;
2007                      (void) tile;
2008                      if (rotate_image != (Image *) NULL)
2009                        (void) SetImageArtifact(rotate_image,
2010                          "compose:outside-overlay","false");
2011                      else
2012                        (void) SetImageArtifact(composite_image,
2013                          "compose:outside-overlay","false");
2014                       image=msl_info->image[n];
2015                       height=composite_image->rows;
2016                       width=composite_image->columns;
2017                       for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) height)
2018                         for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) width)
2019                         {
2020                           if (rotate_image != (Image *) NULL)
2021                             (void) CompositeImage(image,rotate_image,compose,
2022                               MagickTrue,x,y,&exception);
2023                           else
2024                             (void) CompositeImage(image,composite_image,
2025                               compose,MagickTrue,x,y,&exception);
2026                         }
2027                      if (rotate_image != (Image *) NULL)
2028                        rotate_image=DestroyImage(rotate_image);
2029                      break;
2030                    }
2031                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2032                    keyword);
2033                  break;
2034                }
2035                case 'X':
2036                case 'x':
2037                {
2038                  if (LocaleCompare(keyword,"x") == 0)
2039                    {
2040                      geometry.x=StringToLong(value);
2041                      break;
2042                    }
2043                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2044                    keyword);
2045                  break;
2046                }
2047                case 'Y':
2048                case 'y':
2049                {
2050                  if (LocaleCompare(keyword,"y") == 0)
2051                    {
2052                      geometry.y=StringToLong(value);
2053                      break;
2054                    }
2055                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2056                    keyword);
2057                  break;
2058                }
2059                default:
2060                {
2061                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2062                    keyword);
2063                  break;
2064                }
2065              }
2066            }
2067          image=msl_info->image[n];
2068          (void) FormatLocaleString(composite_geometry,MaxTextExtent,
2069            "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
2070            (double) composite_image->rows,(double) geometry.x,(double)
2071            geometry.y);
2072          flags=ParseGravityGeometry(image,composite_geometry,&geometry,
2073            &exception);
2074          channel_mask=SetImageChannelMask(image,channel);
2075          if (rotate_image == (Image *) NULL)
2076            CompositeImage(image,composite_image,compose,MagickTrue,geometry.x,
2077              geometry.y,&exception);
2078          else
2079            {
2080              /*
2081                Rotate image.
2082              */
2083              geometry.x-=(ssize_t) (rotate_image->columns-
2084                composite_image->columns)/2;
2085              geometry.y-=(ssize_t) (rotate_image->rows-
2086                composite_image->rows)/2;
2087              CompositeImage(image,rotate_image,compose,MagickTrue,geometry.x,
2088                geometry.y,&exception);
2089              rotate_image=DestroyImage(rotate_image);
2090            }
2091          (void) SetImageChannelMask(image,channel_mask);
2092          composite_image=DestroyImage(composite_image);
2093          break;
2094        }
2095      if (LocaleCompare((const char *) tag,"contrast") == 0)
2096        {
2097          MagickBooleanType
2098            sharpen;
2099
2100          /*
2101            Contrast image.
2102          */
2103          if (msl_info->image[n] == (Image *) NULL)
2104            {
2105              ThrowMSLException(OptionError,"NoImagesDefined",
2106                (const char *) tag);
2107              break;
2108            }
2109          sharpen=MagickFalse;
2110          if (attributes != (const xmlChar **) NULL)
2111            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2112            {
2113              keyword=(const char *) attributes[i++];
2114              attribute=InterpretImageProperties(msl_info->image_info[n],
2115                msl_info->attributes[n],(const char *) attributes[i],
2116                &exception);
2117              CloneString(&value,attribute);
2118              switch (*keyword)
2119              {
2120                case 'S':
2121                case 's':
2122                {
2123                  if (LocaleCompare(keyword,"sharpen") == 0)
2124                    {
2125                      option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2126                        value);
2127                      if (option < 0)
2128                        ThrowMSLException(OptionError,"UnrecognizedBooleanType",
2129                          value);
2130                      sharpen=(MagickBooleanType) option;
2131                      break;
2132                    }
2133                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2134                    keyword);
2135                  break;
2136                }
2137                default:
2138                {
2139                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2140                    keyword);
2141                  break;
2142                }
2143              }
2144            }
2145          (void) ContrastImage(msl_info->image[n],sharpen,
2146            msl_info->exception);
2147          break;
2148        }
2149      if (LocaleCompare((const char *) tag,"crop") == 0)
2150        {
2151          Image
2152            *crop_image;
2153
2154          /*
2155            Crop image.
2156          */
2157          if (msl_info->image[n] == (Image *) NULL)
2158            {
2159              ThrowMSLException(OptionError,"NoImagesDefined",
2160                (const char *) tag);
2161              break;
2162            }
2163          SetGeometry(msl_info->image[n],&geometry);
2164          if (attributes != (const xmlChar **) NULL)
2165            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2166            {
2167              keyword=(const char *) attributes[i++];
2168              attribute=InterpretImageProperties(msl_info->image_info[n],
2169                msl_info->attributes[n],(const char *) attributes[i],
2170                &exception);
2171              CloneString(&value,attribute);
2172              switch (*keyword)
2173              {
2174                case 'G':
2175                case 'g':
2176                {
2177                  if (LocaleCompare(keyword,"geometry") == 0)
2178                    {
2179                      flags=ParseGravityGeometry(msl_info->image[n],value,
2180                        &geometry,&exception);
2181                      break;
2182                    }
2183                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2184                    keyword);
2185                  break;
2186                }
2187                case 'H':
2188                case 'h':
2189                {
2190                  if (LocaleCompare(keyword,"height") == 0)
2191                    {
2192                      geometry.height=StringToLong(value);
2193                      break;
2194                    }
2195                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2196                    keyword);
2197                  break;
2198                }
2199                case 'W':
2200                case 'w':
2201                {
2202                  if (LocaleCompare(keyword,"width") == 0)
2203                    {
2204                      geometry.width=StringToLong(value);
2205                      break;
2206                    }
2207                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2208                    keyword);
2209                  break;
2210                }
2211                case 'X':
2212                case 'x':
2213                {
2214                  if (LocaleCompare(keyword,"x") == 0)
2215                    {
2216                      geometry.x=StringToLong(value);
2217                      break;
2218                    }
2219                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2220                    keyword);
2221                  break;
2222                }
2223                case 'Y':
2224                case 'y':
2225                {
2226                  if (LocaleCompare(keyword,"y") == 0)
2227                    {
2228                      geometry.y=StringToLong(value);
2229                      break;
2230                    }
2231                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2232                    keyword);
2233                  break;
2234                }
2235                default:
2236                {
2237                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2238                    keyword);
2239                  break;
2240                }
2241              }
2242            }
2243          crop_image=CropImage(msl_info->image[n],&geometry,
2244            msl_info->exception);
2245          if (crop_image == (Image *) NULL)
2246            break;
2247          msl_info->image[n]=DestroyImage(msl_info->image[n]);
2248          msl_info->image[n]=crop_image;
2249          break;
2250        }
2251      if (LocaleCompare((const char *) tag,"cycle-colormap") == 0)
2252        {
2253          ssize_t
2254            display;
2255
2256          /*
2257            Cycle-colormap image.
2258          */
2259          if (msl_info->image[n] == (Image *) NULL)
2260            {
2261              ThrowMSLException(OptionError,"NoImagesDefined",
2262                (const char *) tag);
2263              break;
2264            }
2265          display=0;
2266          if (attributes != (const xmlChar **) NULL)
2267            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2268            {
2269              keyword=(const char *) attributes[i++];
2270              attribute=InterpretImageProperties(msl_info->image_info[n],
2271                msl_info->attributes[n],(const char *) attributes[i],
2272                &exception);
2273              CloneString(&value,attribute);
2274              switch (*keyword)
2275              {
2276                case 'D':
2277                case 'd':
2278                {
2279                  if (LocaleCompare(keyword,"display") == 0)
2280                    {
2281                      display=StringToLong(value);
2282                      break;
2283                    }
2284                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2285                    keyword);
2286                  break;
2287                }
2288                default:
2289                {
2290                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2291                    keyword);
2292                  break;
2293                }
2294              }
2295            }
2296          (void) CycleColormapImage(msl_info->image[n],display,&exception);
2297          break;
2298        }
2299      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
2300    }
2301    case 'D':
2302    case 'd':
2303    {
2304      if (LocaleCompare((const char *) tag,"despeckle") == 0)
2305        {
2306          Image
2307            *despeckle_image;
2308
2309          /*
2310            Despeckle image.
2311          */
2312          if (msl_info->image[n] == (Image *) NULL)
2313            {
2314              ThrowMSLException(OptionError,"NoImagesDefined",
2315                (const char *) tag);
2316              break;
2317            }
2318          if (attributes != (const xmlChar **) NULL)
2319            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2320            {
2321              keyword=(const char *) attributes[i++];
2322              attribute=InterpretImageProperties(msl_info->image_info[n],
2323                msl_info->attributes[n],(const char *) attributes[i],
2324                &exception);
2325              CloneString(&value,attribute);
2326              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
2327            }
2328          despeckle_image=DespeckleImage(msl_info->image[n],
2329            msl_info->exception);
2330          if (despeckle_image == (Image *) NULL)
2331            break;
2332          msl_info->image[n]=DestroyImage(msl_info->image[n]);
2333          msl_info->image[n]=despeckle_image;
2334          break;
2335        }
2336      if (LocaleCompare((const char *) tag,"display") == 0)
2337        {
2338          if (msl_info->image[n] == (Image *) NULL)
2339            {
2340              ThrowMSLException(OptionError,"NoImagesDefined",
2341                (const char *) tag);
2342              break;
2343            }
2344          if (attributes != (const xmlChar **) NULL)
2345            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2346            {
2347              keyword=(const char *) attributes[i++];
2348              attribute=InterpretImageProperties(msl_info->image_info[n],
2349                msl_info->attributes[n],(const char *) attributes[i],
2350                &exception);
2351              CloneString(&value,attribute);
2352              switch (*keyword)
2353              {
2354                default:
2355                {
2356                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2357                    keyword);
2358                  break;
2359                }
2360              }
2361            }
2362          (void) DisplayImages(msl_info->image_info[n],msl_info->image[n],
2363            msl_info->exception);
2364          break;
2365        }
2366      if (LocaleCompare((const char *) tag,"draw") == 0)
2367        {
2368          char
2369            text[MaxTextExtent];
2370
2371          /*
2372            Annotate image.
2373          */
2374          if (msl_info->image[n] == (Image *) NULL)
2375            {
2376              ThrowMSLException(OptionError,"NoImagesDefined",
2377                (const char *) tag);
2378              break;
2379            }
2380          draw_info=CloneDrawInfo(msl_info->image_info[n],
2381            msl_info->draw_info[n]);
2382          angle=0.0;
2383          current=draw_info->affine;
2384          GetAffineMatrix(&affine);
2385          if (attributes != (const xmlChar **) NULL)
2386            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2387            {
2388              keyword=(const char *) attributes[i++];
2389              attribute=InterpretImageProperties(msl_info->image_info[n],
2390                msl_info->attributes[n],(const char *) attributes[i],
2391                &exception);
2392              CloneString(&value,attribute);
2393              switch (*keyword)
2394              {
2395                case 'A':
2396                case 'a':
2397                {
2398                  if (LocaleCompare(keyword,"affine") == 0)
2399                    {
2400                      char
2401                        *p;
2402
2403                      p=value;
2404                      draw_info->affine.sx=StringToDouble(p,&p);
2405                      if (*p ==',')
2406                        p++;
2407                      draw_info->affine.rx=StringToDouble(p,&p);
2408                      if (*p ==',')
2409                        p++;
2410                      draw_info->affine.ry=StringToDouble(p,&p);
2411                      if (*p ==',')
2412                        p++;
2413                      draw_info->affine.sy=StringToDouble(p,&p);
2414                      if (*p ==',')
2415                        p++;
2416                      draw_info->affine.tx=StringToDouble(p,&p);
2417                      if (*p ==',')
2418                        p++;
2419                      draw_info->affine.ty=StringToDouble(p,&p);
2420                      break;
2421                    }
2422                  if (LocaleCompare(keyword,"align") == 0)
2423                    {
2424                      option=ParseCommandOption(MagickAlignOptions,MagickFalse,
2425                        value);
2426                      if (option < 0)
2427                        ThrowMSLException(OptionError,"UnrecognizedAlignType",
2428                          value);
2429                      draw_info->align=(AlignType) option;
2430                      break;
2431                    }
2432                  if (LocaleCompare(keyword,"antialias") == 0)
2433                    {
2434                      option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2435                        value);
2436                      if (option < 0)
2437                        ThrowMSLException(OptionError,"UnrecognizedBooleanType",
2438                          value);
2439                      draw_info->stroke_antialias=(MagickBooleanType) option;
2440                      draw_info->text_antialias=(MagickBooleanType) option;
2441                      break;
2442                    }
2443                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2444                    keyword);
2445                  break;
2446                }
2447                case 'D':
2448                case 'd':
2449                {
2450                  if (LocaleCompare(keyword,"density") == 0)
2451                    {
2452                      CloneString(&draw_info->density,value);
2453                      break;
2454                    }
2455                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2456                    keyword);
2457                  break;
2458                }
2459                case 'E':
2460                case 'e':
2461                {
2462                  if (LocaleCompare(keyword,"encoding") == 0)
2463                    {
2464                      CloneString(&draw_info->encoding,value);
2465                      break;
2466                    }
2467                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2468                    keyword);
2469                  break;
2470                }
2471                case 'F':
2472                case 'f':
2473                {
2474                  if (LocaleCompare(keyword, "fill") == 0)
2475                    {
2476                      (void) QueryColorCompliance(value,AllCompliance,
2477                        &draw_info->fill,&exception);
2478                      break;
2479                    }
2480                  if (LocaleCompare(keyword,"family") == 0)
2481                    {
2482                      CloneString(&draw_info->family,value);
2483                      break;
2484                    }
2485                  if (LocaleCompare(keyword,"font") == 0)
2486                    {
2487                      CloneString(&draw_info->font,value);
2488                      break;
2489                    }
2490                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2491                    keyword);
2492                  break;
2493                }
2494                case 'G':
2495                case 'g':
2496                {
2497                  if (LocaleCompare(keyword,"geometry") == 0)
2498                    {
2499                      flags=ParsePageGeometry(msl_info->image[n],value,
2500                        &geometry,&exception);
2501                      if ((flags & HeightValue) == 0)
2502                        geometry.height=geometry.width;
2503                      break;
2504                    }
2505                  if (LocaleCompare(keyword,"gravity") == 0)
2506                    {
2507                      option=ParseCommandOption(MagickGravityOptions,MagickFalse,
2508                        value);
2509                      if (option < 0)
2510                        ThrowMSLException(OptionError,"UnrecognizedGravityType",
2511                          value);
2512                      draw_info->gravity=(GravityType) option;
2513                      break;
2514                    }
2515                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2516                    keyword);
2517                  break;
2518                }
2519                case 'P':
2520                case 'p':
2521                {
2522                  if (LocaleCompare(keyword,"primitive") == 0)
2523                    {
2524                      CloneString(&draw_info->primitive,value);
2525                      break;
2526                    }
2527                  if (LocaleCompare(keyword,"pointsize") == 0)
2528                    {
2529                      draw_info->pointsize=StringToDouble(value,
2530                        (char **) NULL);
2531                      break;
2532                    }
2533                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2534                    keyword);
2535                  break;
2536                }
2537                case 'R':
2538                case 'r':
2539                {
2540                  if (LocaleCompare(keyword,"rotate") == 0)
2541                    {
2542                      angle=StringToDouble(value,(char **) NULL);
2543                      affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
2544                      affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
2545                      affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
2546                      affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
2547                      break;
2548                    }
2549                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2550                    keyword);
2551                  break;
2552                }
2553                case 'S':
2554                case 's':
2555                {
2556                  if (LocaleCompare(keyword,"scale") == 0)
2557                    {
2558                      flags=ParseGeometry(value,&geometry_info);
2559                      if ((flags & SigmaValue) == 0)
2560                        geometry_info.sigma=1.0;
2561                      affine.sx=geometry_info.rho;
2562                      affine.sy=geometry_info.sigma;
2563                      break;
2564                    }
2565                  if (LocaleCompare(keyword,"skewX") == 0)
2566                    {
2567                      angle=StringToDouble(value,(char **) NULL);
2568                      affine.ry=cos(DegreesToRadians(fmod(angle,360.0)));
2569                      break;
2570                    }
2571                  if (LocaleCompare(keyword,"skewY") == 0)
2572                    {
2573                      angle=StringToDouble(value,(char **) NULL);
2574                      affine.rx=cos(DegreesToRadians(fmod(angle,360.0)));
2575                      break;
2576                    }
2577                  if (LocaleCompare(keyword,"stretch") == 0)
2578                    {
2579                      option=ParseCommandOption(MagickStretchOptions,
2580                        MagickFalse,value);
2581                      if (option < 0)
2582                        ThrowMSLException(OptionError,"UnrecognizedStretchType",
2583                          value);
2584                      draw_info->stretch=(StretchType) option;
2585                      break;
2586                    }
2587                  if (LocaleCompare(keyword, "stroke") == 0)
2588                    {
2589                      (void) QueryColorCompliance(value,AllCompliance,
2590                        &draw_info->stroke,&exception);
2591                      break;
2592                    }
2593                  if (LocaleCompare(keyword,"strokewidth") == 0)
2594                    {
2595                      draw_info->stroke_width=StringToLong(value);
2596                      break;
2597                    }
2598                  if (LocaleCompare(keyword,"style") == 0)
2599                    {
2600                      option=ParseCommandOption(MagickStyleOptions,MagickFalse,
2601                        value);
2602                      if (option < 0)
2603                        ThrowMSLException(OptionError,"UnrecognizedStyleType",
2604                          value);
2605                      draw_info->style=(StyleType) option;
2606                      break;
2607                    }
2608                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2609                    keyword);
2610                  break;
2611                }
2612                case 'T':
2613                case 't':
2614                {
2615                  if (LocaleCompare(keyword,"text") == 0)
2616                    {
2617                      CloneString(&draw_info->text,value);
2618                      break;
2619                    }
2620                  if (LocaleCompare(keyword,"translate") == 0)
2621                    {
2622                      flags=ParseGeometry(value,&geometry_info);
2623                      if ((flags & SigmaValue) == 0)
2624                        geometry_info.sigma=1.0;
2625                      affine.tx=geometry_info.rho;
2626                      affine.ty=geometry_info.sigma;
2627                      break;
2628                    }
2629                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2630                    keyword);
2631                  break;
2632                }
2633                case 'U':
2634                case 'u':
2635                {
2636                  if (LocaleCompare(keyword, "undercolor") == 0)
2637                    {
2638                      (void) QueryColorCompliance(value,AllCompliance,
2639                        &draw_info->undercolor,&exception);
2640                      break;
2641                    }
2642                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2643                    keyword);
2644                  break;
2645                }
2646                case 'W':
2647                case 'w':
2648                {
2649                  if (LocaleCompare(keyword,"weight") == 0)
2650                    {
2651                      draw_info->weight=StringToLong(value);
2652                      break;
2653                    }
2654                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2655                    keyword);
2656                  break;
2657                }
2658                case 'X':
2659                case 'x':
2660                {
2661                  if (LocaleCompare(keyword,"x") == 0)
2662                    {
2663                      geometry.x=StringToLong(value);
2664                      break;
2665                    }
2666                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2667                    keyword);
2668                  break;
2669                }
2670                case 'Y':
2671                case 'y':
2672                {
2673                  if (LocaleCompare(keyword,"y") == 0)
2674                    {
2675                      geometry.y=StringToLong(value);
2676                      break;
2677                    }
2678                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2679                    keyword);
2680                  break;
2681                }
2682                default:
2683                {
2684                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2685                    keyword);
2686                  break;
2687                }
2688              }
2689            }
2690          (void) FormatLocaleString(text,MaxTextExtent,
2691            "%.20gx%.20g%+.20g%+.20g",(double) geometry.width,(double)
2692            geometry.height,(double) geometry.x,(double) geometry.y);
2693          CloneString(&draw_info->geometry,text);
2694          draw_info->affine.sx=affine.sx*current.sx+affine.ry*current.rx;
2695          draw_info->affine.rx=affine.rx*current.sx+affine.sy*current.rx;
2696          draw_info->affine.ry=affine.sx*current.ry+affine.ry*current.sy;
2697          draw_info->affine.sy=affine.rx*current.ry+affine.sy*current.sy;
2698          draw_info->affine.tx=affine.sx*current.tx+affine.ry*current.ty+
2699            affine.tx;
2700          draw_info->affine.ty=affine.rx*current.tx+affine.sy*current.ty+
2701            affine.ty;
2702          (void) DrawImage(msl_info->image[n],draw_info,&exception);
2703          draw_info=DestroyDrawInfo(draw_info);
2704          break;
2705        }
2706      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
2707    }
2708    case 'E':
2709    case 'e':
2710    {
2711      if (LocaleCompare((const char *) tag,"edge") == 0)
2712        {
2713          Image
2714            *edge_image;
2715
2716          /*
2717            Edge image.
2718          */
2719          if (msl_info->image[n] == (Image *) NULL)
2720            {
2721              ThrowMSLException(OptionError,"NoImagesDefined",
2722                (const char *) tag);
2723              break;
2724            }
2725          if (attributes != (const xmlChar **) NULL)
2726            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2727            {
2728              keyword=(const char *) attributes[i++];
2729              attribute=InterpretImageProperties(msl_info->image_info[n],
2730                msl_info->attributes[n],(const char *) attributes[i],
2731                &exception);
2732              CloneString(&value,attribute);
2733              switch (*keyword)
2734              {
2735                case 'G':
2736                case 'g':
2737                {
2738                  if (LocaleCompare(keyword,"geometry") == 0)
2739                    {
2740                      flags=ParseGeometry(value,&geometry_info);
2741                      if ((flags & SigmaValue) == 0)
2742                        geometry_info.sigma=1.0;
2743                      break;
2744                    }
2745                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2746                    keyword);
2747                  break;
2748                }
2749                case 'R':
2750                case 'r':
2751                {
2752                  if (LocaleCompare(keyword,"radius") == 0)
2753                    {
2754                      geometry_info.rho=StringToDouble(value,(char **) NULL);
2755                      break;
2756                    }
2757                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2758                    keyword);
2759                  break;
2760                }
2761                default:
2762                {
2763                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2764                    keyword);
2765                  break;
2766                }
2767              }
2768            }
2769          edge_image=EdgeImage(msl_info->image[n],geometry_info.rho,
2770            msl_info->exception);
2771          if (edge_image == (Image *) NULL)
2772            break;
2773          msl_info->image[n]=DestroyImage(msl_info->image[n]);
2774          msl_info->image[n]=edge_image;
2775          break;
2776        }
2777      if (LocaleCompare((const char *) tag,"emboss") == 0)
2778        {
2779          Image
2780            *emboss_image;
2781
2782          /*
2783            Emboss image.
2784          */
2785          if (msl_info->image[n] == (Image *) NULL)
2786            {
2787              ThrowMSLException(OptionError,"NoImagesDefined",
2788                (const char *) tag);
2789              break;
2790            }
2791          if (attributes != (const xmlChar **) NULL)
2792            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2793            {
2794              keyword=(const char *) attributes[i++];
2795              attribute=InterpretImageProperties(msl_info->image_info[n],
2796                msl_info->attributes[n],(const char *) attributes[i],
2797                &exception);
2798              CloneString(&value,attribute);
2799              switch (*keyword)
2800              {
2801                case 'G':
2802                case 'g':
2803                {
2804                  if (LocaleCompare(keyword,"geometry") == 0)
2805                    {
2806                      flags=ParseGeometry(value,&geometry_info);
2807                      if ((flags & SigmaValue) == 0)
2808                        geometry_info.sigma=1.0;
2809                      break;
2810                    }
2811                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2812                    keyword);
2813                  break;
2814                }
2815                case 'R':
2816                case 'r':
2817                {
2818                  if (LocaleCompare(keyword,"radius") == 0)
2819                    {
2820                      geometry_info.rho=StringToDouble(value,
2821                        (char **) NULL);
2822                      break;
2823                    }
2824                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2825                    keyword);
2826                  break;
2827                }
2828                case 'S':
2829                case 's':
2830                {
2831                  if (LocaleCompare(keyword,"sigma") == 0)
2832                    {
2833                      geometry_info.sigma=StringToLong(value);
2834                      break;
2835                    }
2836                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2837                    keyword);
2838                  break;
2839                }
2840                default:
2841                {
2842                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2843                    keyword);
2844                  break;
2845                }
2846              }
2847            }
2848          emboss_image=EmbossImage(msl_info->image[n],geometry_info.rho,
2849            geometry_info.sigma,msl_info->exception);
2850          if (emboss_image == (Image *) NULL)
2851            break;
2852          msl_info->image[n]=DestroyImage(msl_info->image[n]);
2853          msl_info->image[n]=emboss_image;
2854          break;
2855        }
2856      if (LocaleCompare((const char *) tag,"enhance") == 0)
2857        {
2858          Image
2859            *enhance_image;
2860
2861          /*
2862            Enhance image.
2863          */
2864          if (msl_info->image[n] == (Image *) NULL)
2865            {
2866              ThrowMSLException(OptionError,"NoImagesDefined",
2867                (const char *) tag);
2868              break;
2869            }
2870          if (attributes != (const xmlChar **) NULL)
2871            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2872            {
2873              keyword=(const char *) attributes[i++];
2874              attribute=InterpretImageProperties(msl_info->image_info[n],
2875                msl_info->attributes[n],(const char *) attributes[i],
2876                &exception);
2877              CloneString(&value,attribute);
2878              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
2879            }
2880          enhance_image=EnhanceImage(msl_info->image[n],
2881            msl_info->exception);
2882          if (enhance_image == (Image *) NULL)
2883            break;
2884          msl_info->image[n]=DestroyImage(msl_info->image[n]);
2885          msl_info->image[n]=enhance_image;
2886          break;
2887        }
2888      if (LocaleCompare((const char *) tag,"equalize") == 0)
2889        {
2890          /*
2891            Equalize image.
2892          */
2893          if (msl_info->image[n] == (Image *) NULL)
2894            {
2895              ThrowMSLException(OptionError,"NoImagesDefined",
2896                (const char *) tag);
2897              break;
2898            }
2899          if (attributes != (const xmlChar **) NULL)
2900            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2901            {
2902              keyword=(const char *) attributes[i++];
2903              attribute=InterpretImageProperties(msl_info->image_info[n],
2904                msl_info->attributes[n],(const char *) attributes[i],
2905                &exception);
2906              CloneString(&value,attribute);
2907              switch (*keyword)
2908              {
2909                default:
2910                {
2911                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
2912                    keyword);
2913                  break;
2914                }
2915              }
2916            }
2917          (void) EqualizeImage(msl_info->image[n],
2918            msl_info->exception);
2919          break;
2920        }
2921      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
2922    }
2923    case 'F':
2924    case 'f':
2925    {
2926      if (LocaleCompare((const char *) tag, "flatten") == 0)
2927      {
2928        if (msl_info->image[n] == (Image *) NULL)
2929        {
2930          ThrowMSLException(OptionError,"NoImagesDefined",
2931            (const char *) tag);
2932          break;
2933        }
2934
2935        /* no attributes here */
2936
2937        /* process the image */
2938        {
2939          Image
2940            *newImage;
2941
2942          newImage=MergeImageLayers(msl_info->image[n],FlattenLayer,
2943            msl_info->exception);
2944          if (newImage == (Image *) NULL)
2945            break;
2946          msl_info->image[n]=DestroyImage(msl_info->image[n]);
2947          msl_info->image[n]=newImage;
2948          break;
2949        }
2950      }
2951      if (LocaleCompare((const char *) tag,"flip") == 0)
2952        {
2953          Image
2954            *flip_image;
2955
2956          /*
2957            Flip image.
2958          */
2959          if (msl_info->image[n] == (Image *) NULL)
2960            {
2961              ThrowMSLException(OptionError,"NoImagesDefined",
2962                (const char *) tag);
2963              break;
2964            }
2965          if (attributes != (const xmlChar **) NULL)
2966            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2967            {
2968              keyword=(const char *) attributes[i++];
2969              attribute=InterpretImageProperties(msl_info->image_info[n],
2970                msl_info->attributes[n],(const char *) attributes[i],
2971                &exception);
2972              CloneString(&value,attribute);
2973              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
2974            }
2975          flip_image=FlipImage(msl_info->image[n],
2976            msl_info->exception);
2977          if (flip_image == (Image *) NULL)
2978            break;
2979          msl_info->image[n]=DestroyImage(msl_info->image[n]);
2980          msl_info->image[n]=flip_image;
2981          break;
2982        }
2983      if (LocaleCompare((const char *) tag,"flop") == 0)
2984        {
2985          Image
2986            *flop_image;
2987
2988          /*
2989            Flop image.
2990          */
2991          if (msl_info->image[n] == (Image *) NULL)
2992            {
2993              ThrowMSLException(OptionError,"NoImagesDefined",
2994                (const char *) tag);
2995              break;
2996            }
2997          if (attributes != (const xmlChar **) NULL)
2998            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
2999            {
3000              keyword=(const char *) attributes[i++];
3001              attribute=InterpretImageProperties(msl_info->image_info[n],
3002                msl_info->attributes[n],(const char *) attributes[i],
3003                &exception);
3004              CloneString(&value,attribute);
3005              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
3006            }
3007          flop_image=FlopImage(msl_info->image[n],
3008            msl_info->exception);
3009          if (flop_image == (Image *) NULL)
3010            break;
3011          msl_info->image[n]=DestroyImage(msl_info->image[n]);
3012          msl_info->image[n]=flop_image;
3013          break;
3014        }
3015      if (LocaleCompare((const char *) tag,"frame") == 0)
3016        {
3017          FrameInfo
3018            frame_info;
3019
3020          Image
3021            *frame_image;
3022
3023          /*
3024            Frame image.
3025          */
3026          if (msl_info->image[n] == (Image *) NULL)
3027            {
3028              ThrowMSLException(OptionError,"NoImagesDefined",
3029                (const char *) tag);
3030              break;
3031            }
3032          SetGeometry(msl_info->image[n],&geometry);
3033          if (attributes != (const xmlChar **) NULL)
3034            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3035            {
3036              keyword=(const char *) attributes[i++];
3037              attribute=InterpretImageProperties(msl_info->image_info[n],
3038                msl_info->attributes[n],(const char *) attributes[i],
3039                &exception);
3040              CloneString(&value,attribute);
3041              switch (*keyword)
3042              {
3043                case 'C':
3044                case 'c':
3045                {
3046                  if (LocaleCompare(keyword,"compose") == 0)
3047                    {
3048                      option=ParseCommandOption(MagickComposeOptions,
3049                        MagickFalse,value);
3050                      if (option < 0)
3051                        ThrowMSLException(OptionError,"UnrecognizedComposeType",
3052                          value);
3053                      msl_info->image[n]->compose=(CompositeOperator) option;
3054                      break;
3055                    }
3056                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3057                    keyword);
3058                  break;
3059                }
3060                case 'F':
3061                case 'f':
3062                {
3063                  if (LocaleCompare(keyword, "fill") == 0)
3064                    {
3065                      (void) QueryColorCompliance(value,AllCompliance,
3066                        &msl_info->image[n]->matte_color,&exception);
3067                      break;
3068                    }
3069                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3070                    keyword);
3071                  break;
3072                }
3073                case 'G':
3074                case 'g':
3075                {
3076                  if (LocaleCompare(keyword,"geometry") == 0)
3077                    {
3078                      flags=ParsePageGeometry(msl_info->image[n],value,
3079                        &geometry,&exception);
3080                      if ((flags & HeightValue) == 0)
3081                        geometry.height=geometry.width;
3082                      frame_info.width=geometry.width;
3083                      frame_info.height=geometry.height;
3084                      frame_info.outer_bevel=geometry.x;
3085                      frame_info.inner_bevel=geometry.y;
3086                      break;
3087                    }
3088                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3089                    keyword);
3090                  break;
3091                }
3092                case 'H':
3093                case 'h':
3094                {
3095                  if (LocaleCompare(keyword,"height") == 0)
3096                    {
3097                      frame_info.height=StringToLong(value);
3098                      break;
3099                    }
3100                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3101                    keyword);
3102                  break;
3103                }
3104                case 'I':
3105                case 'i':
3106                {
3107                  if (LocaleCompare(keyword,"inner") == 0)
3108                    {
3109                      frame_info.inner_bevel=StringToLong(value);
3110                      break;
3111                    }
3112                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3113                    keyword);
3114                  break;
3115                }
3116                case 'O':
3117                case 'o':
3118                {
3119                  if (LocaleCompare(keyword,"outer") == 0)
3120                    {
3121                      frame_info.outer_bevel=StringToLong(value);
3122                      break;
3123                    }
3124                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3125                    keyword);
3126                  break;
3127                }
3128                case 'W':
3129                case 'w':
3130                {
3131                  if (LocaleCompare(keyword,"width") == 0)
3132                    {
3133                      frame_info.width=StringToLong(value);
3134                      break;
3135                    }
3136                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3137                    keyword);
3138                  break;
3139                }
3140                default:
3141                {
3142                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3143                    keyword);
3144                  break;
3145                }
3146              }
3147            }
3148          frame_info.x=(ssize_t) frame_info.width;
3149          frame_info.y=(ssize_t) frame_info.height;
3150          frame_info.width=msl_info->image[n]->columns+2*frame_info.x;
3151          frame_info.height=msl_info->image[n]->rows+2*frame_info.y;
3152          frame_image=FrameImage(msl_info->image[n],&frame_info,
3153            msl_info->image[n]->compose,msl_info->exception);
3154          if (frame_image == (Image *) NULL)
3155            break;
3156          msl_info->image[n]=DestroyImage(msl_info->image[n]);
3157          msl_info->image[n]=frame_image;
3158          break;
3159        }
3160      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
3161    }
3162    case 'G':
3163    case 'g':
3164    {
3165      if (LocaleCompare((const char *) tag,"gamma") == 0)
3166        {
3167          char
3168            gamma[MaxTextExtent];
3169
3170          PixelInfo
3171            pixel;
3172
3173          /*
3174            Gamma image.
3175          */
3176          if (msl_info->image[n] == (Image *) NULL)
3177            {
3178              ThrowMSLException(OptionError,"NoImagesDefined",
3179                (const char *) tag);
3180              break;
3181            }
3182          channel=UndefinedChannel;
3183          pixel.red=0.0;
3184          pixel.green=0.0;
3185          pixel.blue=0.0;
3186          *gamma='\0';
3187          if (attributes != (const xmlChar **) NULL)
3188            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3189            {
3190              keyword=(const char *) attributes[i++];
3191              attribute=InterpretImageProperties(msl_info->image_info[n],
3192                msl_info->attributes[n],(const char *) attributes[i],
3193                &exception);
3194              CloneString(&value,attribute);
3195              switch (*keyword)
3196              {
3197                case 'B':
3198                case 'b':
3199                {
3200                  if (LocaleCompare(keyword,"blue") == 0)
3201                    {
3202                      pixel.blue=StringToDouble(value,(char **) NULL);
3203                      break;
3204                    }
3205                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3206                    keyword);
3207                  break;
3208                }
3209                case 'C':
3210                case 'c':
3211                {
3212                  if (LocaleCompare(keyword,"channel") == 0)
3213                    {
3214                      option=ParseChannelOption(value);
3215                      if (option < 0)
3216                        ThrowMSLException(OptionError,"UnrecognizedChannelType",
3217                          value);
3218                      channel=(ChannelType) option;
3219                      break;
3220                    }
3221                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3222                    keyword);
3223                  break;
3224                }
3225                case 'G':
3226                case 'g':
3227                {
3228                  if (LocaleCompare(keyword,"gamma") == 0)
3229                    {
3230                      (void) CopyMagickString(gamma,value,MaxTextExtent);
3231                      break;
3232                    }
3233                  if (LocaleCompare(keyword,"green") == 0)
3234                    {
3235                      pixel.green=StringToDouble(value,(char **) NULL);
3236                      break;
3237                    }
3238                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3239                    keyword);
3240                  break;
3241                }
3242                case 'R':
3243                case 'r':
3244                {
3245                  if (LocaleCompare(keyword,"red") == 0)
3246                    {
3247                      pixel.red=StringToDouble(value,(char **) NULL);
3248                      break;
3249                    }
3250                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3251                    keyword);
3252                  break;
3253                }
3254                default:
3255                {
3256                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3257                    keyword);
3258                  break;
3259                }
3260              }
3261            }
3262          if (*gamma == '\0')
3263            (void) FormatLocaleString(gamma,MaxTextExtent,"%g,%g,%g",
3264              (double) pixel.red,(double) pixel.green,(double) pixel.blue);
3265          (void) GammaImage(msl_info->image[n],atof(gamma),
3266            msl_info->exception);
3267          break;
3268        }
3269      else if (LocaleCompare((const char *) tag,"get") == 0)
3270        {
3271          if (msl_info->image[n] == (Image *) NULL)
3272            {
3273              ThrowMSLException(OptionError,"NoImagesDefined",
3274                (const char *) tag);
3275              break;
3276            }
3277          if (attributes == (const xmlChar **) NULL)
3278            break;
3279          for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3280          {
3281            keyword=(const char *) attributes[i++];
3282            CloneString(&value,(const char *) attributes[i]);
3283            (void) CopyMagickString(key,value,MaxTextExtent);
3284            switch (*keyword)
3285            {
3286              case 'H':
3287              case 'h':
3288              {
3289                if (LocaleCompare(keyword,"height") == 0)
3290                  {
3291                    (void) FormatLocaleString(value,MaxTextExtent,"%.20g",
3292                      (double) msl_info->image[n]->rows);
3293                    (void) SetImageProperty(msl_info->attributes[n],key,value,
3294                      &exception);
3295                    break;
3296                  }
3297                ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
3298              }
3299              case 'W':
3300              case 'w':
3301              {
3302                if (LocaleCompare(keyword,"width") == 0)
3303                  {
3304                    (void) FormatLocaleString(value,MaxTextExtent,"%.20g",
3305                      (double) msl_info->image[n]->columns);
3306                    (void) SetImageProperty(msl_info->attributes[n],key,value,
3307                      &exception);
3308                    break;
3309                  }
3310                ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
3311              }
3312              default:
3313              {
3314                ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
3315                break;
3316              }
3317            }
3318          }
3319          break;
3320        }
3321    else if (LocaleCompare((const char *) tag, "group") == 0)
3322    {
3323      msl_info->number_groups++;
3324      msl_info->group_info=(MSLGroupInfo *) ResizeQuantumMemory(
3325        msl_info->group_info,msl_info->number_groups+1UL,
3326        sizeof(*msl_info->group_info));
3327      break;
3328    }
3329      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
3330    }
3331    case 'I':
3332    case 'i':
3333    {
3334      if (LocaleCompare((const char *) tag,"image") == 0)
3335        {
3336          MSLPushImage(msl_info,(Image *) NULL);
3337          if (attributes == (const xmlChar **) NULL)
3338            break;
3339          for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3340          {
3341            keyword=(const char *) attributes[i++];
3342            CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
3343              msl_info->attributes[n],(const char *) attributes[i],&exception));
3344            switch (*keyword)
3345            {
3346              case 'C':
3347              case 'c':
3348              {
3349                if (LocaleCompare(keyword,"color") == 0)
3350                  {
3351                    Image
3352                      *next_image;
3353
3354                    (void) CopyMagickString(msl_info->image_info[n]->filename,
3355                      "xc:",MaxTextExtent);
3356                    (void) ConcatenateMagickString(msl_info->image_info[n]->
3357                      filename,value,MaxTextExtent);
3358                    next_image=ReadImage(msl_info->image_info[n],&exception);
3359                    CatchException(&exception);
3360                    if (next_image == (Image *) NULL)
3361                      continue;
3362                    if (msl_info->image[n] == (Image *) NULL)
3363                      msl_info->image[n]=next_image;
3364                    else
3365                      {
3366                        register Image
3367                          *p;
3368
3369                        /*
3370                          Link image into image list.
3371                        */
3372                        p=msl_info->image[n];
3373                        while (p->next != (Image *) NULL)
3374                          p=GetNextImageInList(p);
3375                        next_image->previous=p;
3376                        p->next=next_image;
3377                      }
3378                    break;
3379                  }
3380                (void) SetMSLAttributes(msl_info,keyword,value);
3381                break;
3382              }
3383              default:
3384              {
3385                (void) SetMSLAttributes(msl_info,keyword,value);
3386                break;
3387              }
3388            }
3389          }
3390          break;
3391        }
3392      if (LocaleCompare((const char *) tag,"implode") == 0)
3393        {
3394          Image
3395            *implode_image;
3396
3397          /*
3398            Implode image.
3399          */
3400          if (msl_info->image[n] == (Image *) NULL)
3401            {
3402              ThrowMSLException(OptionError,"NoImagesDefined",
3403                (const char *) tag);
3404              break;
3405            }
3406          if (attributes != (const xmlChar **) NULL)
3407            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3408            {
3409              keyword=(const char *) attributes[i++];
3410              attribute=InterpretImageProperties(msl_info->image_info[n],
3411                msl_info->attributes[n],(const char *) attributes[i],
3412                &exception);
3413              CloneString(&value,attribute);
3414              switch (*keyword)
3415              {
3416                case 'A':
3417                case 'a':
3418                {
3419                  if (LocaleCompare(keyword,"amount") == 0)
3420                    {
3421                      geometry_info.rho=StringToDouble(value,
3422                        (char **) NULL);
3423                      break;
3424                    }
3425                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3426                    keyword);
3427                  break;
3428                }
3429                case 'G':
3430                case 'g':
3431                {
3432                  if (LocaleCompare(keyword,"geometry") == 0)
3433                    {
3434                      flags=ParseGeometry(value,&geometry_info);
3435                      if ((flags & SigmaValue) == 0)
3436                        geometry_info.sigma=1.0;
3437                      break;
3438                    }
3439                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3440                    keyword);
3441                  break;
3442                }
3443                default:
3444                {
3445                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3446                    keyword);
3447                  break;
3448                }
3449              }
3450            }
3451          implode_image=ImplodeImage(msl_info->image[n],geometry_info.rho,
3452            msl_info->image[n]->interpolate,msl_info->exception);
3453          if (implode_image == (Image *) NULL)
3454            break;
3455          msl_info->image[n]=DestroyImage(msl_info->image[n]);
3456          msl_info->image[n]=implode_image;
3457          break;
3458        }
3459      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
3460    }
3461    case 'L':
3462    case 'l':
3463    {
3464      if (LocaleCompare((const char *) tag,"label") == 0)
3465        break;
3466      if (LocaleCompare((const char *) tag, "level") == 0)
3467      {
3468        double
3469          levelBlack = 0, levelGamma = 1, levelWhite = QuantumRange;
3470
3471        if (msl_info->image[n] == (Image *) NULL)
3472        {
3473          ThrowMSLException(OptionError,"NoImagesDefined",
3474            (const char *) tag);
3475          break;
3476        }
3477        if (attributes == (const xmlChar **) NULL)
3478          break;
3479        for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3480        {
3481          keyword=(const char *) attributes[i++];
3482          CloneString(&value,(const char *) attributes[i]);
3483          (void) CopyMagickString(key,value,MaxTextExtent);
3484          switch (*keyword)
3485          {
3486            case 'B':
3487            case 'b':
3488            {
3489              if (LocaleCompare(keyword,"black") == 0)
3490              {
3491                levelBlack = StringToDouble(value,(char **) NULL);
3492                break;
3493              }
3494              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
3495              break;
3496            }
3497            case 'G':
3498            case 'g':
3499            {
3500              if (LocaleCompare(keyword,"gamma") == 0)
3501              {
3502                levelGamma = StringToDouble(value,(char **) NULL);
3503                break;
3504              }
3505              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
3506              break;
3507            }
3508            case 'W':
3509            case 'w':
3510            {
3511              if (LocaleCompare(keyword,"white") == 0)
3512              {
3513                levelWhite = StringToDouble(value,(char **) NULL);
3514                break;
3515              }
3516              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
3517              break;
3518            }
3519            default:
3520            {
3521              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
3522              break;
3523            }
3524          }
3525        }
3526
3527        /* process image */
3528        LevelImage(msl_info->image[n],levelBlack,levelWhite,levelGamma,
3529          msl_info->exception);
3530        break;
3531      }
3532    }
3533    case 'M':
3534    case 'm':
3535    {
3536      if (LocaleCompare((const char *) tag,"magnify") == 0)
3537        {
3538          Image
3539            *magnify_image;
3540
3541          /*
3542            Magnify image.
3543          */
3544          if (msl_info->image[n] == (Image *) NULL)
3545            {
3546              ThrowMSLException(OptionError,"NoImagesDefined",
3547                (const char *) tag);
3548              break;
3549            }
3550          if (attributes != (const xmlChar **) NULL)
3551            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3552            {
3553              keyword=(const char *) attributes[i++];
3554              attribute=InterpretImageProperties(msl_info->image_info[n],
3555                msl_info->attributes[n],(const char *) attributes[i],
3556                &exception);
3557              CloneString(&value,attribute);
3558              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
3559            }
3560          magnify_image=MagnifyImage(msl_info->image[n],
3561            msl_info->exception);
3562          if (magnify_image == (Image *) NULL)
3563            break;
3564          msl_info->image[n]=DestroyImage(msl_info->image[n]);
3565          msl_info->image[n]=magnify_image;
3566          break;
3567        }
3568      if (LocaleCompare((const char *) tag,"map") == 0)
3569        {
3570          Image
3571            *affinity_image;
3572
3573          MagickBooleanType
3574            dither;
3575
3576          QuantizeInfo
3577            *quantize_info;
3578
3579          /*
3580            Map image.
3581          */
3582          if (msl_info->image[n] == (Image *) NULL)
3583            {
3584              ThrowMSLException(OptionError,"NoImagesDefined",
3585                (const char *) tag);
3586              break;
3587            }
3588          affinity_image=NewImageList();
3589          dither=MagickFalse;
3590          if (attributes != (const xmlChar **) NULL)
3591            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3592            {
3593              keyword=(const char *) attributes[i++];
3594              attribute=InterpretImageProperties(msl_info->image_info[n],
3595                msl_info->attributes[n],(const char *) attributes[i],
3596                &exception);
3597              CloneString(&value,attribute);
3598              switch (*keyword)
3599              {
3600                case 'D':
3601                case 'd':
3602                {
3603                  if (LocaleCompare(keyword,"dither") == 0)
3604                    {
3605                      option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
3606                        value);
3607                      if (option < 0)
3608                        ThrowMSLException(OptionError,"UnrecognizedBooleanType",
3609                          value);
3610                      dither=(MagickBooleanType) option;
3611                      break;
3612                    }
3613                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3614                    keyword);
3615                  break;
3616                }
3617                case 'I':
3618                case 'i':
3619                {
3620                  if (LocaleCompare(keyword,"image") == 0)
3621                    for (j=0; j < msl_info->n; j++)
3622                    {
3623                      const char
3624                        *attribute;
3625
3626                      attribute=GetImageProperty(msl_info->attributes[j],"id",
3627                        &exception);
3628                      if ((attribute != (const char *) NULL)  &&
3629                          (LocaleCompare(attribute,value) == 0))
3630                        {
3631                          affinity_image=CloneImage(msl_info->image[j],0,0,
3632                            MagickFalse,&exception);
3633                          break;
3634                        }
3635                    }
3636                  break;
3637                }
3638                default:
3639                {
3640                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3641                    keyword);
3642                  break;
3643                }
3644              }
3645            }
3646          quantize_info=AcquireQuantizeInfo(msl_info->image_info[n]);
3647          quantize_info->dither_method=dither != MagickFalse ?
3648            RiemersmaDitherMethod : NoDitherMethod;
3649          (void) RemapImages(quantize_info,msl_info->image[n],
3650            affinity_image,&exception);
3651          quantize_info=DestroyQuantizeInfo(quantize_info);
3652          affinity_image=DestroyImage(affinity_image);
3653          break;
3654        }
3655      if (LocaleCompare((const char *) tag,"matte-floodfill") == 0)
3656        {
3657          double
3658            opacity;
3659
3660          PixelInfo
3661            target;
3662
3663          PaintMethod
3664            paint_method;
3665
3666          /*
3667            Matte floodfill image.
3668          */
3669          opacity=0.0;
3670          if (msl_info->image[n] == (Image *) NULL)
3671            {
3672              ThrowMSLException(OptionError,"NoImagesDefined",
3673                (const char *) tag);
3674              break;
3675            }
3676          SetGeometry(msl_info->image[n],&geometry);
3677          paint_method=FloodfillMethod;
3678          if (attributes != (const xmlChar **) NULL)
3679            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3680            {
3681              keyword=(const char *) attributes[i++];
3682              attribute=InterpretImageProperties(msl_info->image_info[n],
3683                msl_info->attributes[n],(const char *) attributes[i],
3684                &exception);
3685              CloneString(&value,attribute);
3686              switch (*keyword)
3687              {
3688                case 'B':
3689                case 'b':
3690                {
3691                  if (LocaleCompare(keyword,"bordercolor") == 0)
3692                    {
3693                      (void) QueryColorCompliance(value,AllCompliance,
3694                        &target,&exception);
3695                      paint_method=FillToBorderMethod;
3696                      break;
3697                    }
3698                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3699                    keyword);
3700                  break;
3701                }
3702                case 'F':
3703                case 'f':
3704                {
3705                  if (LocaleCompare(keyword,"fuzz") == 0)
3706                    {
3707                      msl_info->image[n]->fuzz=StringToDouble(value,
3708                        (char **) NULL);
3709                      break;
3710                    }
3711                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3712                    keyword);
3713                  break;
3714                }
3715                case 'G':
3716                case 'g':
3717                {
3718                  if (LocaleCompare(keyword,"geometry") == 0)
3719                    {
3720                      flags=ParsePageGeometry(msl_info->image[n],value,
3721                        &geometry,&exception);
3722                      if ((flags & HeightValue) == 0)
3723                        geometry.height=geometry.width;
3724                      (void) GetOneVirtualPixelInfo(msl_info->image[n],
3725                        TileVirtualPixelMethod,geometry.x,geometry.y,&target,
3726                        &exception);
3727                      break;
3728                    }
3729                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3730                    keyword);
3731                  break;
3732                }
3733                case 'O':
3734                case 'o':
3735                {
3736                  if (LocaleCompare(keyword,"opacity") == 0)
3737                    {
3738                      opacity=StringToDouble(value,(char **) NULL);
3739                      break;
3740                    }
3741                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3742                    keyword);
3743                  break;
3744                }
3745                case 'X':
3746                case 'x':
3747                {
3748                  if (LocaleCompare(keyword,"x") == 0)
3749                    {
3750                      geometry.x=StringToLong(value);
3751                      (void) GetOneVirtualPixelInfo(msl_info->image[n],
3752                        TileVirtualPixelMethod,geometry.x,geometry.y,&target,
3753                        &exception);
3754                      break;
3755                    }
3756                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3757                    keyword);
3758                  break;
3759                }
3760                case 'Y':
3761                case 'y':
3762                {
3763                  if (LocaleCompare(keyword,"y") == 0)
3764                    {
3765                      geometry.y=StringToLong(value);
3766                      (void) GetOneVirtualPixelInfo(msl_info->image[n],
3767                        TileVirtualPixelMethod,geometry.x,geometry.y,&target,
3768                        &exception);
3769                      break;
3770                    }
3771                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3772                    keyword);
3773                  break;
3774                }
3775                default:
3776                {
3777                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3778                    keyword);
3779                  break;
3780                }
3781              }
3782            }
3783          draw_info=CloneDrawInfo(msl_info->image_info[n],
3784            msl_info->draw_info[n]);
3785          draw_info->fill.alpha=ClampToQuantum(opacity);
3786          channel_mask=SetImageChannelMask(msl_info->image[n],AlphaChannel);
3787          (void) FloodfillPaintImage(msl_info->image[n],draw_info,&target,
3788            geometry.x,geometry.y,paint_method == FloodfillMethod ?
3789            MagickFalse : MagickTrue,msl_info->exception);
3790          (void) SetPixelChannelMask(msl_info->image[n],channel_mask);
3791          draw_info=DestroyDrawInfo(draw_info);
3792          break;
3793        }
3794      if (LocaleCompare((const char *) tag,"median-filter") == 0)
3795        {
3796          Image
3797            *median_image;
3798
3799          /*
3800            Median-filter image.
3801          */
3802          if (msl_info->image[n] == (Image *) NULL)
3803            {
3804              ThrowMSLException(OptionError,"NoImagesDefined",
3805                (const char *) tag);
3806              break;
3807            }
3808          if (attributes != (const xmlChar **) NULL)
3809            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3810            {
3811              keyword=(const char *) attributes[i++];
3812              attribute=InterpretImageProperties(msl_info->image_info[n],
3813                msl_info->attributes[n],(const char *) attributes[i],
3814                &exception);
3815              CloneString(&value,attribute);
3816              switch (*keyword)
3817              {
3818                case 'G':
3819                case 'g':
3820                {
3821                  if (LocaleCompare(keyword,"geometry") == 0)
3822                    {
3823                      flags=ParseGeometry(value,&geometry_info);
3824                      if ((flags & SigmaValue) == 0)
3825                        geometry_info.sigma=1.0;
3826                      break;
3827                    }
3828                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3829                    keyword);
3830                  break;
3831                }
3832                case 'R':
3833                case 'r':
3834                {
3835                  if (LocaleCompare(keyword,"radius") == 0)
3836                    {
3837                      geometry_info.rho=StringToDouble(value,
3838                        (char **) NULL);
3839                      break;
3840                    }
3841                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3842                    keyword);
3843                  break;
3844                }
3845                default:
3846                {
3847                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3848                    keyword);
3849                  break;
3850                }
3851              }
3852            }
3853          median_image=StatisticImage(msl_info->image[n],MedianStatistic,
3854            (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3855            msl_info->exception);
3856          if (median_image == (Image *) NULL)
3857            break;
3858          msl_info->image[n]=DestroyImage(msl_info->image[n]);
3859          msl_info->image[n]=median_image;
3860          break;
3861        }
3862      if (LocaleCompare((const char *) tag,"minify") == 0)
3863        {
3864          Image
3865            *minify_image;
3866
3867          /*
3868            Minify image.
3869          */
3870          if (msl_info->image[n] == (Image *) NULL)
3871            {
3872              ThrowMSLException(OptionError,"NoImagesDefined",
3873                (const char *) tag);
3874              break;
3875            }
3876          if (attributes != (const xmlChar **) NULL)
3877            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3878            {
3879              keyword=(const char *) attributes[i++];
3880              attribute=InterpretImageProperties(msl_info->image_info[n],
3881                msl_info->attributes[n],(const char *) attributes[i],
3882                &exception);
3883              CloneString(&value,attribute);
3884              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
3885            }
3886          minify_image=MinifyImage(msl_info->image[n],
3887            msl_info->exception);
3888          if (minify_image == (Image *) NULL)
3889            break;
3890          msl_info->image[n]=DestroyImage(msl_info->image[n]);
3891          msl_info->image[n]=minify_image;
3892          break;
3893        }
3894      if (LocaleCompare((const char *) tag,"msl") == 0 )
3895        break;
3896      if (LocaleCompare((const char *) tag,"modulate") == 0)
3897        {
3898          char
3899            modulate[MaxTextExtent];
3900
3901          /*
3902            Modulate image.
3903          */
3904          if (msl_info->image[n] == (Image *) NULL)
3905            {
3906              ThrowMSLException(OptionError,"NoImagesDefined",
3907                (const char *) tag);
3908              break;
3909            }
3910          geometry_info.rho=100.0;
3911          geometry_info.sigma=100.0;
3912          geometry_info.xi=100.0;
3913          if (attributes != (const xmlChar **) NULL)
3914            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
3915            {
3916              keyword=(const char *) attributes[i++];
3917              attribute=InterpretImageProperties(msl_info->image_info[n],
3918                msl_info->attributes[n],(const char *) attributes[i],
3919                &exception);
3920              CloneString(&value,attribute);
3921              switch (*keyword)
3922              {
3923                case 'B':
3924                case 'b':
3925                {
3926                  if (LocaleCompare(keyword,"blackness") == 0)
3927                    {
3928                      geometry_info.rho=StringToDouble(value,
3929                        (char **) NULL);
3930                      break;
3931                    }
3932                  if (LocaleCompare(keyword,"brightness") == 0)
3933                    {
3934                      geometry_info.rho=StringToDouble(value,
3935                        (char **) NULL);
3936                      break;
3937                    }
3938                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3939                    keyword);
3940                  break;
3941                }
3942                case 'F':
3943                case 'f':
3944                {
3945                  if (LocaleCompare(keyword,"factor") == 0)
3946                    {
3947                      flags=ParseGeometry(value,&geometry_info);
3948                      break;
3949                    }
3950                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3951                    keyword);
3952                  break;
3953                }
3954                case 'H':
3955                case 'h':
3956                {
3957                  if (LocaleCompare(keyword,"hue") == 0)
3958                    {
3959                      geometry_info.xi=StringToDouble(value,
3960                        (char **) NULL);
3961                      break;
3962                    }
3963                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3964                    keyword);
3965                  break;
3966                }
3967                case 'L':
3968                case 'l':
3969                {
3970                  if (LocaleCompare(keyword,"lightness") == 0)
3971                    {
3972                      geometry_info.rho=StringToDouble(value,
3973                        (char **) NULL);
3974                      break;
3975                    }
3976                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3977                    keyword);
3978                  break;
3979                }
3980                case 'S':
3981                case 's':
3982                {
3983                  if (LocaleCompare(keyword,"saturation") == 0)
3984                    {
3985                      geometry_info.sigma=StringToDouble(value,
3986                        (char **) NULL);
3987                      break;
3988                    }
3989                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
3990                    keyword);
3991                  break;
3992                }
3993                case 'W':
3994                case 'w':
3995                {
3996                  if (LocaleCompare(keyword,"whiteness") == 0)
3997                    {
3998                      geometry_info.sigma=StringToDouble(value,
3999                        (char **) NULL);
4000                      break;
4001                    }
4002                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4003                    keyword);
4004                  break;
4005                }
4006                default:
4007                {
4008                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4009                    keyword);
4010                  break;
4011                }
4012              }
4013            }
4014          (void) FormatLocaleString(modulate,MaxTextExtent,"%g,%g,%g",
4015            geometry_info.rho,geometry_info.sigma,geometry_info.xi);
4016          (void) ModulateImage(msl_info->image[n],modulate,
4017            msl_info->exception);
4018          break;
4019        }
4020      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
4021    }
4022    case 'N':
4023    case 'n':
4024    {
4025      if (LocaleCompare((const char *) tag,"negate") == 0)
4026        {
4027          MagickBooleanType
4028            gray;
4029
4030          /*
4031            Negate image.
4032          */
4033          if (msl_info->image[n] == (Image *) NULL)
4034            {
4035              ThrowMSLException(OptionError,"NoImagesDefined",
4036                (const char *) tag);
4037              break;
4038            }
4039          gray=MagickFalse;
4040          if (attributes != (const xmlChar **) NULL)
4041            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
4042            {
4043              keyword=(const char *) attributes[i++];
4044              attribute=InterpretImageProperties(msl_info->image_info[n],
4045                msl_info->attributes[n],(const char *) attributes[i],
4046                &exception);
4047              CloneString(&value,attribute);
4048              switch (*keyword)
4049              {
4050                case 'C':
4051                case 'c':
4052                {
4053                  if (LocaleCompare(keyword,"channel") == 0)
4054                    {
4055                      option=ParseChannelOption(value);
4056                      if (option < 0)
4057                        ThrowMSLException(OptionError,"UnrecognizedChannelType",
4058                          value);
4059                      channel=(ChannelType) option;
4060                      break;
4061                    }
4062                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4063                    keyword);
4064                  break;
4065                }
4066                case 'G':
4067                case 'g':
4068                {
4069                  if (LocaleCompare(keyword,"gray") == 0)
4070                    {
4071                      option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
4072                        value);
4073                      if (option < 0)
4074                        ThrowMSLException(OptionError,"UnrecognizedBooleanType",
4075                          value);
4076                      gray=(MagickBooleanType) option;
4077                      break;
4078                    }
4079                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4080                    keyword);
4081                  break;
4082                }
4083                default:
4084                {
4085                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4086                    keyword);
4087                  break;
4088                }
4089              }
4090            }
4091          channel_mask=SetImageChannelMask(msl_info->image[n],channel);
4092          (void) NegateImage(msl_info->image[n],gray,
4093            msl_info->exception);
4094          (void) SetPixelChannelMask(msl_info->image[n],channel_mask);
4095          break;
4096        }
4097      if (LocaleCompare((const char *) tag,"normalize") == 0)
4098        {
4099          /*
4100            Normalize image.
4101          */
4102          if (msl_info->image[n] == (Image *) NULL)
4103            {
4104              ThrowMSLException(OptionError,"NoImagesDefined",
4105                (const char *) tag);
4106              break;
4107            }
4108          if (attributes != (const xmlChar **) NULL)
4109            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
4110            {
4111              keyword=(const char *) attributes[i++];
4112              attribute=InterpretImageProperties(msl_info->image_info[n],
4113                msl_info->attributes[n],(const char *) attributes[i],
4114                &exception);
4115              CloneString(&value,attribute);
4116              switch (*keyword)
4117              {
4118                case 'C':
4119                case 'c':
4120                {
4121                  if (LocaleCompare(keyword,"channel") == 0)
4122                    {
4123                      option=ParseChannelOption(value);
4124                      if (option < 0)
4125                        ThrowMSLException(OptionError,"UnrecognizedChannelType",
4126                          value);
4127                      channel=(ChannelType) option;
4128                      break;
4129                    }
4130                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4131                    keyword);
4132                  break;
4133                }
4134                default:
4135                {
4136                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4137                    keyword);
4138                  break;
4139                }
4140              }
4141            }
4142          (void) NormalizeImage(msl_info->image[n],
4143            msl_info->exception);
4144          break;
4145        }
4146      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
4147    }
4148    case 'O':
4149    case 'o':
4150    {
4151      if (LocaleCompare((const char *) tag,"oil-paint") == 0)
4152        {
4153          Image
4154            *paint_image;
4155
4156          /*
4157            Oil-paint image.
4158          */
4159          if (msl_info->image[n] == (Image *) NULL)
4160            {
4161              ThrowMSLException(OptionError,"NoImagesDefined",
4162                (const char *) tag);
4163              break;
4164            }
4165          if (attributes != (const xmlChar **) NULL)
4166            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
4167            {
4168              keyword=(const char *) attributes[i++];
4169              attribute=InterpretImageProperties(msl_info->image_info[n],
4170                msl_info->attributes[n],(const char *) attributes[i],
4171                &exception);
4172              CloneString(&value,attribute);
4173              switch (*keyword)
4174              {
4175                case 'G':
4176                case 'g':
4177                {
4178                  if (LocaleCompare(keyword,"geometry") == 0)
4179                    {
4180                      flags=ParseGeometry(value,&geometry_info);
4181                      if ((flags & SigmaValue) == 0)
4182                        geometry_info.sigma=1.0;
4183                      break;
4184                    }
4185                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4186                    keyword);
4187                  break;
4188                }
4189                case 'R':
4190                case 'r':
4191                {
4192                  if (LocaleCompare(keyword,"radius") == 0)
4193                    {
4194                      geometry_info.rho=StringToDouble(value,
4195                        (char **) NULL);
4196                      break;
4197                    }
4198                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4199                    keyword);
4200                  break;
4201                }
4202                default:
4203                {
4204                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4205                    keyword);
4206                  break;
4207                }
4208              }
4209            }
4210          paint_image=OilPaintImage(msl_info->image[n],geometry_info.rho,
4211            geometry_info.sigma,msl_info->exception);
4212          if (paint_image == (Image *) NULL)
4213            break;
4214          msl_info->image[n]=DestroyImage(msl_info->image[n]);
4215          msl_info->image[n]=paint_image;
4216          break;
4217        }
4218      if (LocaleCompare((const char *) tag,"opaque") == 0)
4219        {
4220          PixelInfo
4221            fill_color,
4222            target;
4223
4224          /*
4225            Opaque image.
4226          */
4227          if (msl_info->image[n] == (Image *) NULL)
4228            {
4229              ThrowMSLException(OptionError,"NoImagesDefined",
4230                (const char *) tag);
4231              break;
4232            }
4233          (void) QueryColorCompliance("none",AllCompliance,&target,
4234            &exception);
4235          (void) QueryColorCompliance("none",AllCompliance,&fill_color,
4236            &exception);
4237          if (attributes != (const xmlChar **) NULL)
4238            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
4239            {
4240              keyword=(const char *) attributes[i++];
4241              attribute=InterpretImageProperties(msl_info->image_info[n],
4242                msl_info->attributes[n],(const char *) attributes[i],
4243                &exception);
4244              CloneString(&value,attribute);
4245              switch (*keyword)
4246              {
4247                case 'C':
4248                case 'c':
4249                {
4250                  if (LocaleCompare(keyword,"channel") == 0)
4251                    {
4252                      option=ParseChannelOption(value);
4253                      if (option < 0)
4254                        ThrowMSLException(OptionError,"UnrecognizedChannelType",
4255                          value);
4256                      channel=(ChannelType) option;
4257                      break;
4258                    }
4259                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4260                    keyword);
4261                  break;
4262                }
4263                case 'F':
4264                case 'f':
4265                {
4266                  if (LocaleCompare(keyword,"fill") == 0)
4267                    {
4268                      (void) QueryColorCompliance(value,AllCompliance,
4269                        &fill_color,&exception);
4270                      break;
4271                    }
4272                  if (LocaleCompare(keyword,"fuzz") == 0)
4273                    {
4274                      msl_info->image[n]->fuzz=StringToDouble(value,
4275                        (char **) NULL);
4276                      break;
4277                    }
4278                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4279                    keyword);
4280                  break;
4281                }
4282                default:
4283                {
4284                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4285                    keyword);
4286                  break;
4287                }
4288              }
4289            }
4290          channel_mask=SetImageChannelMask(msl_info->image[n],channel);
4291          (void) OpaquePaintImage(msl_info->image[n],&target,&fill_color,
4292            MagickFalse,msl_info->exception);
4293          (void) SetPixelChannelMask(msl_info->image[n],channel_mask);
4294          break;
4295        }
4296      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
4297    }
4298    case 'P':
4299    case 'p':
4300    {
4301      if (LocaleCompare((const char *) tag,"print") == 0)
4302        {
4303          if (attributes == (const xmlChar **) NULL)
4304            break;
4305          for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
4306          {
4307            keyword=(const char *) attributes[i++];
4308            attribute=InterpretImageProperties(msl_info->image_info[n],
4309              msl_info->attributes[n],(const char *) attributes[i],
4310              &exception);
4311            CloneString(&value,attribute);
4312            switch (*keyword)
4313            {
4314              case 'O':
4315              case 'o':
4316              {
4317                if (LocaleCompare(keyword,"output") == 0)
4318                  {
4319                    (void) FormatLocaleFile(stdout,"%s",value);
4320                    break;
4321                  }
4322                ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
4323                break;
4324              }
4325              default:
4326              {
4327                ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
4328                break;
4329              }
4330            }
4331          }
4332          break;
4333        }
4334        if (LocaleCompare((const char *) tag, "profile") == 0)
4335          {
4336            if (msl_info->image[n] == (Image *) NULL)
4337              {
4338                ThrowMSLException(OptionError,"NoImagesDefined",
4339                  (const char *) tag);
4340                break;
4341              }
4342            if (attributes == (const xmlChar **) NULL)
4343              break;
4344            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
4345            {
4346              const char
4347                *name;
4348
4349              const StringInfo
4350                *profile;
4351
4352              Image
4353                *profile_image;
4354
4355              ImageInfo
4356                *profile_info;
4357
4358              keyword=(const char *) attributes[i++];
4359              attribute=InterpretImageProperties(msl_info->image_info[n],
4360                msl_info->attributes[n],(const char *) attributes[i],
4361                &exception);
4362              CloneString(&value,attribute);
4363              if (*keyword == '!')
4364                {
4365                  /*
4366                    Remove a profile from the image.
4367                  */
4368                  (void) ProfileImage(msl_info->image[n],keyword,
4369                    (const unsigned char *) NULL,0,&exception);
4370                  continue;
4371                }
4372              /*
4373                Associate a profile with the image.
4374              */
4375              profile_info=CloneImageInfo(msl_info->image_info[n]);
4376              profile=GetImageProfile(msl_info->image[n],"iptc");
4377              if (profile != (StringInfo *) NULL)
4378                profile_info->profile=(void *) CloneStringInfo(profile);
4379              profile_image=GetImageCache(profile_info,keyword,&exception);
4380              profile_info=DestroyImageInfo(profile_info);
4381              if (profile_image == (Image *) NULL)
4382                {
4383                  char
4384                    name[MaxTextExtent],
4385                    filename[MaxTextExtent];
4386
4387                  register char
4388                    *p;
4389
4390                  StringInfo
4391                    *profile;
4392
4393                  (void) CopyMagickString(filename,keyword,MaxTextExtent);
4394                  (void) CopyMagickString(name,keyword,MaxTextExtent);
4395                  for (p=filename; *p != '\0'; p++)
4396                    if ((*p == ':') && (IsPathDirectory(keyword) < 0) &&
4397                        (IsPathAccessible(keyword) == MagickFalse))
4398                      {
4399                        register char
4400                          *q;
4401
4402                        /*
4403                          Look for profile name (e.g. name:profile).
4404                        */
4405                        (void) CopyMagickString(name,filename,(size_t)
4406                          (p-filename+1));
4407                        for (q=filename; *q != '\0'; q++)
4408                          *q=(*++p);
4409                        break;
4410                      }
4411                  profile=FileToStringInfo(filename,~0UL,&exception);
4412                  if (profile != (StringInfo *) NULL)
4413                    {
4414                      (void) ProfileImage(msl_info->image[n],name,
4415                        GetStringInfoDatum(profile),(size_t)
4416                        GetStringInfoLength(profile),&exception);
4417                      profile=DestroyStringInfo(profile);
4418                    }
4419                  continue;
4420                }
4421              ResetImageProfileIterator(profile_image);
4422              name=GetNextImageProfile(profile_image);
4423              while (name != (const char *) NULL)
4424              {
4425                profile=GetImageProfile(profile_image,name);
4426                if (profile != (StringInfo *) NULL)
4427                  (void) ProfileImage(msl_info->image[n],name,
4428                    GetStringInfoDatum(profile),(size_t)
4429                    GetStringInfoLength(profile),&exception);
4430                name=GetNextImageProfile(profile_image);
4431              }
4432              profile_image=DestroyImage(profile_image);
4433            }
4434            break;
4435          }
4436      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
4437    }
4438    case 'Q':
4439    case 'q':
4440    {
4441      if (LocaleCompare((const char *) tag,"quantize") == 0)
4442        {
4443          QuantizeInfo
4444            quantize_info;
4445
4446          /*
4447            Quantize image.
4448          */
4449          if (msl_info->image[n] == (Image *) NULL)
4450            {
4451              ThrowMSLException(OptionError,"NoImagesDefined",
4452                (const char *) tag);
4453              break;
4454            }
4455          GetQuantizeInfo(&quantize_info);
4456          if (attributes != (const xmlChar **) NULL)
4457            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
4458            {
4459              keyword=(const char *) attributes[i++];
4460              attribute=InterpretImageProperties(msl_info->image_info[n],
4461                msl_info->attributes[n],(const char *) attributes[i],
4462                &exception);
4463              CloneString(&value,attribute);
4464              switch (*keyword)
4465              {
4466                case 'C':
4467                case 'c':
4468                {
4469                  if (LocaleCompare(keyword,"colors") == 0)
4470                    {
4471                      quantize_info.number_colors=StringToLong(value);
4472                      break;
4473                    }
4474                  if (LocaleCompare(keyword,"colorspace") == 0)
4475                    {
4476                      option=ParseCommandOption(MagickColorspaceOptions,
4477                        MagickFalse,value);
4478                      if (option < 0)
4479                        ThrowMSLException(OptionError,
4480                          "UnrecognizedColorspaceType",value);
4481                      quantize_info.colorspace=(ColorspaceType) option;
4482                      break;
4483                    }
4484                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4485                    keyword);
4486                  break;
4487                }
4488                case 'D':
4489                case 'd':
4490                {
4491                  if (LocaleCompare(keyword,"dither") == 0)
4492                    {
4493                      option=ParseCommandOption(MagickDitherOptions,MagickFalse,
4494                        value);
4495                      if (option < 0)
4496                        ThrowMSLException(OptionError,"UnrecognizedBooleanType",
4497                          value);
4498                      quantize_info.dither_method=(DitherMethod) option;
4499                      break;
4500                    }
4501                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4502                    keyword);
4503                  break;
4504                }
4505                case 'M':
4506                case 'm':
4507                {
4508                  if (LocaleCompare(keyword,"measure") == 0)
4509                    {
4510                      option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
4511                        value);
4512                      if (option < 0)
4513                        ThrowMSLException(OptionError,"UnrecognizedBooleanType",
4514                          value);
4515                      quantize_info.measure_error=(MagickBooleanType) option;
4516                      break;
4517                    }
4518                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4519                    keyword);
4520                  break;
4521                }
4522                case 'T':
4523                case 't':
4524                {
4525                  if (LocaleCompare(keyword,"treedepth") == 0)
4526                    {
4527                      quantize_info.tree_depth=StringToLong(value);
4528                      break;
4529                    }
4530                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4531                    keyword);
4532                  break;
4533                }
4534                default:
4535                {
4536                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4537                    keyword);
4538                  break;
4539                }
4540              }
4541            }
4542          (void) QuantizeImage(&quantize_info,msl_info->image[n],&exception);
4543          break;
4544        }
4545      if (LocaleCompare((const char *) tag,"query-font-metrics") == 0)
4546        {
4547          char
4548            text[MaxTextExtent];
4549
4550          MagickBooleanType
4551            status;
4552
4553          TypeMetric
4554            metrics;
4555
4556          /*
4557            Query font metrics.
4558          */
4559          draw_info=CloneDrawInfo(msl_info->image_info[n],
4560            msl_info->draw_info[n]);
4561          angle=0.0;
4562          current=draw_info->affine;
4563          GetAffineMatrix(&affine);
4564          if (attributes != (const xmlChar **) NULL)
4565            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
4566            {
4567              keyword=(const char *) attributes[i++];
4568              attribute=InterpretImageProperties(msl_info->image_info[n],
4569                msl_info->attributes[n],(const char *) attributes[i],
4570                &exception);
4571              CloneString(&value,attribute);
4572              switch (*keyword)
4573              {
4574                case 'A':
4575                case 'a':
4576                {
4577                  if (LocaleCompare(keyword,"affine") == 0)
4578                    {
4579                      char
4580                        *p;
4581
4582                      p=value;
4583                      draw_info->affine.sx=StringToDouble(p,&p);
4584                      if (*p ==',')
4585                        p++;
4586                      draw_info->affine.rx=StringToDouble(p,&p);
4587                      if (*p ==',')
4588                        p++;
4589                      draw_info->affine.ry=StringToDouble(p,&p);
4590                      if (*p ==',')
4591                        p++;
4592                      draw_info->affine.sy=StringToDouble(p,&p);
4593                      if (*p ==',')
4594                        p++;
4595                      draw_info->affine.tx=StringToDouble(p,&p);
4596                      if (*p ==',')
4597                        p++;
4598                      draw_info->affine.ty=StringToDouble(p,&p);
4599                      break;
4600                    }
4601                  if (LocaleCompare(keyword,"align") == 0)
4602                    {
4603                      option=ParseCommandOption(MagickAlignOptions,MagickFalse,
4604                        value);
4605                      if (option < 0)
4606                        ThrowMSLException(OptionError,"UnrecognizedAlignType",
4607                          value);
4608                      draw_info->align=(AlignType) option;
4609                      break;
4610                    }
4611                  if (LocaleCompare(keyword,"antialias") == 0)
4612                    {
4613                      option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
4614                        value);
4615                      if (option < 0)
4616                        ThrowMSLException(OptionError,"UnrecognizedBooleanType",
4617                          value);
4618                      draw_info->stroke_antialias=(MagickBooleanType) option;
4619                      draw_info->text_antialias=(MagickBooleanType) option;
4620                      break;
4621                    }
4622                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4623                    keyword);
4624                  break;
4625                }
4626                case 'D':
4627                case 'd':
4628                {
4629                  if (LocaleCompare(keyword,"density") == 0)
4630                    {
4631                      CloneString(&draw_info->density,value);
4632                      break;
4633                    }
4634                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4635                    keyword);
4636                  break;
4637                }
4638                case 'E':
4639                case 'e':
4640                {
4641                  if (LocaleCompare(keyword,"encoding") == 0)
4642                    {
4643                      CloneString(&draw_info->encoding,value);
4644                      break;
4645                    }
4646                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4647                    keyword);
4648                  break;
4649                }
4650                case 'F':
4651                case 'f':
4652                {
4653                  if (LocaleCompare(keyword, "fill") == 0)
4654                    {
4655                      (void) QueryColorCompliance(value,AllCompliance,
4656                        &draw_info->fill,&exception);
4657                      break;
4658                    }
4659                  if (LocaleCompare(keyword,"family") == 0)
4660                    {
4661                      CloneString(&draw_info->family,value);
4662                      break;
4663                    }
4664                  if (LocaleCompare(keyword,"font") == 0)
4665                    {
4666                      CloneString(&draw_info->font,value);
4667                      break;
4668                    }
4669                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4670                    keyword);
4671                  break;
4672                }
4673                case 'G':
4674                case 'g':
4675                {
4676                  if (LocaleCompare(keyword,"geometry") == 0)
4677                    {
4678                      flags=ParsePageGeometry(msl_info->image[n],value,
4679                        &geometry,&exception);
4680                      if ((flags & HeightValue) == 0)
4681                        geometry.height=geometry.width;
4682                      break;
4683                    }
4684                  if (LocaleCompare(keyword,"gravity") == 0)
4685                    {
4686                      option=ParseCommandOption(MagickGravityOptions,MagickFalse,
4687                        value);
4688                      if (option < 0)
4689                        ThrowMSLException(OptionError,"UnrecognizedGravityType",
4690                          value);
4691                      draw_info->gravity=(GravityType) option;
4692                      break;
4693                    }
4694                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4695                    keyword);
4696                  break;
4697                }
4698                case 'P':
4699                case 'p':
4700                {
4701                  if (LocaleCompare(keyword,"pointsize") == 0)
4702                    {
4703                      draw_info->pointsize=StringToDouble(value,
4704                        (char **) NULL);
4705                      break;
4706                    }
4707                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4708                    keyword);
4709                  break;
4710                }
4711                case 'R':
4712                case 'r':
4713                {
4714                  if (LocaleCompare(keyword,"rotate") == 0)
4715                    {
4716                      angle=StringToDouble(value,(char **) NULL);
4717                      affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
4718                      affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
4719                      affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
4720                      affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
4721                      break;
4722                    }
4723                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4724                    keyword);
4725                  break;
4726                }
4727                case 'S':
4728                case 's':
4729                {
4730                  if (LocaleCompare(keyword,"scale") == 0)
4731                    {
4732                      flags=ParseGeometry(value,&geometry_info);
4733                      if ((flags & SigmaValue) == 0)
4734                        geometry_info.sigma=1.0;
4735                      affine.sx=geometry_info.rho;
4736                      affine.sy=geometry_info.sigma;
4737                      break;
4738                    }
4739                  if (LocaleCompare(keyword,"skewX") == 0)
4740                    {
4741                      angle=StringToDouble(value,(char **) NULL);
4742                      affine.ry=cos(DegreesToRadians(fmod(angle,360.0)));
4743                      break;
4744                    }
4745                  if (LocaleCompare(keyword,"skewY") == 0)
4746                    {
4747                      angle=StringToDouble(value,(char **) NULL);
4748                      affine.rx=cos(DegreesToRadians(fmod(angle,360.0)));
4749                      break;
4750                    }
4751                  if (LocaleCompare(keyword,"stretch") == 0)
4752                    {
4753                      option=ParseCommandOption(MagickStretchOptions,
4754                        MagickFalse,value);
4755                      if (option < 0)
4756                        ThrowMSLException(OptionError,"UnrecognizedStretchType",
4757                          value);
4758                      draw_info->stretch=(StretchType) option;
4759                      break;
4760                    }
4761                  if (LocaleCompare(keyword, "stroke") == 0)
4762                    {
4763                      (void) QueryColorCompliance(value,AllCompliance,
4764                        &draw_info->stroke,&exception);
4765                      break;
4766                    }
4767                  if (LocaleCompare(keyword,"strokewidth") == 0)
4768                    {
4769                      draw_info->stroke_width=StringToLong(value);
4770                      break;
4771                    }
4772                  if (LocaleCompare(keyword,"style") == 0)
4773                    {
4774                      option=ParseCommandOption(MagickStyleOptions,MagickFalse,
4775                        value);
4776                      if (option < 0)
4777                        ThrowMSLException(OptionError,"UnrecognizedStyleType",
4778                          value);
4779                      draw_info->style=(StyleType) option;
4780                      break;
4781                    }
4782                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4783                    keyword);
4784                  break;
4785                }
4786                case 'T':
4787                case 't':
4788                {
4789                  if (LocaleCompare(keyword,"text") == 0)
4790                    {
4791                      CloneString(&draw_info->text,value);
4792                      break;
4793                    }
4794                  if (LocaleCompare(keyword,"translate") == 0)
4795                    {
4796                      flags=ParseGeometry(value,&geometry_info);
4797                      if ((flags & SigmaValue) == 0)
4798                        geometry_info.sigma=1.0;
4799                      affine.tx=geometry_info.rho;
4800                      affine.ty=geometry_info.sigma;
4801                      break;
4802                    }
4803                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4804                    keyword);
4805                  break;
4806                }
4807                case 'U':
4808                case 'u':
4809                {
4810                  if (LocaleCompare(keyword, "undercolor") == 0)
4811                    {
4812                      (void) QueryColorCompliance(value,AllCompliance,
4813                        &draw_info->undercolor,&exception);
4814                      break;
4815                    }
4816                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4817                    keyword);
4818                  break;
4819                }
4820                case 'W':
4821                case 'w':
4822                {
4823                  if (LocaleCompare(keyword,"weight") == 0)
4824                    {
4825                      draw_info->weight=StringToLong(value);
4826                      break;
4827                    }
4828                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4829                    keyword);
4830                  break;
4831                }
4832                case 'X':
4833                case 'x':
4834                {
4835                  if (LocaleCompare(keyword,"x") == 0)
4836                    {
4837                      geometry.x=StringToLong(value);
4838                      break;
4839                    }
4840                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4841                    keyword);
4842                  break;
4843                }
4844                case 'Y':
4845                case 'y':
4846                {
4847                  if (LocaleCompare(keyword,"y") == 0)
4848                    {
4849                      geometry.y=StringToLong(value);
4850                      break;
4851                    }
4852                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4853                    keyword);
4854                  break;
4855                }
4856                default:
4857                {
4858                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4859                    keyword);
4860                  break;
4861                }
4862              }
4863            }
4864          (void) FormatLocaleString(text,MaxTextExtent,
4865            "%.20gx%.20g%+.20g%+.20g",(double) geometry.width,(double)
4866            geometry.height,(double) geometry.x,(double) geometry.y);
4867          CloneString(&draw_info->geometry,text);
4868          draw_info->affine.sx=affine.sx*current.sx+affine.ry*current.rx;
4869          draw_info->affine.rx=affine.rx*current.sx+affine.sy*current.rx;
4870          draw_info->affine.ry=affine.sx*current.ry+affine.ry*current.sy;
4871          draw_info->affine.sy=affine.rx*current.ry+affine.sy*current.sy;
4872          draw_info->affine.tx=affine.sx*current.tx+affine.ry*current.ty+
4873            affine.tx;
4874          draw_info->affine.ty=affine.rx*current.tx+affine.sy*current.ty+
4875            affine.ty;
4876          status=GetTypeMetrics(msl_info->attributes[n],draw_info,&metrics,
4877            msl_info->exception);
4878          if (status != MagickFalse)
4879            {
4880              Image
4881                *image;
4882
4883              image=msl_info->attributes[n];
4884              FormatImageProperty(image,"msl:font-metrics.pixels_per_em.x",
4885                "%g",metrics.pixels_per_em.x);
4886              FormatImageProperty(image,"msl:font-metrics.pixels_per_em.y",
4887                "%g",metrics.pixels_per_em.y);
4888              FormatImageProperty(image,"msl:font-metrics.ascent","%g",
4889                metrics.ascent);
4890              FormatImageProperty(image,"msl:font-metrics.descent","%g",
4891                metrics.descent);
4892              FormatImageProperty(image,"msl:font-metrics.width","%g",
4893                metrics.width);
4894              FormatImageProperty(image,"msl:font-metrics.height","%g",
4895                metrics.height);
4896              FormatImageProperty(image,"msl:font-metrics.max_advance","%g",
4897                metrics.max_advance);
4898              FormatImageProperty(image,"msl:font-metrics.bounds.x1","%g",
4899                metrics.bounds.x1);
4900              FormatImageProperty(image,"msl:font-metrics.bounds.y1","%g",
4901                metrics.bounds.y1);
4902              FormatImageProperty(image,"msl:font-metrics.bounds.x2","%g",
4903                metrics.bounds.x2);
4904              FormatImageProperty(image,"msl:font-metrics.bounds.y2","%g",
4905                metrics.bounds.y2);
4906              FormatImageProperty(image,"msl:font-metrics.origin.x","%g",
4907                metrics.origin.x);
4908              FormatImageProperty(image,"msl:font-metrics.origin.y","%g",
4909                metrics.origin.y);
4910            }
4911          draw_info=DestroyDrawInfo(draw_info);
4912          break;
4913        }
4914      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
4915    }
4916    case 'R':
4917    case 'r':
4918    {
4919      if (LocaleCompare((const char *) tag,"raise") == 0)
4920        {
4921          MagickBooleanType
4922            raise;
4923
4924          /*
4925            Raise image.
4926          */
4927          if (msl_info->image[n] == (Image *) NULL)
4928            {
4929              ThrowMSLException(OptionError,"NoImagesDefined",
4930                (const char *) tag);
4931              break;
4932            }
4933          raise=MagickFalse;
4934          SetGeometry(msl_info->image[n],&geometry);
4935          if (attributes != (const xmlChar **) NULL)
4936            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
4937            {
4938              keyword=(const char *) attributes[i++];
4939              attribute=InterpretImageProperties(msl_info->image_info[n],
4940                msl_info->attributes[n],(const char *) attributes[i],
4941                &exception);
4942              CloneString(&value,attribute);
4943              switch (*keyword)
4944              {
4945                case 'G':
4946                case 'g':
4947                {
4948                  if (LocaleCompare(keyword,"geometry") == 0)
4949                    {
4950                      flags=ParsePageGeometry(msl_info->image[n],value,
4951                        &geometry,&exception);
4952                      if ((flags & HeightValue) == 0)
4953                        geometry.height=geometry.width;
4954                      break;
4955                    }
4956                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4957                    keyword);
4958                  break;
4959                }
4960                case 'H':
4961                case 'h':
4962                {
4963                  if (LocaleCompare(keyword,"height") == 0)
4964                    {
4965                      geometry.height=StringToLong(value);
4966                      break;
4967                    }
4968                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4969                    keyword);
4970                  break;
4971                }
4972                case 'R':
4973                case 'r':
4974                {
4975                  if (LocaleCompare(keyword,"raise") == 0)
4976                    {
4977                      option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
4978                        value);
4979                      if (option < 0)
4980                        ThrowMSLException(OptionError,"UnrecognizedNoiseType",
4981                          value);
4982                      raise=(MagickBooleanType) option;
4983                      break;
4984                    }
4985                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4986                    keyword);
4987                  break;
4988                }
4989                case 'W':
4990                case 'w':
4991                {
4992                  if (LocaleCompare(keyword,"width") == 0)
4993                    {
4994                      geometry.width=StringToLong(value);
4995                      break;
4996                    }
4997                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
4998                    keyword);
4999                  break;
5000                }
5001                default:
5002                {
5003                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5004                    keyword);
5005                  break;
5006                }
5007              }
5008            }
5009          (void) RaiseImage(msl_info->image[n],&geometry,raise,
5010            msl_info->exception);
5011          break;
5012        }
5013      if (LocaleCompare((const char *) tag,"read") == 0)
5014        {
5015          if (attributes == (const xmlChar **) NULL)
5016            break;
5017          for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5018          {
5019            keyword=(const char *) attributes[i++];
5020            CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
5021              msl_info->attributes[n],(const char *) attributes[i],&exception));
5022            switch (*keyword)
5023            {
5024              case 'F':
5025              case 'f':
5026              {
5027                if (LocaleCompare(keyword,"filename") == 0)
5028                  {
5029                    Image
5030                      *image;
5031
5032                    (void) CopyMagickString(msl_info->image_info[n]->filename,
5033                      value,MaxTextExtent);
5034                    image=ReadImage(msl_info->image_info[n],&exception);
5035                    CatchException(&exception);
5036                    if (image == (Image *) NULL)
5037                      continue;
5038                    AppendImageToList(&msl_info->image[n],image);
5039                    break;
5040                  }
5041                (void) SetMSLAttributes(msl_info,keyword,value);
5042                break;
5043              }
5044              default:
5045              {
5046                (void) SetMSLAttributes(msl_info,keyword,value);
5047                break;
5048              }
5049            }
5050          }
5051          break;
5052        }
5053      if (LocaleCompare((const char *) tag,"reduce-noise") == 0)
5054        {
5055          Image
5056            *paint_image;
5057
5058          /*
5059            Reduce-noise image.
5060          */
5061          if (msl_info->image[n] == (Image *) NULL)
5062            {
5063              ThrowMSLException(OptionError,"NoImagesDefined",
5064                (const char *) tag);
5065              break;
5066            }
5067          if (attributes != (const xmlChar **) NULL)
5068            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5069            {
5070              keyword=(const char *) attributes[i++];
5071              attribute=InterpretImageProperties(msl_info->image_info[n],
5072                msl_info->attributes[n],(const char *) attributes[i],
5073                &exception);
5074              CloneString(&value,attribute);
5075              switch (*keyword)
5076              {
5077                case 'G':
5078                case 'g':
5079                {
5080                  if (LocaleCompare(keyword,"geometry") == 0)
5081                    {
5082                      flags=ParseGeometry(value,&geometry_info);
5083                      if ((flags & SigmaValue) == 0)
5084                        geometry_info.sigma=1.0;
5085                      break;
5086                    }
5087                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5088                    keyword);
5089                  break;
5090                }
5091                case 'R':
5092                case 'r':
5093                {
5094                  if (LocaleCompare(keyword,"radius") == 0)
5095                    {
5096                      geometry_info.rho=StringToDouble(value,
5097                        (char **) NULL);
5098                      break;
5099                    }
5100                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5101                    keyword);
5102                  break;
5103                }
5104                default:
5105                {
5106                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5107                    keyword);
5108                  break;
5109                }
5110              }
5111            }
5112          paint_image=StatisticImage(msl_info->image[n],NonpeakStatistic,
5113            (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
5114            msl_info->exception);
5115          if (paint_image == (Image *) NULL)
5116            break;
5117          msl_info->image[n]=DestroyImage(msl_info->image[n]);
5118          msl_info->image[n]=paint_image;
5119          break;
5120        }
5121      else if (LocaleCompare((const char *) tag,"repage") == 0)
5122      {
5123        /* init the values */
5124        width=msl_info->image[n]->page.width;
5125        height=msl_info->image[n]->page.height;
5126        x=msl_info->image[n]->page.x;
5127        y=msl_info->image[n]->page.y;
5128
5129        if (msl_info->image[n] == (Image *) NULL)
5130        {
5131          ThrowMSLException(OptionError,"NoImagesDefined",
5132            (const char *) tag);
5133          break;
5134        }
5135        if (attributes == (const xmlChar **) NULL)
5136        break;
5137        for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5138        {
5139        keyword=(const char *) attributes[i++];
5140        CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
5141          msl_info->attributes[n],(const char *) attributes[i],&exception));
5142        switch (*keyword)
5143        {
5144          case 'G':
5145          case 'g':
5146          {
5147          if (LocaleCompare(keyword,"geometry") == 0)
5148            {
5149              int
5150                flags;
5151
5152              RectangleInfo
5153                geometry;
5154
5155            flags=ParseAbsoluteGeometry(value,&geometry);
5156            if ((flags & WidthValue) != 0)
5157              {
5158                if ((flags & HeightValue) == 0)
5159                  geometry.height=geometry.width;
5160                width=geometry.width;
5161                height=geometry.height;
5162              }
5163            if ((flags & AspectValue) != 0)
5164              {
5165                if ((flags & XValue) != 0)
5166                  x+=geometry.x;
5167                if ((flags & YValue) != 0)
5168                  y+=geometry.y;
5169              }
5170            else
5171              {
5172                if ((flags & XValue) != 0)
5173                  {
5174                    x=geometry.x;
5175                    if ((width == 0) && (geometry.x > 0))
5176                      width=msl_info->image[n]->columns+geometry.x;
5177                  }
5178                if ((flags & YValue) != 0)
5179                  {
5180                    y=geometry.y;
5181                    if ((height == 0) && (geometry.y > 0))
5182                      height=msl_info->image[n]->rows+geometry.y;
5183                  }
5184              }
5185            break;
5186            }
5187          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5188          break;
5189          }
5190          case 'H':
5191          case 'h':
5192          {
5193          if (LocaleCompare(keyword,"height") == 0)
5194            {
5195            height = StringToLong( value );
5196            break;
5197            }
5198          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5199          break;
5200          }
5201          case 'W':
5202          case 'w':
5203          {
5204          if (LocaleCompare(keyword,"width") == 0)
5205            {
5206            width = StringToLong( value );
5207            break;
5208            }
5209          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5210          break;
5211          }
5212          case 'X':
5213          case 'x':
5214          {
5215          if (LocaleCompare(keyword,"x") == 0)
5216            {
5217            x = StringToLong( value );
5218            break;
5219            }
5220          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5221          break;
5222          }
5223          case 'Y':
5224          case 'y':
5225          {
5226          if (LocaleCompare(keyword,"y") == 0)
5227            {
5228            y = StringToLong( value );
5229            break;
5230            }
5231          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5232          break;
5233          }
5234          default:
5235          {
5236          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5237          break;
5238          }
5239        }
5240        }
5241
5242         msl_info->image[n]->page.width=width;
5243         msl_info->image[n]->page.height=height;
5244         msl_info->image[n]->page.x=x;
5245         msl_info->image[n]->page.y=y;
5246        break;
5247      }
5248    else if (LocaleCompare((const char *) tag,"resample") == 0)
5249    {
5250      double
5251        x_resolution,
5252        y_resolution;
5253
5254      if (msl_info->image[n] == (Image *) NULL)
5255        {
5256          ThrowMSLException(OptionError,"NoImagesDefined",
5257            (const char *) tag);
5258          break;
5259        }
5260      if (attributes == (const xmlChar **) NULL)
5261        break;
5262      x_resolution=DefaultResolution;
5263      y_resolution=DefaultResolution;
5264      for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5265      {
5266        keyword=(const char *) attributes[i++];
5267        CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
5268          msl_info->attributes[n],(const char *) attributes[i],&exception));
5269        switch (*keyword)
5270        {
5271          case 'G':
5272          case 'g':
5273          {
5274            if (LocaleCompare(keyword,"geometry") == 0)
5275              {
5276                ssize_t
5277                  flags;
5278
5279                flags=ParseGeometry(value,&geometry_info);
5280                if ((flags & SigmaValue) == 0)
5281                  geometry_info.sigma*=geometry_info.rho;
5282                x_resolution=geometry_info.rho;
5283                y_resolution=geometry_info.sigma;
5284                break;
5285              }
5286            ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5287            break;
5288          }
5289          case 'X':
5290          case 'x':
5291          {
5292            if (LocaleCompare(keyword,"x-resolution") == 0)
5293              {
5294                x_resolution=StringToDouble(value,(char **) NULL);
5295                break;
5296              }
5297            ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5298            break;
5299          }
5300          case 'Y':
5301          case 'y':
5302          {
5303            if (LocaleCompare(keyword,"y-resolution") == 0)
5304              {
5305                y_resolution=StringToDouble(value,(char **) NULL);
5306                break;
5307              }
5308            ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5309            break;
5310          }
5311          default:
5312          {
5313            ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5314            break;
5315          }
5316        }
5317      }
5318      /*
5319        Resample image.
5320      */
5321      {
5322        double
5323          factor;
5324
5325        Image
5326          *resample_image;
5327
5328        factor=1.0;
5329        if (msl_info->image[n]->units == PixelsPerCentimeterResolution)
5330          factor=2.54;
5331        width=(size_t) (x_resolution*msl_info->image[n]->columns/
5332          (factor*(msl_info->image[n]->resolution.x == 0.0 ? DefaultResolution :
5333          msl_info->image[n]->resolution.x))+0.5);
5334        height=(size_t) (y_resolution*msl_info->image[n]->rows/
5335          (factor*(msl_info->image[n]->resolution.y == 0.0 ? DefaultResolution :
5336          msl_info->image[n]->resolution.y))+0.5);
5337        resample_image=ResizeImage(msl_info->image[n],width,height,
5338          msl_info->image[n]->filter,msl_info->exception);
5339        if (resample_image == (Image *) NULL)
5340          break;
5341        msl_info->image[n]=DestroyImage(msl_info->image[n]);
5342        msl_info->image[n]=resample_image;
5343      }
5344      break;
5345    }
5346      if (LocaleCompare((const char *) tag,"resize") == 0)
5347        {
5348          FilterTypes
5349            filter;
5350
5351          Image
5352            *resize_image;
5353
5354          /*
5355            Resize image.
5356          */
5357          if (msl_info->image[n] == (Image *) NULL)
5358            {
5359              ThrowMSLException(OptionError,"NoImagesDefined",
5360                (const char *) tag);
5361              break;
5362            }
5363          filter=UndefinedFilter;
5364          if (attributes != (const xmlChar **) NULL)
5365            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5366            {
5367              keyword=(const char *) attributes[i++];
5368              attribute=InterpretImageProperties(msl_info->image_info[n],
5369                msl_info->attributes[n],(const char *) attributes[i],
5370                &exception);
5371              CloneString(&value,attribute);
5372              switch (*keyword)
5373              {
5374                case 'F':
5375                case 'f':
5376                {
5377                  if (LocaleCompare(keyword,"filter") == 0)
5378                    {
5379                      option=ParseCommandOption(MagickFilterOptions,MagickFalse,
5380                        value);
5381                      if (option < 0)
5382                        ThrowMSLException(OptionError,"UnrecognizedNoiseType",
5383                          value);
5384                      filter=(FilterTypes) option;
5385                      break;
5386                    }
5387                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5388                    keyword);
5389                  break;
5390                }
5391                case 'G':
5392                case 'g':
5393                {
5394                  if (LocaleCompare(keyword,"geometry") == 0)
5395                    {
5396                      flags=ParseRegionGeometry(msl_info->image[n],value,
5397                        &geometry,&exception);
5398                      break;
5399                    }
5400                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5401                    keyword);
5402                  break;
5403                }
5404                case 'H':
5405                case 'h':
5406                {
5407                  if (LocaleCompare(keyword,"height") == 0)
5408                    {
5409                      geometry.height=StringToUnsignedLong(value);
5410                      break;
5411                    }
5412                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5413                    keyword);
5414                  break;
5415                }
5416                case 'W':
5417                case 'w':
5418                {
5419                  if (LocaleCompare(keyword,"width") == 0)
5420                    {
5421                      geometry.width=StringToLong(value);
5422                      break;
5423                    }
5424                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5425                    keyword);
5426                  break;
5427                }
5428                default:
5429                {
5430                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5431                    keyword);
5432                  break;
5433                }
5434              }
5435            }
5436          resize_image=ResizeImage(msl_info->image[n],geometry.width,
5437            geometry.height,filter,msl_info->exception);
5438          if (resize_image == (Image *) NULL)
5439            break;
5440          msl_info->image[n]=DestroyImage(msl_info->image[n]);
5441          msl_info->image[n]=resize_image;
5442          break;
5443        }
5444      if (LocaleCompare((const char *) tag,"roll") == 0)
5445        {
5446          Image
5447            *roll_image;
5448
5449          /*
5450            Roll image.
5451          */
5452          if (msl_info->image[n] == (Image *) NULL)
5453            {
5454              ThrowMSLException(OptionError,"NoImagesDefined",
5455                (const char *) tag);
5456              break;
5457            }
5458          SetGeometry(msl_info->image[n],&geometry);
5459          if (attributes != (const xmlChar **) NULL)
5460            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5461            {
5462              keyword=(const char *) attributes[i++];
5463              attribute=InterpretImageProperties(msl_info->image_info[n],
5464                msl_info->attributes[n],(const char *) attributes[i],
5465                &exception);
5466              CloneString(&value,attribute);
5467              switch (*keyword)
5468              {
5469                case 'G':
5470                case 'g':
5471                {
5472                  if (LocaleCompare(keyword,"geometry") == 0)
5473                    {
5474                      flags=ParsePageGeometry(msl_info->image[n],value,
5475                        &geometry,&exception);
5476                      if ((flags & HeightValue) == 0)
5477                        geometry.height=geometry.width;
5478                      break;
5479                    }
5480                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5481                    keyword);
5482                  break;
5483                }
5484                case 'X':
5485                case 'x':
5486                {
5487                  if (LocaleCompare(keyword,"x") == 0)
5488                    {
5489                      geometry.x=StringToLong(value);
5490                      break;
5491                    }
5492                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5493                    keyword);
5494                  break;
5495                }
5496                case 'Y':
5497                case 'y':
5498                {
5499                  if (LocaleCompare(keyword,"y") == 0)
5500                    {
5501                      geometry.y=StringToLong(value);
5502                      break;
5503                    }
5504                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5505                    keyword);
5506                  break;
5507                }
5508                default:
5509                {
5510                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5511                    keyword);
5512                  break;
5513                }
5514              }
5515            }
5516          roll_image=RollImage(msl_info->image[n],geometry.x,geometry.y,
5517            msl_info->exception);
5518          if (roll_image == (Image *) NULL)
5519            break;
5520          msl_info->image[n]=DestroyImage(msl_info->image[n]);
5521          msl_info->image[n]=roll_image;
5522          break;
5523        }
5524      else if (LocaleCompare((const char *) tag,"roll") == 0)
5525      {
5526        /* init the values */
5527        width=msl_info->image[n]->columns;
5528        height=msl_info->image[n]->rows;
5529        x = y = 0;
5530
5531        if (msl_info->image[n] == (Image *) NULL)
5532        {
5533          ThrowMSLException(OptionError,"NoImagesDefined",
5534            (const char *) tag);
5535          break;
5536        }
5537        if (attributes == (const xmlChar **) NULL)
5538        break;
5539        for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5540        {
5541        keyword=(const char *) attributes[i++];
5542        CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
5543          msl_info->attributes[n],(const char *) attributes[i],&exception));
5544        switch (*keyword)
5545        {
5546          case 'G':
5547          case 'g':
5548          {
5549          if (LocaleCompare(keyword,"geometry") == 0)
5550            {
5551            (void) ParseMetaGeometry(value,&x,&y,&width,&height);
5552            break;
5553            }
5554          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5555          break;
5556          }
5557          case 'X':
5558          case 'x':
5559          {
5560          if (LocaleCompare(keyword,"x") == 0)
5561            {
5562            x = StringToLong( value );
5563            break;
5564            }
5565          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5566          break;
5567          }
5568          case 'Y':
5569          case 'y':
5570          {
5571          if (LocaleCompare(keyword,"y") == 0)
5572            {
5573            y = StringToLong( value );
5574            break;
5575            }
5576          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5577          break;
5578          }
5579          default:
5580          {
5581          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5582          break;
5583          }
5584        }
5585        }
5586
5587        /*
5588          process image.
5589        */
5590        {
5591        Image
5592          *newImage;
5593
5594        newImage=RollImage(msl_info->image[n], x, y, msl_info->exception);
5595        if (newImage == (Image *) NULL)
5596          break;
5597        msl_info->image[n]=DestroyImage(msl_info->image[n]);
5598        msl_info->image[n]=newImage;
5599        }
5600
5601        break;
5602      }
5603      if (LocaleCompare((const char *) tag,"rotate") == 0)
5604        {
5605          Image
5606            *rotate_image;
5607
5608          /*
5609            Rotate image.
5610          */
5611          if (msl_info->image[n] == (Image *) NULL)
5612            {
5613              ThrowMSLException(OptionError,"NoImagesDefined",
5614                (const char *) tag);
5615              break;
5616            }
5617          if (attributes != (const xmlChar **) NULL)
5618            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5619            {
5620              keyword=(const char *) attributes[i++];
5621              attribute=InterpretImageProperties(msl_info->image_info[n],
5622                msl_info->attributes[n],(const char *) attributes[i],
5623                &exception);
5624              CloneString(&value,attribute);
5625              switch (*keyword)
5626              {
5627                case 'D':
5628                case 'd':
5629                {
5630                  if (LocaleCompare(keyword,"degrees") == 0)
5631                    {
5632                      geometry_info.rho=StringToDouble(value,
5633                        (char **) NULL);
5634                      break;
5635                    }
5636                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5637                    keyword);
5638                  break;
5639                }
5640                case 'G':
5641                case 'g':
5642                {
5643                  if (LocaleCompare(keyword,"geometry") == 0)
5644                    {
5645                      flags=ParseGeometry(value,&geometry_info);
5646                      if ((flags & SigmaValue) == 0)
5647                        geometry_info.sigma=1.0;
5648                      break;
5649                    }
5650                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5651                    keyword);
5652                  break;
5653                }
5654                default:
5655                {
5656                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5657                    keyword);
5658                  break;
5659                }
5660              }
5661            }
5662          rotate_image=RotateImage(msl_info->image[n],geometry_info.rho,
5663            msl_info->exception);
5664          if (rotate_image == (Image *) NULL)
5665            break;
5666          msl_info->image[n]=DestroyImage(msl_info->image[n]);
5667          msl_info->image[n]=rotate_image;
5668          break;
5669        }
5670      else if (LocaleCompare((const char *) tag,"rotate") == 0)
5671      {
5672        /* init the values */
5673        double  degrees = 0;
5674
5675        if (msl_info->image[n] == (Image *) NULL)
5676        {
5677          ThrowMSLException(OptionError,"NoImagesDefined",
5678            (const char *) tag);
5679          break;
5680        }
5681        if (attributes == (const xmlChar **) NULL)
5682          break;
5683        for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5684        {
5685        keyword=(const char *) attributes[i++];
5686        CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
5687          msl_info->attributes[n],(const char *) attributes[i],&exception));
5688        switch (*keyword)
5689        {
5690          case 'D':
5691          case 'd':
5692          {
5693          if (LocaleCompare(keyword,"degrees") == 0)
5694            {
5695            degrees = StringToDouble(value,(char **) NULL);
5696            break;
5697            }
5698          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5699          break;
5700          }
5701          default:
5702          {
5703          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
5704          break;
5705          }
5706        }
5707        }
5708
5709        /*
5710          process image.
5711        */
5712        {
5713        Image
5714          *newImage;
5715
5716        newImage=RotateImage(msl_info->image[n], degrees, msl_info->exception);
5717        if (newImage == (Image *) NULL)
5718          break;
5719        msl_info->image[n]=DestroyImage(msl_info->image[n]);
5720        msl_info->image[n]=newImage;
5721        }
5722
5723        break;
5724      }
5725      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
5726    }
5727    case 'S':
5728    case 's':
5729    {
5730      if (LocaleCompare((const char *) tag,"sample") == 0)
5731        {
5732          Image
5733            *sample_image;
5734
5735          /*
5736            Sample image.
5737          */
5738          if (msl_info->image[n] == (Image *) NULL)
5739            {
5740              ThrowMSLException(OptionError,"NoImagesDefined",
5741                (const char *) tag);
5742              break;
5743            }
5744          if (attributes != (const xmlChar **) NULL)
5745            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5746            {
5747              keyword=(const char *) attributes[i++];
5748              attribute=InterpretImageProperties(msl_info->image_info[n],
5749                msl_info->attributes[n],(const char *) attributes[i],
5750                &exception);
5751              CloneString(&value,attribute);
5752              switch (*keyword)
5753              {
5754                case 'G':
5755                case 'g':
5756                {
5757                  if (LocaleCompare(keyword,"geometry") == 0)
5758                    {
5759                      flags=ParseRegionGeometry(msl_info->image[n],value,
5760                        &geometry,&exception);
5761                      break;
5762                    }
5763                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5764                    keyword);
5765                  break;
5766                }
5767                case 'H':
5768                case 'h':
5769                {
5770                  if (LocaleCompare(keyword,"height") == 0)
5771                    {
5772                      geometry.height=StringToUnsignedLong(value);
5773                      break;
5774                    }
5775                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5776                    keyword);
5777                  break;
5778                }
5779                case 'W':
5780                case 'w':
5781                {
5782                  if (LocaleCompare(keyword,"width") == 0)
5783                    {
5784                      geometry.width=StringToLong(value);
5785                      break;
5786                    }
5787                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5788                    keyword);
5789                  break;
5790                }
5791                default:
5792                {
5793                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5794                    keyword);
5795                  break;
5796                }
5797              }
5798            }
5799          sample_image=SampleImage(msl_info->image[n],geometry.width,
5800            geometry.height,msl_info->exception);
5801          if (sample_image == (Image *) NULL)
5802            break;
5803          msl_info->image[n]=DestroyImage(msl_info->image[n]);
5804          msl_info->image[n]=sample_image;
5805          break;
5806        }
5807      if (LocaleCompare((const char *) tag,"scale") == 0)
5808        {
5809          Image
5810            *scale_image;
5811
5812          /*
5813            Scale image.
5814          */
5815          if (msl_info->image[n] == (Image *) NULL)
5816            {
5817              ThrowMSLException(OptionError,"NoImagesDefined",
5818                (const char *) tag);
5819              break;
5820            }
5821          if (attributes != (const xmlChar **) NULL)
5822            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5823            {
5824              keyword=(const char *) attributes[i++];
5825              attribute=InterpretImageProperties(msl_info->image_info[n],
5826                msl_info->attributes[n],(const char *) attributes[i],
5827                &exception);
5828              CloneString(&value,attribute);
5829              switch (*keyword)
5830              {
5831                case 'G':
5832                case 'g':
5833                {
5834                  if (LocaleCompare(keyword,"geometry") == 0)
5835                    {
5836                      flags=ParseRegionGeometry(msl_info->image[n],value,
5837                        &geometry,&exception);
5838                      break;
5839                    }
5840                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5841                    keyword);
5842                  break;
5843                }
5844                case 'H':
5845                case 'h':
5846                {
5847                  if (LocaleCompare(keyword,"height") == 0)
5848                    {
5849                      geometry.height=StringToUnsignedLong(value);
5850                      break;
5851                    }
5852                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5853                    keyword);
5854                  break;
5855                }
5856                case 'W':
5857                case 'w':
5858                {
5859                  if (LocaleCompare(keyword,"width") == 0)
5860                    {
5861                      geometry.width=StringToLong(value);
5862                      break;
5863                    }
5864                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5865                    keyword);
5866                  break;
5867                }
5868                default:
5869                {
5870                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5871                    keyword);
5872                  break;
5873                }
5874              }
5875            }
5876          scale_image=ScaleImage(msl_info->image[n],geometry.width,
5877            geometry.height,msl_info->exception);
5878          if (scale_image == (Image *) NULL)
5879            break;
5880          msl_info->image[n]=DestroyImage(msl_info->image[n]);
5881          msl_info->image[n]=scale_image;
5882          break;
5883        }
5884      if (LocaleCompare((const char *) tag,"segment") == 0)
5885        {
5886          ColorspaceType
5887            colorspace;
5888
5889          MagickBooleanType
5890            verbose;
5891
5892          /*
5893            Segment image.
5894          */
5895          if (msl_info->image[n] == (Image *) NULL)
5896            {
5897              ThrowMSLException(OptionError,"NoImagesDefined",
5898                (const char *) tag);
5899              break;
5900            }
5901          geometry_info.rho=1.0;
5902          geometry_info.sigma=1.5;
5903          colorspace=sRGBColorspace;
5904          verbose=MagickFalse;
5905          if (attributes != (const xmlChar **) NULL)
5906            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5907            {
5908              keyword=(const char *) attributes[i++];
5909              attribute=InterpretImageProperties(msl_info->image_info[n],
5910                msl_info->attributes[n],(const char *) attributes[i],
5911                &exception);
5912              CloneString(&value,attribute);
5913              switch (*keyword)
5914              {
5915                case 'C':
5916                case 'c':
5917                {
5918                  if (LocaleCompare(keyword,"cluster-threshold") == 0)
5919                    {
5920                      geometry_info.rho=StringToDouble(value,
5921                        (char **) NULL);
5922                      break;
5923                    }
5924                  if (LocaleCompare(keyword,"colorspace") == 0)
5925                    {
5926                      option=ParseCommandOption(MagickColorspaceOptions,
5927                        MagickFalse,value);
5928                      if (option < 0)
5929                        ThrowMSLException(OptionError,
5930                          "UnrecognizedColorspaceType",value);
5931                      colorspace=(ColorspaceType) option;
5932                      break;
5933                    }
5934                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5935                    keyword);
5936                  break;
5937                }
5938                case 'G':
5939                case 'g':
5940                {
5941                  if (LocaleCompare(keyword,"geometry") == 0)
5942                    {
5943                      flags=ParseGeometry(value,&geometry_info);
5944                      if ((flags & SigmaValue) == 0)
5945                        geometry_info.sigma=1.5;
5946                      break;
5947                    }
5948                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5949                    keyword);
5950                  break;
5951                }
5952                case 'S':
5953                case 's':
5954                {
5955                  if (LocaleCompare(keyword,"smoothing-threshold") == 0)
5956                    {
5957                      geometry_info.sigma=StringToDouble(value,
5958                        (char **) NULL);
5959                      break;
5960                    }
5961                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5962                    keyword);
5963                  break;
5964                }
5965                default:
5966                {
5967                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
5968                    keyword);
5969                  break;
5970                }
5971              }
5972            }
5973          (void) SegmentImage(msl_info->image[n],colorspace,verbose,
5974            geometry_info.rho,geometry_info.sigma,&exception);
5975          break;
5976        }
5977      else if (LocaleCompare((const char *) tag, "set") == 0)
5978      {
5979        if (msl_info->image[n] == (Image *) NULL)
5980        {
5981          ThrowMSLException(OptionError,"NoImagesDefined",(const char *) tag);
5982          break;
5983        }
5984
5985        if (attributes == (const xmlChar **) NULL)
5986          break;
5987        for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
5988        {
5989          keyword=(const char *) attributes[i++];
5990          CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
5991            msl_info->attributes[n],(const char *) attributes[i],&exception));
5992          switch (*keyword)
5993          {
5994            case 'C':
5995            case 'c':
5996            {
5997              if (LocaleCompare(keyword,"clip-mask") == 0)
5998                {
5999                  for (j=0; j < msl_info->n; j++)
6000                  {
6001                    const char
6002                      *property;
6003
6004                    property=GetImageProperty(msl_info->attributes[j],"id",
6005                      &exception);
6006                    if (LocaleCompare(property,value) == 0)
6007                      {
6008                        SetImageMask(msl_info->image[n],msl_info->image[j],
6009                          &exception);
6010                        break;
6011                      }
6012                  }
6013                  break;
6014                }
6015              if (LocaleCompare(keyword,"clip-path") == 0)
6016                {
6017                  for (j=0; j < msl_info->n; j++)
6018                  {
6019                    const char
6020                      *property;
6021
6022                    property=GetImageProperty(msl_info->attributes[j],"id",
6023                      &exception);
6024                    if (LocaleCompare(property,value) == 0)
6025                      {
6026                        SetImageMask(msl_info->image[n],msl_info->image[j],
6027                          &exception);
6028                        break;
6029                      }
6030                  }
6031                  break;
6032                }
6033              if (LocaleCompare(keyword,"colorspace") == 0)
6034                {
6035                  ssize_t
6036                    colorspace;
6037
6038                  colorspace=(ColorspaceType) ParseCommandOption(
6039                    MagickColorspaceOptions,MagickFalse,value);
6040                  if (colorspace < 0)
6041                    ThrowMSLException(OptionError,"UnrecognizedColorspace",
6042                      value);
6043                  (void) TransformImageColorspace(msl_info->image[n],
6044                    (ColorspaceType) colorspace,&exception);
6045                  break;
6046                }
6047              (void) SetMSLAttributes(msl_info,keyword,value);
6048              (void) SetImageProperty(msl_info->image[n],keyword,value,
6049                &exception);
6050              break;
6051            }
6052            case 'D':
6053            case 'd':
6054            {
6055              if (LocaleCompare(keyword,"density") == 0)
6056                {
6057                  flags=ParseGeometry(value,&geometry_info);
6058                  msl_info->image[n]->resolution.x=geometry_info.rho;
6059                  msl_info->image[n]->resolution.y=geometry_info.sigma;
6060                  if ((flags & SigmaValue) == 0)
6061                    msl_info->image[n]->resolution.y=
6062                      msl_info->image[n]->resolution.x;
6063                  break;
6064                }
6065              (void) SetMSLAttributes(msl_info,keyword,value);
6066              (void) SetImageProperty(msl_info->image[n],keyword,value,
6067                &exception);
6068              break;
6069            }
6070            case 'O':
6071            case 'o':
6072            {
6073              if (LocaleCompare(keyword, "opacity") == 0)
6074                {
6075                  ssize_t  opac = OpaqueAlpha,
6076                  len = (ssize_t) strlen( value );
6077
6078                  if (value[len-1] == '%') {
6079                    char  tmp[100];
6080                    (void) CopyMagickString(tmp,value,len);
6081                    opac = StringToLong( tmp );
6082                    opac = (int)(QuantumRange * ((float)opac/100));
6083                  } else
6084                    opac = StringToLong( value );
6085                  (void) SetImageAlpha( msl_info->image[n], (Quantum) opac,
6086                    &exception);
6087                  break;
6088              }
6089              (void) SetMSLAttributes(msl_info,keyword,value);
6090              (void) SetImageProperty(msl_info->image[n],keyword,value,
6091                msl_info->exception);
6092              break;
6093            }
6094            case 'P':
6095            case 'p':
6096            {
6097              if (LocaleCompare(keyword, "page") == 0)
6098              {
6099                char
6100                  page[MaxTextExtent];
6101
6102                const char
6103                  *image_option;
6104
6105                MagickStatusType
6106                  flags;
6107
6108                RectangleInfo
6109                  geometry;
6110
6111                (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
6112                image_option=GetImageOption(msl_info->image_info[n],"page");
6113                if (image_option != (const char *) NULL)
6114                  flags=ParseAbsoluteGeometry(image_option,&geometry);
6115                flags=ParseAbsoluteGeometry(value,&geometry);
6116                (void) FormatLocaleString(page,MaxTextExtent,"%.20gx%.20g",
6117                  (double) geometry.width,(double) geometry.height);
6118                if (((flags & XValue) != 0) || ((flags & YValue) != 0))
6119                  (void) FormatLocaleString(page,MaxTextExtent,
6120                    "%.20gx%.20g%+.20g%+.20g",(double) geometry.width,
6121                    (double) geometry.height,(double) geometry.x,(double)
6122                    geometry.y);
6123                (void) SetImageOption(msl_info->image_info[n],keyword,page);
6124                msl_info->image_info[n]->page=GetPageGeometry(page);
6125                break;
6126              }
6127              (void) SetMSLAttributes(msl_info,keyword,value);
6128              (void) SetImageProperty(msl_info->image[n],keyword,value,
6129                msl_info->exception);
6130              break;
6131            }
6132            default:
6133            {
6134              (void) SetMSLAttributes(msl_info,keyword,value);
6135              (void) SetImageProperty(msl_info->image[n],keyword,value,
6136                msl_info->exception);
6137              break;
6138            }
6139          }
6140        }
6141        break;
6142      }
6143      if (LocaleCompare((const char *) tag,"shade") == 0)
6144        {
6145          Image
6146            *shade_image;
6147
6148          MagickBooleanType
6149            gray;
6150
6151          /*
6152            Shade image.
6153          */
6154          if (msl_info->image[n] == (Image *) NULL)
6155            {
6156              ThrowMSLException(OptionError,"NoImagesDefined",
6157                (const char *) tag);
6158              break;
6159            }
6160          gray=MagickFalse;
6161          if (attributes != (const xmlChar **) NULL)
6162            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6163            {
6164              keyword=(const char *) attributes[i++];
6165              attribute=InterpretImageProperties(msl_info->image_info[n],
6166                msl_info->attributes[n],(const char *) attributes[i],
6167                &exception);
6168              CloneString(&value,attribute);
6169              switch (*keyword)
6170              {
6171                case 'A':
6172                case 'a':
6173                {
6174                  if (LocaleCompare(keyword,"azimuth") == 0)
6175                    {
6176                      geometry_info.rho=StringToDouble(value,
6177                        (char **) NULL);
6178                      break;
6179                    }
6180                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6181                    keyword);
6182                  break;
6183                }
6184                case 'E':
6185                case 'e':
6186                {
6187                  if (LocaleCompare(keyword,"elevation") == 0)
6188                    {
6189                      geometry_info.sigma=StringToDouble(value,
6190                        (char **) NULL);
6191                      break;
6192                    }
6193                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6194                    keyword);
6195                  break;
6196                }
6197                case 'G':
6198                case 'g':
6199                {
6200                  if (LocaleCompare(keyword,"geometry") == 0)
6201                    {
6202                      flags=ParseGeometry(value,&geometry_info);
6203                      if ((flags & SigmaValue) == 0)
6204                        geometry_info.sigma=1.0;
6205                      break;
6206                    }
6207                  if (LocaleCompare(keyword,"gray") == 0)
6208                    {
6209                      option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6210                        value);
6211                      if (option < 0)
6212                        ThrowMSLException(OptionError,"UnrecognizedNoiseType",
6213                          value);
6214                      gray=(MagickBooleanType) option;
6215                      break;
6216                    }
6217                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6218                    keyword);
6219                  break;
6220                }
6221                default:
6222                {
6223                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6224                    keyword);
6225                  break;
6226                }
6227              }
6228            }
6229          shade_image=ShadeImage(msl_info->image[n],gray,geometry_info.rho,
6230            geometry_info.sigma,msl_info->exception);
6231          if (shade_image == (Image *) NULL)
6232            break;
6233          msl_info->image[n]=DestroyImage(msl_info->image[n]);
6234          msl_info->image[n]=shade_image;
6235          break;
6236        }
6237      if (LocaleCompare((const char *) tag,"shadow") == 0)
6238        {
6239          Image
6240            *shadow_image;
6241
6242          /*
6243            Shear image.
6244          */
6245          if (msl_info->image[n] == (Image *) NULL)
6246            {
6247              ThrowMSLException(OptionError,"NoImagesDefined",
6248                (const char *) tag);
6249              break;
6250            }
6251          if (attributes != (const xmlChar **) NULL)
6252            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6253            {
6254              keyword=(const char *) attributes[i++];
6255              attribute=InterpretImageProperties(msl_info->image_info[n],
6256                msl_info->attributes[n],(const char *) attributes[i],
6257                &exception);
6258              CloneString(&value,attribute);
6259              switch (*keyword)
6260              {
6261                case 'G':
6262                case 'g':
6263                {
6264                  if (LocaleCompare(keyword,"geometry") == 0)
6265                    {
6266                      flags=ParseGeometry(value,&geometry_info);
6267                      if ((flags & SigmaValue) == 0)
6268                        geometry_info.sigma=1.0;
6269                      break;
6270                    }
6271                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6272                    keyword);
6273                  break;
6274                }
6275                case 'O':
6276                case 'o':
6277                {
6278                  if (LocaleCompare(keyword,"opacity") == 0)
6279                    {
6280                      geometry_info.rho=StringToLong(value);
6281                      break;
6282                    }
6283                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6284                    keyword);
6285                  break;
6286                }
6287                case 'S':
6288                case 's':
6289                {
6290                  if (LocaleCompare(keyword,"sigma") == 0)
6291                    {
6292                      geometry_info.sigma=StringToLong(value);
6293                      break;
6294                    }
6295                  break;
6296                }
6297                case 'X':
6298                case 'x':
6299                {
6300                  if (LocaleCompare(keyword,"x") == 0)
6301                    {
6302                      geometry_info.xi=StringToDouble(value,
6303                        (char **) NULL);
6304                      break;
6305                    }
6306                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6307                    keyword);
6308                  break;
6309                }
6310                case 'Y':
6311                case 'y':
6312                {
6313                  if (LocaleCompare(keyword,"y") == 0)
6314                    {
6315                      geometry_info.psi=StringToLong(value);
6316                      break;
6317                    }
6318                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6319                    keyword);
6320                  break;
6321                }
6322                default:
6323                {
6324                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6325                    keyword);
6326                  break;
6327                }
6328              }
6329            }
6330          shadow_image=ShadowImage(msl_info->image[n],geometry_info.rho,
6331            geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),
6332            (ssize_t) ceil(geometry_info.psi-0.5),msl_info->exception);
6333          if (shadow_image == (Image *) NULL)
6334            break;
6335          msl_info->image[n]=DestroyImage(msl_info->image[n]);
6336          msl_info->image[n]=shadow_image;
6337          break;
6338        }
6339      if (LocaleCompare((const char *) tag,"sharpen") == 0)
6340      {
6341        double
6342            radius = 0.0,
6343            sigma = 1.0;
6344
6345        if (msl_info->image[n] == (Image *) NULL)
6346          {
6347            ThrowMSLException(OptionError,"NoImagesDefined",
6348              (const char *) tag);
6349            break;
6350          }
6351        /*
6352        NOTE: sharpen can have no attributes, since we use all the defaults!
6353        */
6354        if (attributes != (const xmlChar **) NULL)
6355        {
6356          for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6357          {
6358          keyword=(const char *) attributes[i++];
6359          CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
6360            msl_info->attributes[n],(const char *) attributes[i],&exception));
6361          switch (*keyword)
6362          {
6363            case 'R':
6364            case 'r':
6365            {
6366              if (LocaleCompare(keyword, "radius") == 0)
6367              {
6368                radius = StringToDouble(value,(char **) NULL);
6369                break;
6370              }
6371              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6372              break;
6373            }
6374            case 'S':
6375            case 's':
6376            {
6377              if (LocaleCompare(keyword,"sigma") == 0)
6378              {
6379                sigma = StringToLong( value );
6380                break;
6381              }
6382              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6383              break;
6384            }
6385            default:
6386            {
6387              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6388              break;
6389            }
6390          }
6391          }
6392        }
6393
6394        /*
6395          sharpen image.
6396        */
6397        {
6398        Image
6399          *newImage;
6400
6401        newImage=SharpenImage(msl_info->image[n],radius,sigma,
6402          msl_info->exception);
6403        if (newImage == (Image *) NULL)
6404          break;
6405        msl_info->image[n]=DestroyImage(msl_info->image[n]);
6406        msl_info->image[n]=newImage;
6407        break;
6408        }
6409      }
6410      else if (LocaleCompare((const char *) tag,"shave") == 0)
6411      {
6412        /* init the values */
6413        width = height = 0;
6414        x = y = 0;
6415
6416        if (msl_info->image[n] == (Image *) NULL)
6417        {
6418          ThrowMSLException(OptionError,"NoImagesDefined",
6419            (const char *) tag);
6420          break;
6421        }
6422        if (attributes == (const xmlChar **) NULL)
6423        break;
6424        for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6425        {
6426        keyword=(const char *) attributes[i++];
6427        CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
6428          msl_info->attributes[n],(const char *) attributes[i],&exception));
6429        switch (*keyword)
6430        {
6431          case 'G':
6432          case 'g':
6433          {
6434          if (LocaleCompare(keyword,"geometry") == 0)
6435            {
6436            (void) ParseMetaGeometry(value,&x,&y,&width,&height);
6437            break;
6438            }
6439          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6440          break;
6441          }
6442          case 'H':
6443          case 'h':
6444          {
6445          if (LocaleCompare(keyword,"height") == 0)
6446            {
6447            height = StringToLong( value );
6448            break;
6449            }
6450          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6451          break;
6452          }
6453          case 'W':
6454          case 'w':
6455          {
6456          if (LocaleCompare(keyword,"width") == 0)
6457            {
6458            width = StringToLong( value );
6459            break;
6460            }
6461          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6462          break;
6463          }
6464          default:
6465          {
6466          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6467          break;
6468          }
6469        }
6470        }
6471
6472        /*
6473          process image.
6474        */
6475        {
6476        Image
6477          *newImage;
6478        RectangleInfo
6479          rectInfo;
6480
6481        rectInfo.height = height;
6482        rectInfo.width = width;
6483        rectInfo.x = x;
6484        rectInfo.y = y;
6485
6486
6487        newImage=ShaveImage(msl_info->image[n], &rectInfo,
6488          msl_info->exception);
6489        if (newImage == (Image *) NULL)
6490          break;
6491        msl_info->image[n]=DestroyImage(msl_info->image[n]);
6492        msl_info->image[n]=newImage;
6493        }
6494
6495        break;
6496      }
6497      if (LocaleCompare((const char *) tag,"shear") == 0)
6498        {
6499          Image
6500            *shear_image;
6501
6502          /*
6503            Shear image.
6504          */
6505          if (msl_info->image[n] == (Image *) NULL)
6506            {
6507              ThrowMSLException(OptionError,"NoImagesDefined",
6508                (const char *) tag);
6509              break;
6510            }
6511          if (attributes != (const xmlChar **) NULL)
6512            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6513            {
6514              keyword=(const char *) attributes[i++];
6515              attribute=InterpretImageProperties(msl_info->image_info[n],
6516                msl_info->attributes[n],(const char *) attributes[i],
6517                &exception);
6518              CloneString(&value,attribute);
6519              switch (*keyword)
6520              {
6521                case 'F':
6522                case 'f':
6523                {
6524                  if (LocaleCompare(keyword, "fill") == 0)
6525                    {
6526                      (void) QueryColorCompliance(value,AllCompliance,
6527                        &msl_info->image[n]->background_color,&exception);
6528                      break;
6529                    }
6530                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6531                    keyword);
6532                  break;
6533                }
6534                case 'G':
6535                case 'g':
6536                {
6537                  if (LocaleCompare(keyword,"geometry") == 0)
6538                    {
6539                      flags=ParseGeometry(value,&geometry_info);
6540                      if ((flags & SigmaValue) == 0)
6541                        geometry_info.sigma=1.0;
6542                      break;
6543                    }
6544                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6545                    keyword);
6546                  break;
6547                }
6548                case 'X':
6549                case 'x':
6550                {
6551                  if (LocaleCompare(keyword,"x") == 0)
6552                    {
6553                      geometry_info.rho=StringToDouble(value,
6554                        (char **) NULL);
6555                      break;
6556                    }
6557                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6558                    keyword);
6559                  break;
6560                }
6561                case 'Y':
6562                case 'y':
6563                {
6564                  if (LocaleCompare(keyword,"y") == 0)
6565                    {
6566                      geometry_info.sigma=StringToLong(value);
6567                      break;
6568                    }
6569                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6570                    keyword);
6571                  break;
6572                }
6573                default:
6574                {
6575                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6576                    keyword);
6577                  break;
6578                }
6579              }
6580            }
6581          shear_image=ShearImage(msl_info->image[n],geometry_info.rho,
6582            geometry_info.sigma,msl_info->exception);
6583          if (shear_image == (Image *) NULL)
6584            break;
6585          msl_info->image[n]=DestroyImage(msl_info->image[n]);
6586          msl_info->image[n]=shear_image;
6587          break;
6588        }
6589      if (LocaleCompare((const char *) tag,"signature") == 0)
6590        {
6591          /*
6592            Signature image.
6593          */
6594          if (msl_info->image[n] == (Image *) NULL)
6595            {
6596              ThrowMSLException(OptionError,"NoImagesDefined",
6597                (const char *) tag);
6598              break;
6599            }
6600          if (attributes != (const xmlChar **) NULL)
6601            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6602            {
6603              keyword=(const char *) attributes[i++];
6604              attribute=InterpretImageProperties(msl_info->image_info[n],
6605                msl_info->attributes[n],(const char *) attributes[i],
6606                &exception);
6607              CloneString(&value,attribute);
6608              switch (*keyword)
6609              {
6610                default:
6611                {
6612                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6613                    keyword);
6614                  break;
6615                }
6616              }
6617            }
6618          (void) SignatureImage(msl_info->image[n],&exception);
6619          break;
6620        }
6621      if (LocaleCompare((const char *) tag,"solarize") == 0)
6622        {
6623          /*
6624            Solarize image.
6625          */
6626          if (msl_info->image[n] == (Image *) NULL)
6627            {
6628              ThrowMSLException(OptionError,"NoImagesDefined",
6629                (const char *) tag);
6630              break;
6631            }
6632          geometry_info.rho=QuantumRange/2.0;
6633          if (attributes != (const xmlChar **) NULL)
6634            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6635            {
6636              keyword=(const char *) attributes[i++];
6637              attribute=InterpretImageProperties(msl_info->image_info[n],
6638                msl_info->attributes[n],(const char *) attributes[i],
6639                &exception);
6640              CloneString(&value,attribute);
6641              switch (*keyword)
6642              {
6643                case 'G':
6644                case 'g':
6645                {
6646                  if (LocaleCompare(keyword,"geometry") == 0)
6647                    {
6648                      flags=ParseGeometry(value,&geometry_info);
6649                      break;
6650                    }
6651                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6652                    keyword);
6653                  break;
6654                }
6655                case 'T':
6656                case 't':
6657                {
6658                  if (LocaleCompare(keyword,"threshold") == 0)
6659                    {
6660                      geometry_info.rho=StringToDouble(value,
6661                        (char **) NULL);
6662                      break;
6663                    }
6664                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6665                    keyword);
6666                  break;
6667                }
6668                default:
6669                {
6670                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6671                    keyword);
6672                  break;
6673                }
6674              }
6675            }
6676          (void) SolarizeImage(msl_info->image[n],geometry_info.rho,
6677            msl_info->exception);
6678          break;
6679        }
6680      if (LocaleCompare((const char *) tag,"spread") == 0)
6681        {
6682          Image
6683            *spread_image;
6684
6685          /*
6686            Spread image.
6687          */
6688          if (msl_info->image[n] == (Image *) NULL)
6689            {
6690              ThrowMSLException(OptionError,"NoImagesDefined",
6691                (const char *) tag);
6692              break;
6693            }
6694          if (attributes != (const xmlChar **) NULL)
6695            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6696            {
6697              keyword=(const char *) attributes[i++];
6698              attribute=InterpretImageProperties(msl_info->image_info[n],
6699                msl_info->attributes[n],(const char *) attributes[i],
6700                &exception);
6701              CloneString(&value,attribute);
6702              switch (*keyword)
6703              {
6704                case 'G':
6705                case 'g':
6706                {
6707                  if (LocaleCompare(keyword,"geometry") == 0)
6708                    {
6709                      flags=ParseGeometry(value,&geometry_info);
6710                      if ((flags & SigmaValue) == 0)
6711                        geometry_info.sigma=1.0;
6712                      break;
6713                    }
6714                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6715                    keyword);
6716                  break;
6717                }
6718                case 'R':
6719                case 'r':
6720                {
6721                  if (LocaleCompare(keyword,"radius") == 0)
6722                    {
6723                      geometry_info.rho=StringToDouble(value,
6724                        (char **) NULL);
6725                      break;
6726                    }
6727                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6728                    keyword);
6729                  break;
6730                }
6731                default:
6732                {
6733                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6734                    keyword);
6735                  break;
6736                }
6737              }
6738            }
6739          spread_image=SpreadImage(msl_info->image[n],geometry_info.rho,
6740            msl_info->image[n]->interpolate,msl_info->exception);
6741          if (spread_image == (Image *) NULL)
6742            break;
6743          msl_info->image[n]=DestroyImage(msl_info->image[n]);
6744          msl_info->image[n]=spread_image;
6745          break;
6746        }
6747      else if (LocaleCompare((const char *) tag,"stegano") == 0)
6748      {
6749        Image *
6750          watermark = (Image*)NULL;
6751
6752        if (msl_info->image[n] == (Image *) NULL)
6753          {
6754            ThrowMSLException(OptionError,"NoImagesDefined",
6755              (const char *) tag);
6756            break;
6757          }
6758        if (attributes == (const xmlChar **) NULL)
6759        break;
6760        for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6761        {
6762        keyword=(const char *) attributes[i++];
6763        CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
6764          msl_info->attributes[n],(const char *) attributes[i],&exception));
6765        switch (*keyword)
6766        {
6767          case 'I':
6768          case 'i':
6769          {
6770          if (LocaleCompare(keyword,"image") == 0)
6771            {
6772            for (j=0; j<msl_info->n;j++)
6773            {
6774              const char *
6775                theAttr = GetImageProperty(msl_info->attributes[j], "id",
6776                      &exception);
6777              if (theAttr && LocaleCompare(theAttr, value) == 0)
6778              {
6779                watermark = msl_info->image[j];
6780                break;
6781              }
6782            }
6783            break;
6784            }
6785          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6786          break;
6787          }
6788          default:
6789          {
6790          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6791          break;
6792          }
6793        }
6794        }
6795
6796        /*
6797          process image.
6798        */
6799        if ( watermark != (Image*) NULL )
6800        {
6801        Image
6802          *newImage;
6803
6804        newImage=SteganoImage(msl_info->image[n], watermark, msl_info->exception);
6805        if (newImage == (Image *) NULL)
6806          break;
6807        msl_info->image[n]=DestroyImage(msl_info->image[n]);
6808        msl_info->image[n]=newImage;
6809        break;
6810        } else
6811          ThrowMSLException(OptionError,"MissingWatermarkImage",keyword);
6812      }
6813      else if (LocaleCompare((const char *) tag,"stereo") == 0)
6814      {
6815        Image *
6816          stereoImage = (Image*)NULL;
6817
6818        if (msl_info->image[n] == (Image *) NULL)
6819          {
6820            ThrowMSLException(OptionError,"NoImagesDefined",(const char *) tag);
6821            break;
6822          }
6823        if (attributes == (const xmlChar **) NULL)
6824        break;
6825        for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6826        {
6827        keyword=(const char *) attributes[i++];
6828        CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
6829          msl_info->attributes[n],(const char *) attributes[i],&exception));
6830        switch (*keyword)
6831        {
6832          case 'I':
6833          case 'i':
6834          {
6835          if (LocaleCompare(keyword,"image") == 0)
6836            {
6837            for (j=0; j<msl_info->n;j++)
6838            {
6839              const char *
6840                theAttr = GetImageProperty(msl_info->attributes[j], "id",
6841                      &exception);
6842              if (theAttr && LocaleCompare(theAttr, value) == 0)
6843              {
6844                stereoImage = msl_info->image[j];
6845                break;
6846              }
6847            }
6848            break;
6849            }
6850          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6851          break;
6852          }
6853          default:
6854          {
6855          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6856          break;
6857          }
6858        }
6859        }
6860
6861        /*
6862          process image.
6863        */
6864        if ( stereoImage != (Image*) NULL )
6865        {
6866        Image
6867          *newImage;
6868
6869        newImage=StereoImage(msl_info->image[n], stereoImage, msl_info->exception);
6870        if (newImage == (Image *) NULL)
6871          break;
6872        msl_info->image[n]=DestroyImage(msl_info->image[n]);
6873        msl_info->image[n]=newImage;
6874        break;
6875        } else
6876          ThrowMSLException(OptionError,"Missing stereo image",keyword);
6877      }
6878      if (LocaleCompare((const char *) tag,"strip") == 0)
6879        {
6880          /*
6881            Strip image.
6882          */
6883          if (msl_info->image[n] == (Image *) NULL)
6884            {
6885              ThrowMSLException(OptionError,"NoImagesDefined",
6886                (const char *) tag);
6887              break;
6888            }
6889          if (attributes != (const xmlChar **) NULL)
6890            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6891            {
6892              keyword=(const char *) attributes[i++];
6893              attribute=InterpretImageProperties(msl_info->image_info[n],
6894                msl_info->attributes[n],(const char *) attributes[i],
6895                &exception);
6896              CloneString(&value,attribute);
6897              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
6898            }
6899          (void) StripImage(msl_info->image[n],msl_info->exception);
6900          break;
6901        }
6902      if (LocaleCompare((const char *) tag,"swap") == 0)
6903        {
6904          Image
6905            *p,
6906            *q,
6907            *swap;
6908
6909          ssize_t
6910            index,
6911            swap_index;
6912
6913          if (msl_info->image[n] == (Image *) NULL)
6914            {
6915              ThrowMSLException(OptionError,"NoImagesDefined",
6916                (const char *) tag);
6917              break;
6918            }
6919          index=(-1);
6920          swap_index=(-2);
6921          if (attributes != (const xmlChar **) NULL)
6922            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6923            {
6924              keyword=(const char *) attributes[i++];
6925              attribute=InterpretImageProperties(msl_info->image_info[n],
6926                msl_info->attributes[n],(const char *) attributes[i],
6927                &exception);
6928              CloneString(&value,attribute);
6929              switch (*keyword)
6930              {
6931                case 'G':
6932                case 'g':
6933                {
6934                  if (LocaleCompare(keyword,"indexes") == 0)
6935                    {
6936                      flags=ParseGeometry(value,&geometry_info);
6937                      index=(ssize_t) geometry_info.rho;
6938                      if ((flags & SigmaValue) == 0)
6939                        swap_index=(ssize_t) geometry_info.sigma;
6940                      break;
6941                    }
6942                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6943                    keyword);
6944                  break;
6945                }
6946                default:
6947                {
6948                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
6949                    keyword);
6950                  break;
6951                }
6952              }
6953            }
6954          /*
6955            Swap images.
6956          */
6957          p=GetImageFromList(msl_info->image[n],index);
6958          q=GetImageFromList(msl_info->image[n],swap_index);
6959          if ((p == (Image *) NULL) || (q == (Image *) NULL))
6960            {
6961              ThrowMSLException(OptionError,"NoSuchImage",(const char *) tag);
6962              break;
6963            }
6964          swap=CloneImage(p,0,0,MagickTrue,msl_info->exception);
6965          ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,
6966            msl_info->exception));
6967          ReplaceImageInList(&q,swap);
6968          msl_info->image[n]=GetFirstImageInList(q);
6969          break;
6970        }
6971      if (LocaleCompare((const char *) tag,"swirl") == 0)
6972        {
6973          Image
6974            *swirl_image;
6975
6976          /*
6977            Swirl image.
6978          */
6979          if (msl_info->image[n] == (Image *) NULL)
6980            {
6981              ThrowMSLException(OptionError,"NoImagesDefined",
6982                (const char *) tag);
6983              break;
6984            }
6985          if (attributes != (const xmlChar **) NULL)
6986            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
6987            {
6988              keyword=(const char *) attributes[i++];
6989              attribute=InterpretImageProperties(msl_info->image_info[n],
6990                msl_info->attributes[n],(const char *) attributes[i],
6991                &exception);
6992              CloneString(&value,attribute);
6993              switch (*keyword)
6994              {
6995                case 'D':
6996                case 'd':
6997                {
6998                  if (LocaleCompare(keyword,"degrees") == 0)
6999                    {
7000                      geometry_info.rho=StringToDouble(value,
7001                        (char **) NULL);
7002                      break;
7003                    }
7004                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
7005                    keyword);
7006                  break;
7007                }
7008                case 'G':
7009                case 'g':
7010                {
7011                  if (LocaleCompare(keyword,"geometry") == 0)
7012                    {
7013                      flags=ParseGeometry(value,&geometry_info);
7014                      if ((flags & SigmaValue) == 0)
7015                        geometry_info.sigma=1.0;
7016                      break;
7017                    }
7018                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
7019                    keyword);
7020                  break;
7021                }
7022                default:
7023                {
7024                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
7025                    keyword);
7026                  break;
7027                }
7028              }
7029            }
7030          swirl_image=SwirlImage(msl_info->image[n],geometry_info.rho,
7031            msl_info->image[n]->interpolate,msl_info->exception);
7032          if (swirl_image == (Image *) NULL)
7033            break;
7034          msl_info->image[n]=DestroyImage(msl_info->image[n]);
7035          msl_info->image[n]=swirl_image;
7036          break;
7037        }
7038      if (LocaleCompare((const char *) tag,"sync") == 0)
7039        {
7040          /*
7041            Sync image.
7042          */
7043          if (msl_info->image[n] == (Image *) NULL)
7044            {
7045              ThrowMSLException(OptionError,"NoImagesDefined",
7046                (const char *) tag);
7047              break;
7048            }
7049          if (attributes != (const xmlChar **) NULL)
7050            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
7051            {
7052              keyword=(const char *) attributes[i++];
7053              attribute=InterpretImageProperties(msl_info->image_info[n],
7054                msl_info->attributes[n],(const char *) attributes[i],
7055                &exception);
7056              CloneString(&value,attribute);
7057              switch (*keyword)
7058              {
7059                default:
7060                {
7061                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
7062                    keyword);
7063                  break;
7064                }
7065              }
7066            }
7067          (void) SyncImage(msl_info->image[n],&exception);
7068          break;
7069        }
7070      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
7071    }
7072    case 'T':
7073    case 't':
7074    {
7075      if (LocaleCompare((const char *) tag,"map") == 0)
7076        {
7077          Image
7078            *texture_image;
7079
7080          /*
7081            Texture image.
7082          */
7083          if (msl_info->image[n] == (Image *) NULL)
7084            {
7085              ThrowMSLException(OptionError,"NoImagesDefined",
7086                (const char *) tag);
7087              break;
7088            }
7089          texture_image=NewImageList();
7090          if (attributes != (const xmlChar **) NULL)
7091            for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
7092            {
7093              keyword=(const char *) attributes[i++];
7094              attribute=InterpretImageProperties(msl_info->image_info[n],
7095                msl_info->attributes[n],(const char *) attributes[i],
7096                &exception);
7097              CloneString(&value,attribute);
7098              switch (*keyword)
7099              {
7100                case 'I':
7101                case 'i':
7102                {
7103                  if (LocaleCompare(keyword,"image") == 0)
7104                    for (j=0; j < msl_info->n; j++)
7105                    {
7106                      const char
7107                        *attribute;
7108
7109                      attribute=GetImageProperty(msl_info->attributes[j],"id",
7110                      &exception);
7111                      if ((attribute != (const char *) NULL)  &&
7112                          (LocaleCompare(attribute,value) == 0))
7113                        {
7114                          texture_image=CloneImage(msl_info->image[j],0,0,
7115                            MagickFalse,&exception);
7116                          break;
7117                        }
7118                    }
7119                  break;
7120                }
7121                default:
7122                {
7123                  ThrowMSLException(OptionError,"UnrecognizedAttribute",
7124                    keyword);
7125                  break;
7126                }
7127              }
7128            }
7129          (void) TextureImage(msl_info->image[n],texture_image,&exception);
7130          texture_image=DestroyImage(texture_image);
7131          break;
7132        }
7133      else if (LocaleCompare((const char *) tag,"threshold") == 0)
7134      {
7135        /* init the values */
7136        double  threshold = 0;
7137
7138        if (msl_info->image[n] == (Image *) NULL)
7139          {
7140            ThrowMSLException(OptionError,"NoImagesDefined",(const char *) tag);
7141            break;
7142          }
7143        if (attributes == (const xmlChar **) NULL)
7144        break;
7145        for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
7146        {
7147        keyword=(const char *) attributes[i++];
7148        CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
7149          msl_info->attributes[n],(const char *) attributes[i],&exception));
7150        switch (*keyword)
7151        {
7152          case 'T':
7153          case 't':
7154          {
7155          if (LocaleCompare(keyword,"threshold") == 0)
7156            {
7157            threshold = StringToDouble(value,(char **) NULL);
7158            break;
7159            }
7160          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
7161          break;
7162          }
7163          default:
7164          {
7165          ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
7166          break;
7167          }
7168        }
7169        }
7170
7171        /*
7172          process image.
7173        */
7174        {
7175          BilevelImage(msl_info->image[n],threshold,&exception);
7176          break;
7177        }
7178      }
7179      else if (LocaleCompare((const char *) tag, "transparent") == 0)
7180      {
7181        if (msl_info->image[n] == (Image *) NULL)
7182          {
7183            ThrowMSLException(OptionError,"NoImagesDefined",(const char *) tag);
7184            break;
7185          }
7186        if (attributes == (const xmlChar **) NULL)
7187          break;
7188        for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
7189        {
7190          keyword=(const char *) attributes[i++];
7191          CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
7192            msl_info->attributes[n],(const char *) attributes[i],&exception));
7193          switch (*keyword)
7194          {
7195            case 'C':
7196            case 'c':
7197            {
7198              if (LocaleCompare(keyword,"color") == 0)
7199              {
7200                PixelInfo
7201                  target;
7202
7203                (void) QueryColorCompliance(value,AllCompliance,&target,
7204                  &exception);
7205                (void) TransparentPaintImage(msl_info->image[n],&target,
7206                  TransparentAlpha,MagickFalse,msl_info->exception);
7207                break;
7208              }
7209              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
7210              break;
7211            }
7212            default:
7213            {
7214              ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
7215            break;
7216            }
7217          }
7218        }
7219        break;
7220      }
7221      else if (LocaleCompare((const char *) tag, "trim") == 0)
7222      {
7223        if (msl_info->image[n] == (Image *) NULL)
7224          {
7225            ThrowMSLException(OptionError,"NoImagesDefined",(const char *) tag);
7226            break;
7227          }
7228
7229        /* no attributes here */
7230
7231        /* process the image */
7232        {
7233          Image
7234            *newImage;
7235          RectangleInfo
7236            rectInfo;
7237
7238          /* all zeros on a crop == trim edges! */
7239          rectInfo.height = rectInfo.width = 0;
7240          rectInfo.x =  rectInfo.y = 0;
7241
7242          newImage=CropImage(msl_info->image[n],&rectInfo, msl_info->exception);
7243          if (newImage == (Image *) NULL)
7244            break;
7245          msl_info->image[n]=DestroyImage(msl_info->image[n]);
7246          msl_info->image[n]=newImage;
7247          break;
7248        }
7249      }
7250      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
7251    }
7252    case 'W':
7253    case 'w':
7254    {
7255      if (LocaleCompare((const char *) tag,"write") == 0)
7256        {
7257          if (msl_info->image[n] == (Image *) NULL)
7258            {
7259              ThrowMSLException(OptionError,"NoImagesDefined",
7260                (const char *) tag);
7261              break;
7262            }
7263          if (attributes == (const xmlChar **) NULL)
7264            break;
7265          for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
7266          {
7267            keyword=(const char *) attributes[i++];
7268            CloneString(&value,InterpretImageProperties(msl_info->image_info[n],
7269              msl_info->attributes[n],(const char *) attributes[i],&exception));
7270            switch (*keyword)
7271            {
7272              case 'F':
7273              case 'f':
7274              {
7275                if (LocaleCompare(keyword,"filename") == 0)
7276                  {
7277                    (void) CopyMagickString(msl_info->image[n]->filename,value,
7278                      MaxTextExtent);
7279                    break;
7280                  }
7281                (void) SetMSLAttributes(msl_info,keyword,value);
7282              }
7283              default:
7284              {
7285                (void) SetMSLAttributes(msl_info,keyword,value);
7286                break;
7287              }
7288            }
7289          }
7290
7291          /* process */
7292          {
7293            (void) WriteImage(msl_info->image_info[n], msl_info->image[n],
7294              msl_info->exception);
7295            break;
7296          }
7297        }
7298      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
7299    }
7300    default:
7301    {
7302      ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
7303      break;
7304    }
7305  }
7306  if ( value != NULL )
7307    value=DestroyString(value);
7308  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  )");
7309}
7310
7311static void MSLEndElement(void *context,const xmlChar *tag)
7312{
7313  ssize_t
7314    n;
7315
7316  MSLInfo
7317    *msl_info;
7318
7319  /*
7320    Called when the end of an element has been detected.
7321  */
7322  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  SAX.endElement(%s)",
7323    tag);
7324  msl_info=(MSLInfo *) context;
7325  n=msl_info->n;
7326  switch (*tag)
7327  {
7328    case 'C':
7329    case 'c':
7330    {
7331      if (LocaleCompare((const char *) tag,"comment") == 0 )
7332        {
7333          (void) DeleteImageProperty(msl_info->image[n],"comment");
7334          if (msl_info->content == (char *) NULL)
7335            break;
7336          StripString(msl_info->content);
7337          (void) SetImageProperty(msl_info->image[n],"comment",
7338            msl_info->content,msl_info->exception);
7339          break;
7340        }
7341      break;
7342    }
7343    case 'G':
7344    case 'g':
7345    {
7346      if (LocaleCompare((const char *) tag, "group") == 0 )
7347      {
7348        if (msl_info->group_info[msl_info->number_groups-1].numImages > 0 )
7349        {
7350          ssize_t  i = (ssize_t)
7351            (msl_info->group_info[msl_info->number_groups-1].numImages);
7352          while ( i-- )
7353          {
7354            if (msl_info->image[msl_info->n] != (Image *) NULL)
7355              msl_info->image[msl_info->n]=DestroyImage(
7356                msl_info->image[msl_info->n]);
7357            msl_info->attributes[msl_info->n]=DestroyImage(
7358                msl_info->attributes[msl_info->n]);
7359            msl_info->image_info[msl_info->n]=DestroyImageInfo(
7360                msl_info->image_info[msl_info->n]);
7361            msl_info->n--;
7362          }
7363        }
7364        msl_info->number_groups--;
7365      }
7366      break;
7367    }
7368    case 'I':
7369    case 'i':
7370    {
7371      if (LocaleCompare((const char *) tag, "image") == 0)
7372        MSLPopImage(msl_info);
7373       break;
7374    }
7375    case 'L':
7376    case 'l':
7377    {
7378      if (LocaleCompare((const char *) tag,"label") == 0 )
7379        {
7380          (void) DeleteImageProperty(msl_info->image[n],"label");
7381          if (msl_info->content == (char *) NULL)
7382            break;
7383          StripString(msl_info->content);
7384          (void) SetImageProperty(msl_info->image[n],"label",
7385            msl_info->content,msl_info->exception);
7386          break;
7387        }
7388      break;
7389    }
7390    case 'M':
7391    case 'm':
7392    {
7393      if (LocaleCompare((const char *) tag, "msl") == 0 )
7394      {
7395        /*
7396          This our base element.
7397            at the moment we don't do anything special
7398            but someday we might!
7399        */
7400      }
7401      break;
7402    }
7403    default:
7404      break;
7405  }
7406  if (msl_info->content != (char *) NULL)
7407    msl_info->content=DestroyString(msl_info->content);
7408}
7409
7410static void MSLCharacters(void *context,const xmlChar *c,int length)
7411{
7412  MSLInfo
7413    *msl_info;
7414
7415  register char
7416    *p;
7417
7418  register ssize_t
7419    i;
7420
7421  /*
7422    Receiving some characters from the parser.
7423  */
7424  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7425    "  SAX.characters(%s,%d)",c,length);
7426  msl_info=(MSLInfo *) context;
7427  if (msl_info->content != (char *) NULL)
7428    msl_info->content=(char *) ResizeQuantumMemory(msl_info->content,
7429      strlen(msl_info->content)+length+MaxTextExtent,
7430      sizeof(*msl_info->content));
7431  else
7432    {
7433      msl_info->content=(char *) NULL;
7434      if (~length >= (MaxTextExtent-1))
7435        msl_info->content=(char *) AcquireQuantumMemory(length+MaxTextExtent,
7436          sizeof(*msl_info->content));
7437      if (msl_info->content != (char *) NULL)
7438        *msl_info->content='\0';
7439    }
7440  if (msl_info->content == (char *) NULL)
7441    return;
7442  p=msl_info->content+strlen(msl_info->content);
7443  for (i=0; i < length; i++)
7444    *p++=c[i];
7445  *p='\0';
7446}
7447
7448static void MSLReference(void *context,const xmlChar *name)
7449{
7450  MSLInfo
7451    *msl_info;
7452
7453  xmlParserCtxtPtr
7454    parser;
7455
7456  /*
7457    Called when an entity reference is detected.
7458  */
7459  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7460    "  SAX.reference(%s)",name);
7461  msl_info=(MSLInfo *) context;
7462  parser=msl_info->parser;
7463  if (*name == '#')
7464    (void) xmlAddChild(parser->node,xmlNewCharRef(msl_info->document,name));
7465  else
7466    (void) xmlAddChild(parser->node,xmlNewReference(msl_info->document,name));
7467}
7468
7469static void MSLIgnorableWhitespace(void *context,const xmlChar *c,int length)
7470{
7471  MSLInfo
7472    *msl_info;
7473
7474  /*
7475    Receiving some ignorable whitespaces from the parser.
7476  */
7477  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7478    "  SAX.ignorableWhitespace(%.30s, %d)",c,length);
7479  msl_info=(MSLInfo *) context;
7480  (void) msl_info;
7481}
7482
7483static void MSLProcessingInstructions(void *context,const xmlChar *target,
7484  const xmlChar *data)
7485{
7486  MSLInfo
7487    *msl_info;
7488
7489  /*
7490    A processing instruction has been parsed.
7491  */
7492  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7493    "  SAX.processingInstruction(%s, %s)",
7494    target,data);
7495  msl_info=(MSLInfo *) context;
7496  (void) msl_info;
7497}
7498
7499static void MSLComment(void *context,const xmlChar *value)
7500{
7501  MSLInfo
7502    *msl_info;
7503
7504  /*
7505    A comment has been parsed.
7506  */
7507  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7508    "  SAX.comment(%s)",value);
7509  msl_info=(MSLInfo *) context;
7510  (void) msl_info;
7511}
7512
7513static void MSLWarning(void *context,const char *format,...)
7514{
7515  char
7516    *message,
7517    reason[MaxTextExtent];
7518
7519  MSLInfo
7520    *msl_info;
7521
7522  va_list
7523    operands;
7524
7525  /**
7526    Display and format a warning messages, gives file, line, position and
7527    extra parameters.
7528  */
7529  va_start(operands,format);
7530  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  SAX.warning: ");
7531  (void) LogMagickEvent(CoderEvent,GetMagickModule(),format,operands);
7532  msl_info=(MSLInfo *) context;
7533  (void) msl_info;
7534#if !defined(MAGICKCORE_HAVE_VSNPRINTF)
7535  (void) vsprintf(reason,format,operands);
7536#else
7537  (void) vsnprintf(reason,MaxTextExtent,format,operands);
7538#endif
7539  message=GetExceptionMessage(errno);
7540  ThrowMSLException(CoderError,reason,message);
7541  message=DestroyString(message);
7542  va_end(operands);
7543}
7544
7545static void MSLError(void *context,const char *format,...)
7546{
7547  char
7548    reason[MaxTextExtent];
7549
7550  MSLInfo
7551    *msl_info;
7552
7553  va_list
7554    operands;
7555
7556  /*
7557    Display and format a error formats, gives file, line, position and
7558    extra parameters.
7559  */
7560  va_start(operands,format);
7561  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  SAX.error: ");
7562  (void) LogMagickEvent(CoderEvent,GetMagickModule(),format,operands);
7563  msl_info=(MSLInfo *) context;
7564  (void) msl_info;
7565#if !defined(MAGICKCORE_HAVE_VSNPRINTF)
7566  (void) vsprintf(reason,format,operands);
7567#else
7568  (void) vsnprintf(reason,MaxTextExtent,format,operands);
7569#endif
7570  ThrowMSLException(DelegateFatalError,reason,"SAX error");
7571  va_end(operands);
7572}
7573
7574static void MSLCDataBlock(void *context,const xmlChar *value,int length)
7575{
7576  MSLInfo
7577    *msl_info;
7578
7579   xmlNodePtr
7580     child;
7581
7582  xmlParserCtxtPtr
7583    parser;
7584
7585  /*
7586    Called when a pcdata block has been parsed.
7587  */
7588  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7589    "  SAX.pcdata(%s, %d)",value,length);
7590  msl_info=(MSLInfo *) context;
7591  (void) msl_info;
7592  parser=msl_info->parser;
7593  child=xmlGetLastChild(parser->node);
7594  if ((child != (xmlNodePtr) NULL) && (child->type == XML_CDATA_SECTION_NODE))
7595    {
7596      xmlTextConcat(child,value,length);
7597      return;
7598    }
7599  (void) xmlAddChild(parser->node,xmlNewCDataBlock(parser->myDoc,value,length));
7600}
7601
7602static void MSLExternalSubset(void *context,const xmlChar *name,
7603  const xmlChar *external_id,const xmlChar *system_id)
7604{
7605  MSLInfo
7606    *msl_info;
7607
7608  xmlParserCtxt
7609    parser_context;
7610
7611  xmlParserCtxtPtr
7612    parser;
7613
7614  xmlParserInputPtr
7615    input;
7616
7617  /*
7618    Does this document has an external subset?
7619  */
7620  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7621    "  SAX.externalSubset(%s %s %s)",name,
7622    (external_id != (const xmlChar *) NULL ? (const char *) external_id : " "),
7623    (system_id != (const xmlChar *) NULL ? (const char *) system_id : " "));
7624  msl_info=(MSLInfo *) context;
7625  (void) msl_info;
7626  parser=msl_info->parser;
7627  if (((external_id == NULL) && (system_id == NULL)) ||
7628      ((parser->validate == 0) || (parser->wellFormed == 0) ||
7629      (msl_info->document == 0)))
7630    return;
7631  input=MSLResolveEntity(context,external_id,system_id);
7632  if (input == NULL)
7633    return;
7634  (void) xmlNewDtd(msl_info->document,name,external_id,system_id);
7635  parser_context=(*parser);
7636  parser->inputTab=(xmlParserInputPtr *) xmlMalloc(5*sizeof(*parser->inputTab));
7637  if (parser->inputTab == (xmlParserInputPtr *) NULL)
7638    {
7639      parser->errNo=XML_ERR_NO_MEMORY;
7640      parser->input=parser_context.input;
7641      parser->inputNr=parser_context.inputNr;
7642      parser->inputMax=parser_context.inputMax;
7643      parser->inputTab=parser_context.inputTab;
7644      return;
7645  }
7646  parser->inputNr=0;
7647  parser->inputMax=5;
7648  parser->input=NULL;
7649  xmlPushInput(parser,input);
7650  (void) xmlSwitchEncoding(parser,xmlDetectCharEncoding(parser->input->cur,4));
7651  if (input->filename == (char *) NULL)
7652    input->filename=(char *) xmlStrdup(system_id);
7653  input->line=1;
7654  input->col=1;
7655  input->base=parser->input->cur;
7656  input->cur=parser->input->cur;
7657  input->free=NULL;
7658  xmlParseExternalSubset(parser,external_id,system_id);
7659  while (parser->inputNr > 1)
7660    (void) xmlPopInput(parser);
7661  xmlFreeInputStream(parser->input);
7662  xmlFree(parser->inputTab);
7663  parser->input=parser_context.input;
7664  parser->inputNr=parser_context.inputNr;
7665  parser->inputMax=parser_context.inputMax;
7666  parser->inputTab=parser_context.inputTab;
7667}
7668
7669#if defined(__cplusplus) || defined(c_plusplus)
7670}
7671#endif
7672
7673static MagickBooleanType ProcessMSLScript(const ImageInfo *image_info,
7674  Image **image,ExceptionInfo *exception)
7675{
7676  char
7677    message[MaxTextExtent];
7678
7679  Image
7680    *msl_image;
7681
7682  int
7683    status;
7684
7685  ssize_t
7686    n;
7687
7688  MSLInfo
7689    msl_info;
7690
7691  xmlSAXHandler
7692    sax_modules;
7693
7694  xmlSAXHandlerPtr
7695    sax_handler;
7696
7697  /*
7698    Open image file.
7699  */
7700  assert(image_info != (const ImageInfo *) NULL);
7701  assert(image_info->signature == MagickSignature);
7702  if (image_info->debug != MagickFalse)
7703    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
7704      image_info->filename);
7705  assert(image != (Image **) NULL);
7706  msl_image=AcquireImage(image_info,exception);
7707  status=OpenBlob(image_info,msl_image,ReadBinaryBlobMode,exception);
7708  if (status == MagickFalse)
7709    {
7710      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
7711        msl_image->filename);
7712      msl_image=DestroyImageList(msl_image);
7713      return(MagickFalse);
7714    }
7715  msl_image->columns=1;
7716  msl_image->rows=1;
7717  /*
7718    Parse MSL file.
7719  */
7720  (void) ResetMagickMemory(&msl_info,0,sizeof(msl_info));
7721  msl_info.exception=exception;
7722  msl_info.image_info=(ImageInfo **) AcquireMagickMemory(
7723    sizeof(*msl_info.image_info));
7724  msl_info.draw_info=(DrawInfo **) AcquireMagickMemory(
7725    sizeof(*msl_info.draw_info));
7726  /* top of the stack is the MSL file itself */
7727  msl_info.image=(Image **) AcquireMagickMemory(sizeof(*msl_info.image));
7728  msl_info.attributes=(Image **) AcquireMagickMemory(
7729    sizeof(*msl_info.attributes));
7730  msl_info.group_info=(MSLGroupInfo *) AcquireMagickMemory(
7731    sizeof(*msl_info.group_info));
7732  if ((msl_info.image_info == (ImageInfo **) NULL) ||
7733      (msl_info.image == (Image **) NULL) ||
7734      (msl_info.attributes == (Image **) NULL) ||
7735      (msl_info.group_info == (MSLGroupInfo *) NULL))
7736    ThrowFatalException(ResourceLimitFatalError,
7737      "UnableToInterpretMSLImage");
7738  *msl_info.image_info=CloneImageInfo(image_info);
7739  *msl_info.draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
7740  *msl_info.attributes=AcquireImage(image_info,exception);
7741  msl_info.group_info[0].numImages=0;
7742  /* the first slot is used to point to the MSL file image */
7743  *msl_info.image=msl_image;
7744  if (*image != (Image *) NULL)
7745    MSLPushImage(&msl_info,*image);
7746  (void) xmlSubstituteEntitiesDefault(1);
7747  (void) ResetMagickMemory(&sax_modules,0,sizeof(sax_modules));
7748  sax_modules.internalSubset=MSLInternalSubset;
7749  sax_modules.isStandalone=MSLIsStandalone;
7750  sax_modules.hasInternalSubset=MSLHasInternalSubset;
7751  sax_modules.hasExternalSubset=MSLHasExternalSubset;
7752  sax_modules.resolveEntity=MSLResolveEntity;
7753  sax_modules.getEntity=MSLGetEntity;
7754  sax_modules.entityDecl=MSLEntityDeclaration;
7755  sax_modules.notationDecl=MSLNotationDeclaration;
7756  sax_modules.attributeDecl=MSLAttributeDeclaration;
7757  sax_modules.elementDecl=MSLElementDeclaration;
7758  sax_modules.unparsedEntityDecl=MSLUnparsedEntityDeclaration;
7759  sax_modules.setDocumentLocator=MSLSetDocumentLocator;
7760  sax_modules.startDocument=MSLStartDocument;
7761  sax_modules.endDocument=MSLEndDocument;
7762  sax_modules.startElement=MSLStartElement;
7763  sax_modules.endElement=MSLEndElement;
7764  sax_modules.reference=MSLReference;
7765  sax_modules.characters=MSLCharacters;
7766  sax_modules.ignorableWhitespace=MSLIgnorableWhitespace;
7767  sax_modules.processingInstruction=MSLProcessingInstructions;
7768  sax_modules.comment=MSLComment;
7769  sax_modules.warning=MSLWarning;
7770  sax_modules.error=MSLError;
7771  sax_modules.fatalError=MSLError;
7772  sax_modules.getParameterEntity=MSLGetParameterEntity;
7773  sax_modules.cdataBlock=MSLCDataBlock;
7774  sax_modules.externalSubset=MSLExternalSubset;
7775  sax_handler=(&sax_modules);
7776  msl_info.parser=xmlCreatePushParserCtxt(sax_handler,&msl_info,(char *) NULL,0,
7777    msl_image->filename);
7778  while (ReadBlobString(msl_image,message) != (char *) NULL)
7779  {
7780    n=(ssize_t) strlen(message);
7781    if (n == 0)
7782      continue;
7783    status=xmlParseChunk(msl_info.parser,message,(int) n,MagickFalse);
7784    if (status != 0)
7785      break;
7786    (void) xmlParseChunk(msl_info.parser," ",1,MagickFalse);
7787    if (msl_info.exception->severity >= ErrorException)
7788      break;
7789  }
7790  if (msl_info.exception->severity == UndefinedException)
7791    (void) xmlParseChunk(msl_info.parser," ",1,MagickTrue);
7792  xmlFreeParserCtxt(msl_info.parser);
7793  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"end SAX");
7794  xmlCleanupParser();
7795  msl_info.group_info=(MSLGroupInfo *) RelinquishMagickMemory(
7796    msl_info.group_info);
7797  if (*image == (Image *) NULL)
7798    *image=(*msl_info.image);
7799  if (msl_info.exception->severity != UndefinedException)
7800    return(MagickFalse);
7801  return(MagickTrue);
7802}
7803
7804static Image *ReadMSLImage(const ImageInfo *image_info,ExceptionInfo *exception)
7805{
7806  Image
7807    *image;
7808
7809  /*
7810    Open image file.
7811  */
7812  assert(image_info != (const ImageInfo *) NULL);
7813  assert(image_info->signature == MagickSignature);
7814  if (image_info->debug != MagickFalse)
7815    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
7816      image_info->filename);
7817  assert(exception != (ExceptionInfo *) NULL);
7818  assert(exception->signature == MagickSignature);
7819  image=(Image *) NULL;
7820  (void) ProcessMSLScript(image_info,&image,exception);
7821  return(GetFirstImageInList(image));
7822}
7823#endif
7824
7825/*
7826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7827%                                                                             %
7828%                                                                             %
7829%                                                                             %
7830%   R e g i s t e r M S L I m a g e                                           %
7831%                                                                             %
7832%                                                                             %
7833%                                                                             %
7834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7835%
7836%  RegisterMSLImage() adds attributes for the MSL image format to
7837%  the list of supported formats.  The attributes include the image format
7838%  tag, a method to read and/or write the format, whether the format
7839%  supports the saving of more than one frame to the same file or blob,
7840%  whether the format supports native in-memory I/O, and a brief
7841%  description of the format.
7842%
7843%  The format of the RegisterMSLImage method is:
7844%
7845%      size_t RegisterMSLImage(void)
7846%
7847*/
7848ModuleExport size_t RegisterMSLImage(void)
7849{
7850  MagickInfo
7851    *entry;
7852
7853  entry=SetMagickInfo("MSL");
7854#if defined(MAGICKCORE_XML_DELEGATE)
7855  entry->decoder=(DecodeImageHandler *) ReadMSLImage;
7856  entry->encoder=(EncodeImageHandler *) WriteMSLImage;
7857#endif
7858  entry->description=ConstantString("Magick Scripting Language");
7859  entry->module=ConstantString("MSL");
7860  (void) RegisterMagickInfo(entry);
7861  return(MagickImageCoderSignature);
7862}
7863
7864#if defined(MAGICKCORE_XML_DELEGATE)
7865/*
7866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7867%                                                                             %
7868%                                                                             %
7869%                                                                             %
7870%   S e t M S L A t t r i b u t e s                                           %
7871%                                                                             %
7872%                                                                             %
7873%                                                                             %
7874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7875%
7876%  SetMSLAttributes() ...
7877%
7878%  The format of the SetMSLAttributes method is:
7879%
7880%      MagickBooleanType SetMSLAttributes(MSLInfo *msl_info,
7881%        const char *keyword,const char *value)
7882%
7883%  A description of each parameter follows:
7884%
7885%    o msl_info: the MSL info.
7886%
7887%    o keyword: the keyword.
7888%
7889%    o value: the value.
7890%
7891*/
7892static MagickBooleanType SetMSLAttributes(MSLInfo *msl_info,const char *keyword,
7893  const char *value)
7894{
7895  Image
7896    *attributes;
7897
7898  DrawInfo
7899    *draw_info;
7900
7901  ExceptionInfo
7902    *exception;
7903
7904  GeometryInfo
7905    geometry_info;
7906
7907  Image
7908    *image;
7909
7910  ImageInfo
7911    *image_info;
7912
7913  int
7914    flags;
7915
7916  ssize_t
7917    n;
7918
7919  assert(msl_info != (MSLInfo *) NULL);
7920  if (keyword == (const char *) NULL)
7921    return(MagickTrue);
7922  if (value == (const char *) NULL)
7923    return(MagickTrue);
7924  exception=msl_info->exception;
7925  n=msl_info->n;
7926  attributes=msl_info->attributes[n];
7927  image_info=msl_info->image_info[n];
7928  draw_info=msl_info->draw_info[n];
7929  image=msl_info->image[n];
7930  switch (*keyword)
7931  {
7932    case 'A':
7933    case 'a':
7934    {
7935      if (LocaleCompare(keyword,"adjoin") == 0)
7936        {
7937          ssize_t
7938            adjoin;
7939
7940          adjoin=ParseCommandOption(MagickBooleanOptions,MagickFalse,value);
7941          if (adjoin < 0)
7942            ThrowMSLException(OptionError,"UnrecognizedType",value);
7943          image_info->adjoin=(MagickBooleanType) adjoin;
7944          break;
7945        }
7946      if (LocaleCompare(keyword,"alpha") == 0)
7947        {
7948          ssize_t
7949            alpha;
7950
7951          alpha=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,value);
7952          if (alpha < 0)
7953            ThrowMSLException(OptionError,"UnrecognizedType",value);
7954          if (image != (Image *) NULL)
7955            (void) SetImageAlphaChannel(image,(AlphaChannelOption) alpha,
7956              exception);
7957          break;
7958        }
7959      if (LocaleCompare(keyword,"antialias") == 0)
7960        {
7961          ssize_t
7962            antialias;
7963
7964          antialias=ParseCommandOption(MagickBooleanOptions,MagickFalse,value);
7965          if (antialias < 0)
7966            ThrowMSLException(OptionError,"UnrecognizedGravityType",value);
7967          image_info->antialias=(MagickBooleanType) antialias;
7968          break;
7969        }
7970      if (LocaleCompare(keyword,"area-limit") == 0)
7971        {
7972          MagickSizeType
7973            limit;
7974
7975          limit=MagickResourceInfinity;
7976          if (LocaleCompare(value,"unlimited") != 0)
7977            limit=(MagickSizeType) StringToDoubleInterval(value,100.0);
7978          (void) SetMagickResourceLimit(AreaResource,limit);
7979          break;
7980        }
7981      if (LocaleCompare(keyword,"attenuate") == 0)
7982        {
7983          (void) SetImageOption(image_info,keyword,value);
7984          break;
7985        }
7986      if (LocaleCompare(keyword,"authenticate") == 0)
7987        {
7988          (void) CloneString(&image_info->density,value);
7989          break;
7990        }
7991      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
7992      break;
7993    }
7994    case 'B':
7995    case 'b':
7996    {
7997      if (LocaleCompare(keyword,"background") == 0)
7998        {
7999          (void) QueryColorCompliance(value,AllCompliance,
8000            &image_info->background_color,exception);
8001          break;
8002        }
8003      if (LocaleCompare(keyword,"blue-primary") == 0)
8004        {
8005          if (image == (Image *) NULL)
8006            break;
8007          flags=ParseGeometry(value,&geometry_info);
8008          image->chromaticity.blue_primary.x=geometry_info.rho;
8009          image->chromaticity.blue_primary.y=geometry_info.sigma;
8010          if ((flags & SigmaValue) == 0)
8011            image->chromaticity.blue_primary.y=
8012              image->chromaticity.blue_primary.x;
8013          break;
8014        }
8015      if (LocaleCompare(keyword,"bordercolor") == 0)
8016        {
8017          (void) QueryColorCompliance(value,AllCompliance,
8018            &image_info->border_color,exception);
8019          break;
8020        }
8021      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
8022      break;
8023    }
8024    case 'D':
8025    case 'd':
8026    {
8027      if (LocaleCompare(keyword,"density") == 0)
8028        {
8029          (void) CloneString(&image_info->density,value);
8030          (void) CloneString(&draw_info->density,value);
8031          break;
8032        }
8033      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
8034      break;
8035    }
8036    case 'F':
8037    case 'f':
8038    {
8039      if (LocaleCompare(keyword,"fill") == 0)
8040        {
8041          (void) QueryColorCompliance(value,AllCompliance,&draw_info->fill,
8042            exception);
8043          (void) SetImageOption(image_info,keyword,value);
8044          break;
8045        }
8046      if (LocaleCompare(keyword,"filename") == 0)
8047        {
8048          (void) CopyMagickString(image_info->filename,value,MaxTextExtent);
8049          break;
8050        }
8051      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
8052      break;
8053    }
8054    case 'G':
8055    case 'g':
8056    {
8057      if (LocaleCompare(keyword,"gravity") == 0)
8058        {
8059          ssize_t
8060            gravity;
8061
8062          gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,value);
8063          if (gravity < 0)
8064            ThrowMSLException(OptionError,"UnrecognizedGravityType",value);
8065          (void) SetImageOption(image_info,keyword,value);
8066          break;
8067        }
8068      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
8069      break;
8070    }
8071    case 'I':
8072    case 'i':
8073    {
8074      if (LocaleCompare(keyword,"id") == 0)
8075        {
8076          (void) SetImageProperty(attributes,keyword,value,exception);
8077          break;
8078        }
8079      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
8080      break;
8081    }
8082    case 'M':
8083    case 'm':
8084    {
8085      if (LocaleCompare(keyword,"magick") == 0)
8086        {
8087          (void) CopyMagickString(image_info->magick,value,MaxTextExtent);
8088          break;
8089        }
8090      if (LocaleCompare(keyword,"mattecolor") == 0)
8091        {
8092          (void) QueryColorCompliance(value,AllCompliance,
8093            &image_info->matte_color,exception);
8094          break;
8095        }
8096      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
8097      break;
8098    }
8099    case 'P':
8100    case 'p':
8101    {
8102      if (LocaleCompare(keyword,"pointsize") == 0)
8103        {
8104          image_info->pointsize=StringToDouble(value,(char **) NULL);
8105          draw_info->pointsize=StringToDouble(value,(char **) NULL);
8106          break;
8107        }
8108      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
8109      break;
8110    }
8111    case 'Q':
8112    case 'q':
8113    {
8114      if (LocaleCompare(keyword,"quality") == 0)
8115        {
8116          image_info->quality=StringToLong(value);
8117          if (image == (Image *) NULL)
8118            break;
8119          image->quality=StringToLong(value);
8120          break;
8121        }
8122      break;
8123    }
8124    case 'S':
8125    case 's':
8126    {
8127      if (LocaleCompare(keyword,"size") == 0)
8128        {
8129          (void) CloneString(&image_info->size,value);
8130          break;
8131        }
8132      if (LocaleCompare(keyword,"stroke") == 0)
8133        {
8134          (void) QueryColorCompliance(value,AllCompliance,&draw_info->stroke,
8135            exception);
8136          (void) SetImageOption(image_info,keyword,value);
8137          break;
8138        }
8139      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
8140      break;
8141    }
8142    default:
8143    {
8144      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
8145      break;
8146    }
8147  }
8148  return(MagickTrue);
8149}
8150#endif
8151
8152/*
8153%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8154%                                                                             %
8155%                                                                             %
8156%                                                                             %
8157%   U n r e g i s t e r M S L I m a g e                                       %
8158%                                                                             %
8159%                                                                             %
8160%                                                                             %
8161%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8162%
8163%  UnregisterMSLImage() removes format registrations made by the
8164%  MSL module from the list of supported formats.
8165%
8166%  The format of the UnregisterMSLImage method is:
8167%
8168%      UnregisterMSLImage(void)
8169%
8170*/
8171ModuleExport void UnregisterMSLImage(void)
8172{
8173  (void) UnregisterMagickInfo("MSL");
8174}
8175
8176#if defined(MAGICKCORE_XML_DELEGATE)
8177/*
8178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8179%                                                                             %
8180%                                                                             %
8181%                                                                             %
8182%   W r i t e M S L I m a g e                                                 %
8183%                                                                             %
8184%                                                                             %
8185%                                                                             %
8186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8187%
8188%  WriteMSLImage() writes an image to a file in MVG image format.
8189%
8190%  The format of the WriteMSLImage method is:
8191%
8192%      MagickBooleanType WriteMSLImage(const ImageInfo *image_info,
8193%        Image *image,ExceptionInfo *exception)
8194%
8195%  A description of each parameter follows.
8196%
8197%    o image_info: the image info.
8198%
8199%    o image:  The image.
8200%
8201%    o exception: return any errors or warnings in this structure.
8202%
8203*/
8204static MagickBooleanType WriteMSLImage(const ImageInfo *image_info,Image *image,
8205  ExceptionInfo *exception)
8206{
8207  assert(image_info != (const ImageInfo *) NULL);
8208  assert(image_info->signature == MagickSignature);
8209  assert(image != (Image *) NULL);
8210  assert(image->signature == MagickSignature);
8211  if (image->debug != MagickFalse)
8212    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
8213  (void) ReferenceImage(image);
8214  (void) ProcessMSLScript(image_info,&image,exception);
8215  return(MagickTrue);
8216}
8217#endif
8218