operation.c revision d2cdc860e4860173edebd04bf4a33437724edece
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%             OOO  PPPP  EEEE RRRR   AA  TTTTTT III  OOO  N   N               %
7%            O   O P   P E    R   R A  A   TT    I  O   O NN  N               %
8%            O   O PPPP  EEE  RRRR  AAAA   TT    I  O   O N N N               %
9%            O   O P     E    R R   A  A   TT    I  O   O N  NN               %
10%             OOO  P     EEEE R  RR A  A   TT   III  OOO  N   N               %
11%                                                                             %
12%                                                                             %
13%                         MagickWand Module Methods                           %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                               September 2011                                %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36% Apply the given options (settings, and simple, or sequence operations) to
37% the given image(s) according to the current "image_info" and "draw_info"
38% settings.
39%
40% The final goal is to allow the execution in a strict one option at a time
41% manner that is needed for 'pipelining and file scripting' of options in
42% IMv7.
43%
44% Anthony Thyssen, Sept 2011
45*/
46#if 0
47
48/*
49  Include declarations.
50*/
51#include "MagickWand/studio.h"
52#include "MagickWand/MagickWand.h"
53#include "MagickWand/mogrify-private.h"
54#include "MagickCore/monitor-private.h"
55#include "MagickCore/thread-private.h"
56#include "MagickCore/string-private.h"
57
58/*
59  Define declarations.
60*/
61#define UndefinedCompressionQuality  0UL
62/*
63  Constant declaration. (temporary exports)
64*/
65static const char
66  BackgroundColor[] = "#fff",  /* white */
67  BorderColor[] = "#dfdfdf",  /* gray */
68  MatteColor[] = "#bdbdbd";  /* gray */
69
70/*
71** Function to report on the progress of image operations
72*/
73static MagickBooleanType MonitorProgress(const char *text,
74  const MagickOffsetType offset,const MagickSizeType extent,
75  void *wand_unused(client_data))
76{
77  char
78    message[MaxTextExtent],
79    tag[MaxTextExtent];
80
81  const char
82    *locale_message;
83
84  register char
85    *p;
86
87  if (extent < 2)
88    return(MagickTrue);
89  (void) CopyMagickMemory(tag,text,MaxTextExtent);
90  p=strrchr(tag,'/');
91  if (p != (char *) NULL)
92    *p='\0';
93  (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
94  locale_message=GetLocaleMessage(message);
95  if (locale_message == message)
96    locale_message=tag;
97  if (p == (char *) NULL)
98    (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
99      locale_message,(long) offset,(unsigned long) extent,(long)
100      (100L*offset/(extent-1)));
101  else
102    (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
103      locale_message,p+1,(long) offset,(unsigned long) extent,(long)
104      (100L*offset/(extent-1)));
105  if (offset == (MagickOffsetType) (extent-1))
106    (void) FormatLocaleFile(stderr,"\n");
107  (void) fflush(stderr);
108  return(MagickTrue);
109}
110
111/*
112** GetImageCache() will read an image into a image cache if not already
113** present then return the image that is in the cache under that filename.
114*/
115static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
116  ExceptionInfo *exception)
117{
118  char
119    key[MaxTextExtent];
120
121  ExceptionInfo
122    *sans_exception;
123
124  Image
125    *image;
126
127  ImageInfo
128    *read_info;
129
130  (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
131  sans_exception=AcquireExceptionInfo();
132  image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
133  sans_exception=DestroyExceptionInfo(sans_exception);
134  if (image != (Image *) NULL)
135    return(image);
136  read_info=CloneImageInfo(image_info);
137  (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
138  image=ReadImage(read_info,exception);
139  read_info=DestroyImageInfo(read_info);
140  if (image != (Image *) NULL)
141    (void) SetImageRegistry(ImageRegistryType,key,image,exception);
142  return(image);
143}
144
145/*
146  SparseColorOption() parse the complex -sparse-color argument into an
147  an array of floating point values than call SparseColorImage().
148  Argument is a complex mix of floating-point pixel coodinates, and color
149  specifications (or direct floating point numbers).  The number of floats
150  needed to represent a color varies depending on teh current channel
151  setting.
152*/
153static Image *SparseColorOption(const Image *image,
154  const SparseColorMethod method,const char *arguments,
155  const MagickBooleanType color_from_image,ExceptionInfo *exception)
156{
157  char
158    token[MaxTextExtent];
159
160  const char
161    *p;
162
163  double
164    *sparse_arguments;
165
166  Image
167    *sparse_image;
168
169  PixelInfo
170    color;
171
172  MagickBooleanType
173    error;
174
175  register size_t
176    x;
177
178  size_t
179    number_arguments,
180    number_colors;
181
182  assert(image != (Image *) NULL);
183  assert(image->signature == MagickSignature);
184  if (image->debug != MagickFalse)
185    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
186  assert(exception != (ExceptionInfo *) NULL);
187  assert(exception->signature == MagickSignature);
188  /*
189    Limit channels according to image - and add up number of color channel.
190  */
191  number_colors=0;
192  if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
193    number_colors++;
194  if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
195    number_colors++;
196  if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
197    number_colors++;
198  if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
199      (image->colorspace == CMYKColorspace))
200    number_colors++;
201  if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
202      (image->matte != MagickFalse))
203    number_colors++;
204
205  /*
206    Read string, to determine number of arguments needed,
207  */
208  p=arguments;
209  x=0;
210  while( *p != '\0' )
211  {
212    GetMagickToken(p,&p,token);
213    if ( token[0] == ',' ) continue;
214    if ( isalpha((int) token[0]) || token[0] == '#' ) {
215      if ( color_from_image ) {
216        (void) ThrowMagickException(exception,GetMagickModule(),
217            OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
218            "Color arg given, when colors are coming from image");
219        return( (Image *)NULL);
220      }
221      x += number_colors;  /* color argument */
222    }
223    else {
224      x++;   /* floating point argument */
225    }
226  }
227  error=MagickTrue;
228  if ( color_from_image ) {
229    /* just the control points are being given */
230    error = ( x % 2 != 0 ) ? MagickTrue : MagickFalse;
231    number_arguments=(x/2)*(2+number_colors);
232  }
233  else {
234    /* control points and color values */
235    error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
236    number_arguments=x;
237  }
238  if ( error ) {
239    (void) ThrowMagickException(exception,GetMagickModule(),
240               OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
241               "Invalid number of Arguments");
242    return( (Image *)NULL);
243  }
244
245  /* Allocate and fill in the floating point arguments */
246  sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
247    sizeof(*sparse_arguments));
248  if (sparse_arguments == (double *) NULL) {
249    (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
250      "MemoryAllocationFailed","%s","SparseColorOption");
251    return( (Image *)NULL);
252  }
253  (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
254    sizeof(*sparse_arguments));
255  p=arguments;
256  x=0;
257  while( *p != '\0' && x < number_arguments ) {
258    /* X coordinate */
259    token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
260    if ( token[0] == '\0' ) break;
261    if ( isalpha((int) token[0]) || token[0] == '#' ) {
262      (void) ThrowMagickException(exception,GetMagickModule(),
263            OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
264            "Color found, instead of X-coord");
265      error = MagickTrue;
266      break;
267    }
268    sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
269    /* Y coordinate */
270    token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
271    if ( token[0] == '\0' ) break;
272    if ( isalpha((int) token[0]) || token[0] == '#' ) {
273      (void) ThrowMagickException(exception,GetMagickModule(),
274            OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
275            "Color found, instead of Y-coord");
276      error = MagickTrue;
277      break;
278    }
279    sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
280    /* color values for this control point */
281#if 0
282    if ( (color_from_image ) {
283      /* get color from image */
284      /* HOW??? */
285    }
286    else
287#endif
288    {
289      /* color name or function given in string argument */
290      token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
291      if ( token[0] == '\0' ) break;
292      if ( isalpha((int) token[0]) || token[0] == '#' ) {
293        /* Color string given */
294        (void) QueryMagickColorCompliance(token,AllCompliance,&color,
295                  exception);
296        if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
297          sparse_arguments[x++] = QuantumScale*color.red;
298        if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
299          sparse_arguments[x++] = QuantumScale*color.green;
300        if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
301          sparse_arguments[x++] = QuantumScale*color.blue;
302        if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
303            (image->colorspace == CMYKColorspace))
304          sparse_arguments[x++] = QuantumScale*color.black;
305        if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
306            (image->matte != MagickFalse))
307          sparse_arguments[x++] = QuantumScale*color.alpha;
308      }
309      else {
310        /* Colors given as a set of floating point values - experimental */
311        /* NB: token contains the first floating point value to use! */
312        if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
313          {
314          while ( token[0] == ',' ) GetMagickToken(p,&p,token);
315          if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
316            break;
317          sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
318          token[0] = ','; /* used this token - get another */
319        }
320        if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
321          {
322          while ( token[0] == ',' ) GetMagickToken(p,&p,token);
323          if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
324            break;
325          sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
326          token[0] = ','; /* used this token - get another */
327        }
328        if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
329          {
330          while ( token[0] == ',' ) GetMagickToken(p,&p,token);
331          if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
332            break;
333          sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
334          token[0] = ','; /* used this token - get another */
335        }
336        if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
337            (image->colorspace == CMYKColorspace))
338          {
339          while ( token[0] == ',' ) GetMagickToken(p,&p,token);
340          if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
341            break;
342          sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
343          token[0] = ','; /* used this token - get another */
344        }
345        if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
346            (image->matte != MagickFalse))
347          {
348          while ( token[0] == ',' ) GetMagickToken(p,&p,token);
349          if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
350            break;
351          sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
352          token[0] = ','; /* used this token - get another */
353        }
354      }
355    }
356  }
357  if ( number_arguments != x && !error ) {
358    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
359      "InvalidArgument","`%s': %s","sparse-color","Argument Parsing Error");
360    sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
361    return( (Image *)NULL);
362  }
363  if ( error )
364    return( (Image *)NULL);
365
366  /* Call the Interpolation function with the parsed arguments */
367  sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
368    exception);
369  sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
370  return( sparse_image );
371}
372
373/*
374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375%                                                                             %
376%                                                                             %
377%                                                                             %
378+   A p p l y S e t t i n g O p t i o n                                       %
379%                                                                             %
380%                                                                             %
381%                                                                             %
382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383%
384%  ApplySettingOption() saves the given single settings option into a CLI wand
385%  holding the image_info, draw_info, quantize_info structures that is later
386%  used for reading, processing, and writing images.
387%
388%  No image in the wand is actually modified (setting options only)
389%
390%  The format of the ApplySettingOption method is:
391%
392%    MagickBooleanType ApplySettingOption(MagickWand *wand,
393%        const int argc, const char **argv,ExceptionInfo *exception)
394%
395%  A description of each parameter follows:
396%
397%    o wand: structure holding settings to be applied
398%
399%    o argc: Specifies a pointer to an integer describing the number of
400%      elements in the argument vector.
401%
402%    o argv: Specifies a pointer to a text array containing the command line
403%      arguments.
404%
405%    o exception: return any errors or warnings in this structure.
406%
407*/
408WandExport MagickBooleanType ApplySettingsOption(ImageInfo *image_info,
409  const int argc,const char **argv,ExceptionInfo *exception)
410{
411  GeometryInfo
412    geometry_info;
413
414  ImageInfo
415    *image_info;
416
417  DrawInfo
418    *draw_info;
419
420  const char
421    *option;
422
423  assert(wand != (MagickWand *) NULL);
424  assert(wand->signature == WandSignature);
425  assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
426  assert(wand->quantize_info == (QuantizeInfo *) NULL);
427  if (wand->debug != MagickFalse)
428    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
429  if (argc < 0)
430    return(MagickTrue);
431
432  option=argv[0]+1;
433  image_info=wand->image_info;
434  draw_info=wand->_info;
435
436#define DeleteOption (const char*)NULL
437#define IfSetOption ((*argv[0])=='-')
438
439  switch (*option)
440  {
441    case 'a':
442    {
443      if (LocaleCompare("adjoin",option) == 0)
444        {
445          image_info->adjoin = IfSetOption ? MagickTrue : MagickFalse;
446          break;
447        }
448      if (LocaleCompare("affine",option) == 0)
449        {
450          if (IfSetOption)
451            (void) ParseAffineGeometry(argv[1],draw_info->affine,
452               exception);
453          else
454            GetAffineMatrix(draw_info->affine);
455          break;
456        }
457      if (LocaleCompare("antialias",option) == 0)
458        {
459          image_info->antialias =
460          draw_info->stroke_antialias =
461          draw_info->text_antialias =
462               IfSetOption ? MagickTrue : MagickFalse;
463          break;
464        }
465      if (LocaleCompare("attenuate",option) == 0)
466        {
467          (void) SetImageOption(image_info,option,
468               IfSetOption ? argv[1] : DeleteOption);
469          break;
470        }
471      if (LocaleCompare("authenticate",option) == 0)
472        {
473          (void) SetImageOption(image_info,option,
474               IfSetOption ? argv[1] : DeleteOption);
475          break;
476        }
477      break;
478    }
479    case 'b':
480    {
481      if (LocaleCompare("background",option) == 0)
482        {
483          /* FUTURE: both image_info attribute & ImageOption in use!
484             Note that +background, means fall-back to image attribute
485             so ImageOption is deleted, not set to a default.
486          */
487          if (IfSetOption)
488            {
489              (void) DeleteImageOption(image_info,option);
490              (void) QueryColorCompliance(BackgroundColor,AllCompliance,
491                    image_info->background_color,exception);
492              break;
493            }
494          (void) SetImageOption(image_info,option,argv[1]);
495          (void) QueryColorCompliance(argv[1],AllCompliance,
496              image_info->background_color,exception);
497          break;
498        }
499      if (LocaleCompare("bias",option) == 0)
500        {
501          /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
502             as it is actually rarely used except in direct convolve
503             Usage outside direct convolve is actally non-sensible!
504          */
505          (void) SetImageOption(image_info,option,
506               IfSetOption ? argv[1] : "0");
507          break;
508        }
509      if (LocaleCompare("black-point-compensation",option) == 0)
510        {
511          (void) SetImageOption(image_info,option,
512               IfSetOption ? "true" : "false" );
513          break;
514        }
515      if (LocaleCompare("blue-primary",option) == 0)
516        {
517          (void) SetImageOption(image_info,option,
518               IfSetOption ? argv[1] : "0" );
519          break;
520        }
521      if (LocaleCompare("bordercolor",option) == 0)
522        {
523          /* FUTURE: both image_info attribute & ImageOption in use! */
524          if (IfSetOption)
525            {
526              (void) SetImageOption(image_info,option,argv[1]);
527              (void) QueryColorCompliance(argv[1],AllCompliece,
528                  &image_info->border_color,exception);
529              (void) QueryColorCompliance(argv[1],AllCompliance,
530                  &draw_info->border_color,exception);
531              break;
532            }
533          (void) DeleteImageOption(image_info,option);
534          (void) QueryColorCompliance(BorderColor,AllCompliance,
535            &image_info->border_color,exception);
536          (void) QueryColorCompliance(BorderColor,AllCompliance,
537            &draw_info->border_color,exception);
538          break;
539        }
540      if (LocaleCompare("box",option) == 0)
541        {
542          const char
543            *value = IfSetOption ? argv[1] : "none";
544          (void) SetImageOption(image_info,option,value);
545          (void) QueryColorCompliance(value,AllCompliance,
546               &draw_info->undercolor,exception);
547          break;
548        }
549      break;
550    }
551    case 'c':
552    {
553      if (LocaleCompare("cache",option) == 0)
554        {
555          MagickSizeType
556            limit;
557
558          limit=MagickResourceInfinity;
559          if (LocaleCompare("unlimited",argv[1]) != 0)
560            limit=(MagickSizeType) SiPrefixToDouble(argv[1],100.0);
561          (void) SetMagickResourceLimit(MemoryResource,limit);
562          (void) SetMagickResourceLimit(MapResource,2*limit);
563          break;
564        }
565      if (LocaleCompare("caption",option) == 0)
566        {
567          (void) SetImageOption(image_info,option,
568               IfSetOption ? argv[1] : DeleteOption);
569          break;
570        }
571      if (LocaleCompare("channel",option) == 0)
572        {
573          image_info->channel=(ChannelType) (
574               IfSetOption ? ParseChannelOption(argv[1]) : DefaultChannels );
575          /* This is also a SimpleImageOperator */
576          break;
577        }
578      if (LocaleCompare("colorspace",option) == 0)
579        {
580          /* This is also a SimpleImageOperator */
581          /* Undefined colorspace means don't modify images */
582          image_info->colorspace=UndefinedColorspace;
583          if (IfSetOption)
584            image_info->colorspace=(ColorspaceType) ParseCommandOption(
585                 MagickColorspaceOptions,MagickFalse,argv[1])
586          break;
587        }
588      if (LocaleCompare("comment",option) == 0)
589        {
590          (void) SetImageOption(image_info,option,
591               IfSetOption ? argv[1] : DeleteOption);
592          break;
593        }
594      if (LocaleCompare("compose",option) == 0)
595        {
596          /* FUTURE: What should be used?  image_info  or ImageOption ???
597             The former is more efficent, the later cristy prefers!
598          */
599          const char
600            *value;
601
602          value = IfSetOption ? argv[1] : "undefined";
603          (void) SetImageOption(image_info,option,value);
604          image_info->compose=(CompositeOperator) ParseCommandOption(
605               MagickComposeOptions,MagickFalse,value);
606          break;
607        }
608      if (LocaleCompare("compress",option) == 0)
609        {
610          if (*argv[0] == '+')
611            {
612              image_info->compression=UndefinedCompression;
613              (void) SetImageOption(image_info,option,"undefined");
614              break;
615            }
616          image_info->compression=(CompressionType) ParseCommandOption(
617            MagickCompressOptions,MagickFalse,argv[1]);
618          (void) SetImageOption(image_info,option,argv[1]);
619          break;
620        }
621      break;
622    }
623    case 'd':
624    {
625      if (LocaleCompare("debug",option) == 0)
626        {
627          if (*argv[0] == '+')
628            (void) SetLogEventMask("none");
629          else
630            (void) SetLogEventMask(argv[1]);
631          image_info->debug=IsEventLogging();
632          break;
633        }
634      if (LocaleCompare("define",option) == 0)
635        {
636          if (*argv[0] == '+')
637            {
638              if (LocaleNCompare(argv[1],"registry:",9) == 0)
639                (void) DeleteImageRegistry(argv[1]+9);
640              else
641                (void) DeleteImageOption(image_info,argv[1]);
642              break;
643            }
644          if (LocaleNCompare(argv[1],"registry:",9) == 0)
645            {
646              (void) DefineImageRegistry(StringRegistryType,argv[1]+9,
647                exception);
648              break;
649            }
650          (void) DefineImageOption(image_info,argv[1]);
651          break;
652        }
653      if (LocaleCompare("delay",option) == 0)
654        {
655          if (*argv[0] == '+')
656            {
657              (void) SetImageOption(image_info,option,"0");
658              break;
659            }
660          (void) SetImageOption(image_info,option,argv[1]);
661          break;
662        }
663      if (LocaleCompare("density",option) == 0)
664        {
665          /*
666            Set image density.
667          */
668          if (*argv[0] == '+')
669            {
670              if (image_info->density != (char *) NULL)
671                image_info->density=DestroyString(image_info->density);
672              (void) SetImageOption(image_info,option,"72");
673              break;
674            }
675          (void) CloneString(&image_info->density,argv[1]);
676          (void) SetImageOption(image_info,option,argv[1]);
677          break;
678        }
679      if (LocaleCompare("depth",option) == 0)
680        {
681          if (*argv[0] == '+')
682            {
683              image_info->depth=MAGICKCORE_QUANTUM_DEPTH;
684              break;
685            }
686          image_info->depth=StringToUnsignedLong(argv[1]);
687          break;
688        }
689      if (LocaleCompare("direction",option) == 0)
690        {
691          if (*argv[0] == '+')
692            {
693              (void) SetImageOption(image_info,option,"undefined");
694              break;
695            }
696          (void) SetImageOption(image_info,option,argv[1]);
697          break;
698        }
699      if (LocaleCompare("display",option) == 0)
700        {
701          if (*argv[0] == '+')
702            {
703              if (image_info->server_name != (char *) NULL)
704                image_info->server_name=DestroyString(
705                  image_info->server_name);
706              break;
707            }
708          (void) CloneString(&image_info->server_name,argv[1]);
709          break;
710        }
711      if (LocaleCompare("dispose",option) == 0)
712        {
713          if (*argv[0] == '+')
714            {
715              (void) SetImageOption(image_info,option,"undefined");
716              break;
717            }
718          (void) SetImageOption(image_info,option,argv[1]);
719          break;
720        }
721      if (LocaleCompare("dither",option) == 0)
722        {
723          if (*argv[0] == '+')
724            {
725              image_info->dither=MagickFalse;
726              (void) SetImageOption(image_info,option,"none");
727              break;
728            }
729          (void) SetImageOption(image_info,option,argv[1]);
730          image_info->dither=MagickTrue;
731          break;
732        }
733      break;
734    }
735    case 'e':
736    {
737      if (LocaleCompare("encoding",option) == 0)
738        {
739          if (*argv[0] == '+')
740            {
741              (void) SetImageOption(image_info,option,"undefined");
742              break;
743            }
744          (void) SetImageOption(image_info,option,argv[1]);
745          break;
746        }
747      if (LocaleCompare("endian",option) == 0)
748        {
749          if (*argv[0] == '+')
750            {
751              image_info->endian=UndefinedEndian;
752              (void) SetImageOption(image_info,option,"undefined");
753              break;
754            }
755          image_info->endian=(EndianType) ParseCommandOption(
756            MagickEndianOptions,MagickFalse,argv[1]);
757          (void) SetImageOption(image_info,option,argv[1]);
758          break;
759        }
760      if (LocaleCompare("extract",option) == 0)
761        {
762          /*
763            Set image extract geometry.
764          */
765          if (*argv[0] == '+')
766            {
767              if (image_info->extract != (char *) NULL)
768                image_info->extract=DestroyString(image_info->extract);
769              break;
770            }
771          (void) CloneString(&image_info->extract,argv[1]);
772          break;
773        }
774      break;
775    }
776    case 'f':
777    {
778      if (LocaleCompare("fill",option) == 0)
779        {
780          if (*argv[0] == '+')
781            {
782              (void) SetImageOption(image_info,option,"none");
783              break;
784            }
785          (void) SetImageOption(image_info,option,argv[1]);
786          break;
787        }
788      if (LocaleCompare("filter",option) == 0)
789        {
790          if (*argv[0] == '+')
791            {
792              (void) SetImageOption(image_info,option,"undefined");
793              break;
794            }
795          (void) SetImageOption(image_info,option,argv[1]);
796          break;
797        }
798      if (LocaleCompare("font",option) == 0)
799        {
800          if (*argv[0] == '+')
801            {
802              if (image_info->font != (char *) NULL)
803                image_info->font=DestroyString(image_info->font);
804              break;
805            }
806          (void) CloneString(&image_info->font,argv[1]);
807          break;
808        }
809      if (LocaleCompare("format",option) == 0)
810        {
811          register const char
812            *q;
813
814          for (q=strchr(argv[1],'%'); q != (char *) NULL; q=strchr(q+1,'%'))
815            if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
816              image_info->ping=MagickFalse;
817          (void) SetImageOption(image_info,option,argv[1]);
818          break;
819        }
820      if (LocaleCompare("fuzz",option) == 0)
821        {
822          if (*argv[0] == '+')
823            {
824              image_info->fuzz=0.0;
825              (void) SetImageOption(image_info,option,"0");
826              break;
827            }
828          image_info->fuzz=SiPrefixToDouble(argv[1],(double) QuantumRange+
829            1.0);
830          (void) SetImageOption(image_info,option,argv[1]);
831          break;
832        }
833      break;
834    }
835    case 'g':
836    {
837      if (LocaleCompare("gravity",option) == 0)
838        {
839          if (*argv[0] == '+')
840            {
841              (void) SetImageOption(image_info,option,"undefined");
842              break;
843            }
844          (void) SetImageOption(image_info,option,argv[1]);
845          break;
846        }
847      if (LocaleCompare("green-primary",option) == 0)
848        {
849          if (*argv[0] == '+')
850            {
851              (void) SetImageOption(image_info,option,"0.0");
852              break;
853            }
854          (void) SetImageOption(image_info,option,argv[1]);
855          break;
856        }
857      break;
858    }
859    case 'i':
860    {
861      if (LocaleCompare("intent",option) == 0)
862        {
863          if (*argv[0] == '+')
864            {
865              (void) SetImageOption(image_info,option,"undefined");
866              break;
867            }
868          (void) SetImageOption(image_info,option,argv[1]);
869          break;
870        }
871      if (LocaleCompare("interlace",option) == 0)
872        {
873          if (*argv[0] == '+')
874            {
875              image_info->interlace=UndefinedInterlace;
876              (void) SetImageOption(image_info,option,"undefined");
877              break;
878            }
879          image_info->interlace=(InterlaceType) ParseCommandOption(
880            MagickInterlaceOptions,MagickFalse,argv[1]);
881          (void) SetImageOption(image_info,option,argv[1]);
882          break;
883        }
884      if (LocaleCompare("interline-spacing",option) == 0)
885        {
886          if (*argv[0] == '+')
887            {
888              (void) SetImageOption(image_info,option,"undefined");
889              break;
890            }
891          (void) SetImageOption(image_info,option,argv[1]);
892          break;
893        }
894      if (LocaleCompare("interpolate",option) == 0)
895        {
896          if (*argv[0] == '+')
897            {
898              (void) SetImageOption(image_info,option,"undefined");
899              break;
900            }
901          (void) SetImageOption(image_info,option,argv[1]);
902          break;
903        }
904      if (LocaleCompare("interword-spacing",option) == 0)
905        {
906          if (*argv[0] == '+')
907            {
908              (void) SetImageOption(image_info,option,"undefined");
909              break;
910            }
911          (void) SetImageOption(image_info,option,argv[1]);
912          break;
913        }
914      break;
915    }
916    case 'k':
917    {
918      if (LocaleCompare("kerning",option) == 0)
919        {
920          if (*argv[0] == '+')
921            {
922              (void) SetImageOption(image_info,option,"undefined");
923              break;
924            }
925          (void) SetImageOption(image_info,option,argv[1]);
926          break;
927        }
928      break;
929    }
930    case 'l':
931    {
932      if (LocaleCompare("label",option) == 0)
933        {
934          if (*argv[0] == '+')
935            {
936              (void) DeleteImageOption(image_info,option);
937              break;
938            }
939          (void) SetImageOption(image_info,option,argv[1]);
940          break;
941        }
942      if (LocaleCompare("limit",option) == 0)
943        {
944          MagickSizeType
945            limit;
946
947          ResourceType
948            type;
949
950          if (*argv[0] == '+')
951            break;
952          type=(ResourceType) ParseCommandOption(MagickResourceOptions,
953            MagickFalse,argv[1]);
954          limit=MagickResourceInfinity;
955          if (LocaleCompare("unlimited",argv[2]) != 0)
956            limit=(MagickSizeType) SiPrefixToDouble(argv[2],100.0);
957          (void) SetMagickResourceLimit(type,limit);
958          break;
959        }
960      if (LocaleCompare("list",option) == 0)
961        {
962          ssize_t
963            list;
964
965          /*
966            Display configuration list.
967          */
968          list=ParseCommandOption(MagickListOptions,MagickFalse,argv[1]);
969          switch (list)
970          {
971            case MagickCoderOptions:
972            {
973              (void) ListCoderInfo((FILE *) NULL,exception);
974              break;
975            }
976            case MagickColorOptions:
977            {
978              (void) ListColorInfo((FILE *) NULL,exception);
979              break;
980            }
981            case MagickConfigureOptions:
982            {
983              (void) ListConfigureInfo((FILE *) NULL,exception);
984              break;
985            }
986            case MagickDelegateOptions:
987            {
988              (void) ListDelegateInfo((FILE *) NULL,exception);
989              break;
990            }
991            case MagickFontOptions:
992            {
993              (void) ListTypeInfo((FILE *) NULL,exception);
994              break;
995            }
996            case MagickFormatOptions:
997            {
998              (void) ListMagickInfo((FILE *) NULL,exception);
999              break;
1000            }
1001            case MagickLocaleOptions:
1002            {
1003              (void) ListLocaleInfo((FILE *) NULL,exception);
1004              break;
1005            }
1006            case MagickLogOptions:
1007            {
1008              (void) ListLogInfo((FILE *) NULL,exception);
1009              break;
1010            }
1011            case MagickMagicOptions:
1012            {
1013              (void) ListMagicInfo((FILE *) NULL,exception);
1014              break;
1015            }
1016            case MagickMimeOptions:
1017            {
1018              (void) ListMimeInfo((FILE *) NULL,exception);
1019              break;
1020            }
1021            case MagickModuleOptions:
1022            {
1023              (void) ListModuleInfo((FILE *) NULL,exception);
1024              break;
1025            }
1026            case MagickPolicyOptions:
1027            {
1028              (void) ListPolicyInfo((FILE *) NULL,exception);
1029              break;
1030            }
1031            case MagickResourceOptions:
1032            {
1033              (void) ListMagickResourceInfo((FILE *) NULL,exception);
1034              break;
1035            }
1036            case MagickThresholdOptions:
1037            {
1038              (void) ListThresholdMaps((FILE *) NULL,exception);
1039              break;
1040            }
1041            default:
1042            {
1043              (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
1044                exception);
1045              break;
1046            }
1047          }
1048          break;
1049        }
1050      if (LocaleCompare("log",option) == 0)
1051        {
1052          if (*argv[0] == '+')
1053            break;
1054          (void) SetLogFormat(argv[1]);
1055          break;
1056        }
1057      if (LocaleCompare("loop",option) == 0)
1058        {
1059          if (*argv[0] == '+')
1060            {
1061              (void) SetImageOption(image_info,option,"0");
1062              break;
1063            }
1064          (void) SetImageOption(image_info,option,argv[1]);
1065          break;
1066        }
1067      break;
1068    }
1069    case 'm':
1070    {
1071      if (LocaleCompare("matte",option) == 0)
1072        {
1073          if (*argv[0] == '+')
1074            {
1075              (void) SetImageOption(image_info,option,"false");
1076              break;
1077            }
1078          (void) SetImageOption(image_info,option,"true");
1079          break;
1080        }
1081      if (LocaleCompare("mattecolor",option) == 0)
1082        {
1083          if (*argv[0] == '+')
1084            {
1085              (void) SetImageOption(image_info,option,argv[1]);
1086              (void) QueryColorCompliance(MatteColor,AllCompliance,
1087                &image_info->matte_color,exception);
1088              break;
1089            }
1090          (void) SetImageOption(image_info,option,argv[1]);
1091          (void) QueryColorCompliance(argv[1],AllCompliance,&image_info->matte_color,
1092            exception);
1093          break;
1094        }
1095      if (LocaleCompare("monitor",option) == 0)
1096        {
1097          (void) SetImageInfoProgressMonitor(image_info,MonitorProgress,
1098            (void *) NULL);
1099          break;
1100        }
1101      if (LocaleCompare("monochrome",option) == 0)
1102        {
1103          image_info->monochrome=(*argv[0] == '-') ? MagickTrue : MagickFalse;
1104          break;
1105        }
1106      break;
1107    }
1108    case 'o':
1109    {
1110      if (LocaleCompare("orient",option) == 0)
1111        {
1112          if (*argv[0] == '+')
1113            {
1114              image_info->orientation=UndefinedOrientation;
1115              (void) SetImageOption(image_info,option,"undefined");
1116              break;
1117            }
1118          image_info->orientation=(OrientationType) ParseCommandOption(
1119            MagickOrientationOptions,MagickFalse,argv[1]);
1120          (void) SetImageOption(image_info,option,argv[1]);
1121          break;
1122        }
1123    }
1124    case 'p':
1125    {
1126      if (LocaleCompare("page",option) == 0)
1127        {
1128          char
1129            *canonical_page,
1130            page[MaxTextExtent];
1131
1132          const char
1133            *image_option;
1134
1135          MagickStatusType
1136            flags;
1137
1138          RectangleInfo
1139            geometry;
1140
1141          if (*argv[0] == '+')
1142            {
1143              (void) DeleteImageOption(image_info,option);
1144              (void) CloneString(&image_info->page,(char *) NULL);
1145              break;
1146            }
1147          (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1148          image_option=GetImageOption(image_info,"page");
1149          if (image_option != (const char *) NULL)
1150            flags=ParseAbsoluteGeometry(image_option,&geometry);
1151          canonical_page=GetPageGeometry(argv[1]);
1152          flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1153          canonical_page=DestroyString(canonical_page);
1154          (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1155            (unsigned long) geometry.width,(unsigned long) geometry.height);
1156          if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1157            (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1158              (unsigned long) geometry.width,(unsigned long) geometry.height,
1159              (long) geometry.x,(long) geometry.y);
1160          (void) SetImageOption(image_info,option,page);
1161          (void) CloneString(&image_info->page,page);
1162          break;
1163        }
1164      if (LocaleCompare("pen",option) == 0)
1165        {
1166          if (*argv[0] == '+')
1167            {
1168              (void) SetImageOption(image_info,option,"none");
1169              break;
1170            }
1171          (void) SetImageOption(image_info,option,argv[1]);
1172          break;
1173        }
1174      if (LocaleCompare("ping",option) == 0)
1175        {
1176          image_info->ping=(*argv[0] == '-') ? MagickTrue : MagickFalse;
1177          break;
1178        }
1179      if (LocaleCompare("pointsize",option) == 0)
1180        {
1181          if (*argv[0] == '+')
1182            geometry_info.rho=0.0;
1183          else
1184            (void) ParseGeometry(argv[1],&geometry_info);
1185          image_info->pointsize=geometry_info.rho;
1186          break;
1187        }
1188      if (LocaleCompare("precision",option) == 0)
1189        {
1190          (void) SetMagickPrecision(StringToInteger(argv[1]));
1191          break;
1192        }
1193      if (LocaleCompare("preview",option) == 0)
1194        {
1195          /*
1196            Preview image.
1197          */
1198          if (*argv[0] == '+')
1199            {
1200              image_info->preview_type=UndefinedPreview;
1201              break;
1202            }
1203          image_info->preview_type=(PreviewType) ParseCommandOption(
1204            MagickPreviewOptions,MagickFalse,argv[1]);
1205          break;
1206        }
1207      break;
1208    }
1209    case 'q':
1210    {
1211      if (LocaleCompare("quality",option) == 0)
1212        {
1213          /*
1214            Set image compression quality.
1215          */
1216          if (*argv[0] == '+')
1217            {
1218              image_info->quality=UndefinedCompressionQuality;
1219              (void) SetImageOption(image_info,option,"0");
1220              break;
1221            }
1222          image_info->quality=StringToUnsignedLong(argv[1]);
1223          (void) SetImageOption(image_info,option,argv[1]);
1224          break;
1225        }
1226      if (LocaleCompare("quiet",option) == 0)
1227        {
1228          static WarningHandler
1229            warning_handler = (WarningHandler) NULL;
1230
1231          if (*argv[0] == '+')
1232            {
1233              /*
1234                Restore error or warning messages.
1235              */
1236              warning_handler=SetWarningHandler(warning_handler);
1237              break;
1238            }
1239          /*
1240            Suppress error or warning messages.
1241          */
1242          warning_handler=SetWarningHandler((WarningHandler) NULL);
1243          break;
1244        }
1245      break;
1246    }
1247    case 'r':
1248    {
1249      if (LocaleCompare("red-primary",option) == 0)
1250        {
1251          if (*argv[0] == '+')
1252            {
1253              (void) SetImageOption(image_info,option,"0.0");
1254              break;
1255            }
1256          (void) SetImageOption(image_info,option,argv[1]);
1257          break;
1258        }
1259      break;
1260    }
1261    case 's':
1262    {
1263      if (LocaleCompare("sampling-factor",option) == 0)
1264        {
1265          /*
1266            Set image sampling factor.
1267          */
1268          if (*argv[0] == '+')
1269            {
1270              if (image_info->sampling_factor != (char *) NULL)
1271                image_info->sampling_factor=DestroyString(
1272                  image_info->sampling_factor);
1273              break;
1274            }
1275          (void) CloneString(&image_info->sampling_factor,argv[1]);
1276          break;
1277        }
1278      if (LocaleCompare("scene",option) == 0)
1279        {
1280          /*
1281            Set image scene.
1282          */
1283          if (*argv[0] == '+')
1284            {
1285              image_info->scene=0;
1286              (void) SetImageOption(image_info,option,"0");
1287              break;
1288            }
1289          image_info->scene=StringToUnsignedLong(argv[1]);
1290          (void) SetImageOption(image_info,option,argv[1]);
1291          break;
1292        }
1293      if (LocaleCompare("seed",option) == 0)
1294        {
1295          size_t
1296            seed;
1297
1298          if (*argv[0] == '+')
1299            {
1300              seed=(size_t) time((time_t *) NULL);
1301              SeedPseudoRandomGenerator(seed);
1302              break;
1303            }
1304          seed=StringToUnsignedLong(argv[1]);
1305          SeedPseudoRandomGenerator(seed);
1306          break;
1307        }
1308      if (LocaleCompare("size",option) == 0)
1309        {
1310          /* FUTURE: convert to ImageOption
1311             Look at special handling for "size" in SetImageOption()
1312           */
1313          if (*argv[0] == '+')
1314            {
1315              if (image_info->size != (char *) NULL)
1316                image_info->size=DestroyString(image_info->size);
1317              break;
1318            }
1319          (void) CloneString(&image_info->size,argv[1]);
1320          break;
1321        }
1322      if (LocaleCompare("stroke",option) == 0)
1323        {
1324          if (*argv[0] == '+')
1325            {
1326              (void) SetImageOption(image_info,option,"none");
1327              break;
1328            }
1329          (void) SetImageOption(image_info,option,argv[1]);
1330          break;
1331        }
1332      if (LocaleCompare("strokewidth",option) == 0)
1333        {
1334          if (*argv[0] == '+')
1335            {
1336              (void) SetImageOption(image_info,option,"0");
1337              break;
1338            }
1339          (void) SetImageOption(image_info,option,argv[1]);
1340          break;
1341        }
1342      if (LocaleCompare("synchronize",option) == 0)
1343        {
1344          if (*argv[0] == '+')
1345            {
1346              image_info->synchronize=MagickFalse;
1347              break;
1348            }
1349          image_info->synchronize=MagickTrue;
1350          break;
1351        }
1352      break;
1353    }
1354    case 't':
1355    {
1356      if (LocaleCompare("taint",option) == 0)
1357        {
1358          if (*argv[0] == '+')
1359            {
1360              (void) SetImageOption(image_info,option,"false");
1361              break;
1362            }
1363          (void) SetImageOption(image_info,option,"true");
1364          break;
1365        }
1366      if (LocaleCompare("texture",option) == 0)
1367        {
1368          if (*argv[0] == '+')
1369            {
1370              if (image_info->texture != (char *) NULL)
1371                image_info->texture=DestroyString(image_info->texture);
1372              break;
1373            }
1374          (void) CloneString(&image_info->texture,argv[1]);
1375          break;
1376        }
1377      if (LocaleCompare("tile-offset",option) == 0)
1378        {
1379          if (*argv[0] == '+')
1380            {
1381              (void) SetImageOption(image_info,option,"0");
1382              break;
1383            }
1384          (void) SetImageOption(image_info,option,argv[1]);
1385          break;
1386        }
1387      if (LocaleCompare("transparent-color",option) == 0)
1388        {
1389          if (*argv[0] == '+')
1390            {
1391              (void) QueryColorCompliance("none",AllCompliance,
1392                  &image_info->transparent_color,exception);
1393              (void) SetImageOption(image_info,option,"none");
1394              break;
1395            }
1396              (void) QueryColorCompliance("none",AllCompliance,
1397                  &image_info->transparent_color,exception);
1398            exception);
1399          (void) SetImageOption(image_info,option,argv[1]);
1400          break;
1401        }
1402      if (LocaleCompare("type",option) == 0)
1403        {
1404          if (*argv[0] == '+')
1405            {
1406              image_info->type=UndefinedType;
1407              (void) SetImageOption(image_info,option,"undefined");
1408              break;
1409            }
1410          image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1411            MagickFalse,argv[1]);
1412          (void) SetImageOption(image_info,option,argv[1]);
1413          break;
1414        }
1415      break;
1416    }
1417    case 'u':
1418    {
1419      if (LocaleCompare("undercolor",option) == 0)
1420        {
1421          if (*argv[0] == '+')
1422            {
1423              (void) DeleteImageOption(image_info,option);
1424              break;
1425            }
1426          (void) SetImageOption(image_info,option,argv[1]);
1427          break;
1428        }
1429      if (LocaleCompare("units",option) == 0)
1430        {
1431          if (*argv[0] == '+')
1432            {
1433              image_info->units=UndefinedResolution;
1434              (void) SetImageOption(image_info,option,"undefined");
1435              break;
1436            }
1437          image_info->units=(ResolutionType) ParseCommandOption(
1438            MagickResolutionOptions,MagickFalse,argv[1]);
1439          (void) SetImageOption(image_info,option,argv[1]);
1440          break;
1441        }
1442      break;
1443    }
1444    case 'v':
1445    {
1446      if (LocaleCompare("verbose",option) == 0)
1447        {
1448          if (*argv[0] == '+')
1449            {
1450              image_info->verbose=MagickFalse;
1451              break;
1452            }
1453          image_info->verbose=MagickTrue;
1454          image_info->ping=MagickFalse;
1455          break;
1456        }
1457      if (LocaleCompare("view",option) == 0)
1458        {
1459          if (*argv[0] == '+')
1460            {
1461              if (image_info->view != (char *) NULL)
1462                image_info->view=DestroyString(image_info->view);
1463              break;
1464            }
1465          (void) CloneString(&image_info->view,argv[1]);
1466          break;
1467        }
1468      if (LocaleCompare("virtual-pixel",option) == 0)
1469        {
1470          if (*argv[0] == '+')
1471            {
1472              image_info->virtual_pixel_method=UndefinedVirtualPixelMethod;
1473              (void) SetImageOption(image_info,option,"undefined");
1474              break;
1475            }
1476          image_info->virtual_pixel_method=(VirtualPixelMethod)
1477            ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,argv[1]);
1478          (void) SetImageOption(image_info,option,argv[1]);
1479          break;
1480        }
1481      break;
1482    }
1483    case 'w':
1484    {
1485      if (LocaleCompare("white-point",option) == 0)
1486        {
1487          if (*argv[0] == '+')
1488            {
1489              (void) SetImageOption(image_info,option,"0.0");
1490              break;
1491            }
1492          (void) SetImageOption(image_info,option,argv[1]);
1493          break;
1494        }
1495      break;
1496    }
1497    default:
1498      break;
1499  }
1500  return(MagickTrue);
1501}
1502
1503/*
1504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1505%                                                                             %
1506%                                                                             %
1507%                                                                             %
1508+     A p p l y I m a g e O p e r a t o r                                     %
1509%                                                                             %
1510%                                                                             %
1511%                                                                             %
1512%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1513%
1514%  ApplyImageOperator() apply one simple image operation to just the current
1515%  image.
1516%
1517%  The image in the list may be modified in three different ways...
1518%
1519%    * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1520%    * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1521%    * replace by a list of images (-separate and -crop only!)
1522%
1523%  In each case the result is returned into the list, and the pointer to the
1524%  modified image (last image added if replaced by a list of images) is
1525%  returned.  As the image pointed to may be replaced, the first image in the
1526%  list may also change.  GetFirstImageInList() should be used by caller if
1527%  they wish return the Image pointer to the first image in list.
1528%
1529%  The format of the ApplyImageOperator method is:
1530%
1531%    MagickBooleanType ApplyImageOperator(MagickWand *wand,
1532%        const int argc,const char **argv)
1533%
1534%  A description of each parameter follows:
1535%
1536%    o wand: The CLI wand holding all the settings and pointer to image
1537%
1538%    o argc: Specifies a pointer to an integer describing the number of
1539%      elements in the argument vector.
1540%
1541%    o argv: Specifies a pointer to a text array containing the command line
1542%      arguments.
1543%
1544%    o exception: return any errors or warnings in this structure.
1545%
1546*/
1547MagickExport MagickBooleanType ApplyImageOperator(MagickWand *wand,
1548     const int wand_unused(argc), const char **argv, ExceptionInfo *exception)
1549{
1550  Image *
1551    new_image;
1552
1553  ChannelType
1554    channel;
1555
1556  const char
1557    *format;
1558
1559  DrawInfo
1560    *draw_info;
1561
1562  GeometryInfo
1563    geometry_info;
1564
1565  RectangleInfo
1566    geometry;
1567
1568  MagickStatusType
1569    status;
1570
1571  PixelInfo
1572    fill;
1573
1574  MagickStatusType
1575    flags;
1576
1577  QuantizeInfo
1578    *quantize_info;
1579
1580  assert(image_info != (const ImageInfo *) NULL);
1581  assert(image_info->signature == MagickSignature);
1582  assert(image != (Image **) NULL);
1583  assert((*image)->signature == MagickSignature);
1584  if ((*image)->debug != MagickFalse)
1585    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1586  if (argc < 0)
1587    return(MagickTrue);
1588  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
1589  quantize_info=AcquireQuantizeInfo(image_info);
1590  SetGeometryInfo(&geometry_info);
1591  GetPixelInfo(*image,&fill);
1592  SetPixelInfoPacket(*image,&(*image)->background_color,&fill);
1593  channel=image_info->channel;
1594  format=GetImageOption(image_info,"format");
1595
1596  new_image = (Image *)NULL;
1597
1598  switch (*(argv[0]+1))
1599  {
1600    case 'a':
1601    {
1602      if (LocaleCompare("adaptive-blur",argv[0]+1) == 0)
1603        {
1604          (void) SyncImageSettings(image_info,*image);
1605          flags=ParseGeometry(argv[1],&geometry_info);
1606          if ((flags & SigmaValue) == 0)
1607            geometry_info.sigma=1.0;
1608          if ((flags & XiValue) == 0)
1609            geometry_info.xi=0.0;
1610          new_image=AdaptiveBlurImage(*image,geometry_info.rho,
1611            geometry_info.sigma,geometry_info.xi,exception);
1612          break;
1613        }
1614      if (LocaleCompare("adaptive-resize",argv[0]+1) == 0)
1615        {
1616          /* FUTURE: this is really a "interpolate-resize" operator
1617             "adaptive-resize" uses a fixed "Mesh" interpolation
1618          */
1619          (void) SyncImageSettings(image_info,*image);
1620          (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
1621          new_image=AdaptiveResizeImage(*image,geometry.width,
1622            geometry.height,interpolate_method,exception);
1623          break;
1624        }
1625      if (LocaleCompare("adaptive-sharpen",argv[0]+1) == 0)
1626        {
1627          /*
1628            Adaptive sharpen image.
1629          */
1630          (void) SyncImageSettings(image_info,*image);
1631          flags=ParseGeometry(argv[1],&geometry_info);
1632          if ((flags & SigmaValue) == 0)
1633            geometry_info.sigma=1.0;
1634          if ((flags & XiValue) == 0)
1635            geometry_info.xi=0.0;
1636          new_image=AdaptiveSharpenImage(*image,geometry_info.rho,
1637            geometry_info.sigma,geometry_info.xi,exception);
1638          break;
1639        }
1640      if (LocaleCompare("alpha",argv[0]+1) == 0)
1641        {
1642          AlphaChannelType
1643            alpha_type;
1644
1645          (void) SyncImageSettings(image_info,*image);
1646          alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
1647            MagickFalse,argv[1]);
1648          (void) SetImageAlphaChannel(*image,alpha_type,exception);
1649          break;
1650        }
1651      if (LocaleCompare("annotate",argv[0]+1) == 0)
1652        {
1653          char
1654            *text,
1655            geometry[MaxTextExtent];
1656
1657          (void) SyncImageSettings(image_info,*image);
1658          SetGeometryInfo(&geometry_info);
1659          flags=ParseGeometry(argv[1],&geometry_info);
1660          if ((flags & SigmaValue) == 0)
1661            geometry_info.sigma=geometry_info.rho;
1662          text=InterpretImageProperties(image_info,*image,argv[2],
1663            exception);
1664          if (text == (char *) NULL)
1665            break;
1666          (void) CloneString(&draw_info->text,text);
1667          text=DestroyString(text);
1668          (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1669            geometry_info.xi,geometry_info.psi);
1670          (void) CloneString(&draw_info->geometry,geometry);
1671          draw_info->affine.sx=cos(DegreesToRadians(
1672            fmod(geometry_info.rho,360.0)));
1673          draw_info->affine.rx=sin(DegreesToRadians(
1674            fmod(geometry_info.rho,360.0)));
1675          draw_info->affine.ry=(-sin(DegreesToRadians(
1676            fmod(geometry_info.sigma,360.0))));
1677          draw_info->affine.sy=cos(DegreesToRadians(
1678            fmod(geometry_info.sigma,360.0)));
1679          (void) AnnotateImage(*image,draw_info,exception);
1680          break;
1681        }
1682      if (LocaleCompare("auto-gamma",argv[0]+1) == 0)
1683        {
1684          /*
1685            Auto Adjust Gamma of image based on its mean
1686          */
1687          (void) SyncImageSettings(image_info,*image);
1688          (void) AutoGammaImage(*image,exception);
1689          break;
1690        }
1691      if (LocaleCompare("auto-level",argv[0]+1) == 0)
1692        {
1693          /*
1694            Perfectly Normalize (max/min stretch) the image
1695          */
1696          (void) SyncImageSettings(image_info,*image);
1697          (void) AutoLevelImage(*image,exception);
1698          break;
1699        }
1700      if (LocaleCompare("auto-orient",argv[0]+1) == 0)
1701        {
1702          (void) SyncImageSettings(image_info,*image);
1703          switch ((*image)->orientation)
1704          {
1705            case TopRightOrientation:
1706            {
1707              new_image=FlopImage(*image,exception);
1708              break;
1709            }
1710            case BottomRightOrientation:
1711            {
1712              new_image=RotateImage(*image,180.0,exception);
1713              break;
1714            }
1715            case BottomLeftOrientation:
1716            {
1717              new_image=FlipImage(*image,exception);
1718              break;
1719            }
1720            case LeftTopOrientation:
1721            {
1722              new_image=TransposeImage(*image,exception);
1723              break;
1724            }
1725            case RightTopOrientation:
1726            {
1727              new_image=RotateImage(*image,90.0,exception);
1728              break;
1729            }
1730            case RightBottomOrientation:
1731            {
1732              new_image=TransverseImage(*image,exception);
1733              break;
1734            }
1735            case LeftBottomOrientation:
1736            {
1737              new_image=RotateImage(*image,270.0,exception);
1738              break;
1739            }
1740            default:
1741              break;
1742          }
1743          if (new_image != (Image *) NULL)
1744            new_image->orientation=TopLeftOrientation;
1745          break;
1746        }
1747      break;
1748    }
1749    case 'b':
1750    {
1751      if (LocaleCompare("black-threshold",argv[0]+1) == 0)
1752        {
1753          (void) SyncImageSettings(image_info,*image);
1754          (void) BlackThresholdImage(*image,argv[1],exception);
1755          InheritException(exception,&(*image)->exception);
1756          break;
1757        }
1758      if (LocaleCompare("blue-shift",argv[0]+1) == 0)
1759        {
1760          (void) SyncImageSettings(image_info,*image);
1761          geometry_info.rho=1.5;
1762          if (*argv[0] == '-')
1763            flags=ParseGeometry(argv[1],&geometry_info);
1764          new_image=BlueShiftImage(*image,geometry_info.rho,exception);
1765          break;
1766        }
1767      if (LocaleCompare("blur",argv[0]+1) == 0)
1768        {
1769          /* FUTURE: use of "bias" in a blur is non-sensible */
1770          (void) SyncImageSettings(image_info,*image);
1771          flags=ParseGeometry(argv[1],&geometry_info);
1772          if ((flags & SigmaValue) == 0)
1773            geometry_info.sigma=1.0;
1774          if ((flags & XiValue) == 0)
1775            geometry_info.xi=0.0;
1776          new_image=BlurImage(*image,geometry_info.rho,
1777            geometry_info.sigma,geometry_info.xi,exception);
1778          break;
1779        }
1780      if (LocaleCompare("border",argv[0]+1) == 0)
1781        {
1782          (void) SyncImageSettings(image_info,*image);
1783          flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
1784          if ((flags & SigmaValue) == 0)
1785            geometry.height=geometry.width;
1786          new_image=BorderImage(*image,&geometry,compose,exception);
1787          break;
1788        }
1789      if (LocaleCompare("brightness-contrast",argv[0]+1) == 0)
1790        {
1791          double
1792            brightness,
1793            contrast;
1794
1795          GeometryInfo
1796            geometry_info;
1797
1798          MagickStatusType
1799            flags;
1800
1801          (void) SyncImageSettings(image_info,*image);
1802          flags=ParseGeometry(argv[1],&geometry_info);
1803          brightness=geometry_info.rho;
1804          contrast=0.0;
1805          if ((flags & SigmaValue) != 0)
1806            contrast=geometry_info.sigma;
1807          (void) BrightnessContrastImage(*image,brightness,contrast,
1808            exception);
1809          InheritException(exception,&(*image)->exception);
1810          break;
1811        }
1812      break;
1813    }
1814    case 'c':
1815    {
1816      if (LocaleCompare("cdl",argv[0]+1) == 0)
1817        {
1818          char
1819            *color_correction_collection;
1820
1821          /*
1822            Color correct with a color decision list.
1823          */
1824          (void) SyncImageSettings(image_info,*image);
1825          color_correction_collection=FileToString(argv[1],~0,exception);
1826          if (color_correction_collection == (char *) NULL)
1827            break;
1828          (void) ColorDecisionListImage(*image,color_correction_collection,
1829            exception);
1830          InheritException(exception,&(*image)->exception);
1831          break;
1832        }
1833      if (LocaleCompare("channel",argv[0]+1) == 0)
1834        {
1835          /* The "channel" setting has already been set */
1836          SetPixelChannelMap(*image,image_info->channel);
1837          break;
1838        }
1839      if (LocaleCompare("charcoal",argv[0]+1) == 0)
1840        {
1841          (void) SyncImageSettings(image_info,*image);
1842          flags=ParseGeometry(argv[1],&geometry_info);
1843          if ((flags & SigmaValue) == 0)
1844            geometry_info.sigma=1.0;
1845          if ((flags & XiValue) == 0)
1846            geometry_info.xi=1.0;
1847          new_image=CharcoalImage(*image,geometry_info.rho,
1848            geometry_info.sigma,geometry_info.xi,exception);
1849          break;
1850        }
1851      if (LocaleCompare("chop",argv[0]+1) == 0)
1852        {
1853          (void) SyncImageSettings(image_info,*image);
1854          (void) ParseGravityGeometry(*image,argv[1],&geometry,exception);
1855          new_image=ChopImage(*image,&geometry,exception);
1856          break;
1857        }
1858      if (LocaleCompare("clamp",argv[0]+1) == 0)
1859        {
1860          (void) SyncImageSettings(image_info,*image);
1861          (void) ClampImage(*image);
1862          InheritException(exception,&(*image)->exception);
1863          break;
1864        }
1865      if (LocaleCompare("clip",argv[0]+1) == 0)
1866        {
1867          (void) SyncImageSettings(image_info,*image);
1868          if (*argv[0] == '+')
1869            {
1870              (void) SetImageClipMask(*image,(Image *) NULL,exception);
1871              break;
1872            }
1873          (void) ClipImage(*image,exception);
1874          break;
1875        }
1876      if (LocaleCompare("clip-mask",argv[0]+1) == 0)
1877        {
1878          CacheView
1879            *mask_view;
1880
1881          Image
1882            *mask_image;
1883
1884          register Quantum
1885            *restrict q;
1886
1887          register ssize_t
1888            x;
1889
1890          ssize_t
1891            y;
1892
1893          (void) SyncImageSettings(image_info,*image);
1894          if (*argv[0] == '+')
1895            {
1896              /* Remove the write mask */
1897              (void) SetImageMask(*image,(Image *) NULL,exception);
1898              break;
1899            }
1900          mask_image=GetImageCache(image_info,argv[1],exception);
1901          if (mask_image == (Image *) NULL)
1902            break;
1903          if (SetImageStorageClass(mask_image,DirectClass,exception) == MagickFalse)
1904            return(MagickFalse);
1905          /* create a write mask from clip-mask image */
1906          /* FUTURE: use Alpha operations instead */
1907          mask_view=AcquireCacheView(mask_image);
1908          for (y=0; y < (ssize_t) mask_image->rows; y++)
1909          {
1910            q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1911              exception);
1912            if (q == (Quantum *) NULL)
1913              break;
1914            for (x=0; x < (ssize_t) mask_image->columns; x++)
1915            {
1916              if (mask_image->matte == MagickFalse)
1917                SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1918              SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1919              SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1920              SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1921              q+=GetPixelChannels(mask_image);
1922            }
1923            if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1924              break;
1925          }
1926          /* set the write mask */
1927          mask_view=DestroyCacheView(mask_view);
1928          mask_image->matte=MagickTrue;
1929          (void) SetImageClipMask(*image,mask_image,exception);
1930          mask_image=DestroyImage(mask_image);
1931          InheritException(exception,&(*image)->exception);
1932          break;
1933        }
1934      if (LocaleCompare("clip-path",argv[0]+1) == 0)
1935        {
1936          (void) SyncImageSettings(image_info,*image);
1937          (void) ClipImagePath(*image,argv[1],*argv[0] == '-' ? MagickTrue :
1938            MagickFalse,exception);
1939          break;
1940        }
1941      if (LocaleCompare("colorize",argv[0]+1) == 0)
1942        {
1943          (void) SyncImageSettings(image_info,*image);
1944          new_image=ColorizeImage(*image,argv[1],draw_info->fill,
1945            exception);
1946          break;
1947        }
1948      if (LocaleCompare("color-matrix",argv[0]+1) == 0)
1949        {
1950          KernelInfo
1951            *kernel;
1952
1953          (void) SyncImageSettings(image_info,*image);
1954          kernel=AcquireKernelInfo(argv[1]);
1955          if (kernel == (KernelInfo *) NULL)
1956            break;
1957          new_image=ColorMatrixImage(*image,kernel,exception);
1958          kernel=DestroyKernelInfo(kernel);
1959          break;
1960        }
1961      if (LocaleCompare("colors",argv[0]+1) == 0)
1962        {
1963          /* Reduce the number of colors in the image.  */
1964          (void) SyncImageSettings(image_info,*image);
1965          quantize_info->number_colors=StringToUnsignedLong(argv[1]);
1966          if (quantize_info->number_colors == 0)
1967            break;
1968          if (((*image)->storage_class == DirectClass) ||
1969              (*image)->colors > quantize_info->number_colors)
1970            (void) QuantizeImage(quantize_info,*image,exception);
1971          else
1972            (void) CompressImageColormap(*image,exception);
1973          break;
1974        }
1975      if (LocaleCompare("colorspace",argv[0]+1) == 0)
1976        {
1977          /* This is a Image Setting, which should already been set */
1978          /* FUTURE: default colorspace should be sRGB!
1979             Unless some type of 'linear colorspace' mode is set.
1980             Note that +colorspace sets "undefined" or no effect on
1981             new images, but forces images already in memory back to RGB!
1982          */
1983          (void) SyncImageSettings(image_info,*image);
1984          (void) TransformImageColorspace(*image,
1985                    IfSetOption ? image_info->colorspace : RGBColorspace);
1986          InheritException(exception,&(*image)->exception);
1987          break;
1988        }
1989      if (LocaleCompare("contrast",argv[0]+1) == 0)
1990        {
1991          (void) SyncImageSettings(image_info,*image);
1992          (void) ContrastImage(*image,(*argv[0] == '-') ? MagickTrue :
1993            MagickFalse,exception);
1994          break;
1995        }
1996      if (LocaleCompare("contrast-stretch",argv[0]+1) == 0)
1997        {
1998          double
1999            black_point,
2000            white_point;
2001
2002          MagickStatusType
2003            flags;
2004
2005          /*
2006            Contrast stretch image.
2007          */
2008          (void) SyncImageSettings(image_info,*image);
2009          flags=ParseGeometry(argv[1],&geometry_info);
2010          black_point=geometry_info.rho;
2011          white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2012            black_point;
2013          if ((flags & PercentValue) != 0)
2014            {
2015              black_point*=(double) (*image)->columns*(*image)->rows/100.0;
2016              white_point*=(double) (*image)->columns*(*image)->rows/100.0;
2017            }
2018          white_point=(MagickRealType) (*image)->columns*(*image)->rows-
2019            white_point;
2020          (void) ContrastStretchImage(*image,black_point,white_point,
2021            exception);
2022          InheritException(exception,&(*image)->exception);
2023          break;
2024        }
2025      if (LocaleCompare("convolve",argv[0]+1) == 0)
2026        {
2027          KernelInfo
2028            *kernel_info;
2029
2030          (void) SyncImageSettings(image_info,*image);
2031          kernel_info=AcquireKernelInfo(argv[1]);
2032          if (kernel_info == (KernelInfo *) NULL)
2033            break;
2034          kernel_info->bias=(*image)->bias;
2035          new_image=ConvolveImage(*image,kernel_info,exception);
2036          kernel_info=DestroyKernelInfo(kernel_info);
2037          break;
2038        }
2039      if (LocaleCompare("crop",argv[0]+1) == 0)
2040        {
2041          /*
2042            Crop a image to a smaller size
2043          */
2044          (void) SyncImageSettings(image_info,*image);
2045          new_image=CropImageToTiles(*image,argv[1],exception);
2046          break;
2047        }
2048      if (LocaleCompare("cycle",argv[0]+1) == 0)
2049        {
2050          /*
2051            Cycle an image colormap.
2052          */
2053          (void) SyncImageSettings(image_info,*image);
2054          (void) CycleColormapImage(*image,(ssize_t) StringToLong(argv[1]),
2055            exception);
2056          break;
2057        }
2058      break;
2059    }
2060    case 'd':
2061    {
2062      if (LocaleCompare("decipher",argv[0]+1) == 0)
2063        {
2064          StringInfo
2065            *passkey;
2066
2067          /*
2068            Decipher pixels.
2069          */
2070          (void) SyncImageSettings(image_info,*image);
2071          passkey=FileToStringInfo(argv[1],~0,exception);
2072          if (passkey != (StringInfo *) NULL)
2073            {
2074              (void) PasskeyDecipherImage(*image,passkey,exception);
2075              passkey=DestroyStringInfo(passkey);
2076            }
2077          break;
2078        }
2079      if (LocaleCompare("density",argv[0]+1) == 0)
2080        {
2081          /*
2082            Set image density.
2083          */
2084          (void) CloneString(&draw_info->density,argv[1]);
2085          break;
2086        }
2087      if (LocaleCompare("depth",argv[0]+1) == 0)
2088        {
2089          (void) SyncImageSettings(image_info,*image);
2090          if (*argv[0] == '+')
2091            {
2092              (void) SetImageDepth(*image,MAGICKCORE_QUANTUM_DEPTH);
2093              break;
2094            }
2095          (void) SetImageDepth(*image,StringToUnsignedLong(argv[1]));
2096          break;
2097        }
2098      if (LocaleCompare("deskew",argv[0]+1) == 0)
2099        {
2100          double
2101            threshold;
2102
2103          /*
2104            Straighten the image.
2105          */
2106          (void) SyncImageSettings(image_info,*image);
2107          if (*argv[0] == '+')
2108            threshold=40.0*QuantumRange/100.0;
2109          else
2110            threshold=SiPrefixToDouble(argv[1],QuantumRange);
2111          new_image=DeskewImage(*image,threshold,exception);
2112          break;
2113        }
2114      if (LocaleCompare("despeckle",argv[0]+1) == 0)
2115        {
2116          /*
2117            Reduce the speckles within an image.
2118          */
2119          (void) SyncImageSettings(image_info,*image);
2120          new_image=DespeckleImage(*image,exception);
2121          break;
2122        }
2123      if (LocaleCompare("display",argv[0]+1) == 0)
2124        {
2125          (void) CloneString(&draw_info->server_name,argv[1]);
2126          break;
2127        }
2128      if (LocaleCompare("distort",argv[0]+1) == 0)
2129        {
2130          char
2131            *args,
2132            token[MaxTextExtent];
2133
2134          const char
2135            *p;
2136
2137          DistortImageMethod
2138            method;
2139
2140          double
2141            *arguments;
2142
2143          register ssize_t
2144            x;
2145
2146          size_t
2147            number_arguments;
2148
2149          /*
2150            Distort image.
2151          */
2152          (void) SyncImageSettings(image_info,*image);
2153          method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
2154            MagickFalse,argv[1]);
2155          if ( method == ResizeDistortion )
2156            {
2157               /* Special Case - Argument is actually a resize geometry!
2158               ** Convert that to an appropriate distortion argument array.
2159               */
2160               double
2161                 resize_args[2];
2162               (void) ParseRegionGeometry(*image,argv[2],&geometry,
2163                    exception);
2164               resize_args[0]=(double)geometry.width;
2165               resize_args[1]=(double)geometry.height;
2166               new_image=DistortImage(*image,method,(size_t)2,
2167                    resize_args,MagickTrue,exception);
2168               break;
2169            }
2170          args=InterpretImageProperties(image_info,*image,argv[2],
2171            exception);
2172          if (args == (char *) NULL)
2173            break;
2174          p=(char *) args;
2175          for (x=0; *p != '\0'; x++)
2176          {
2177            GetMagickToken(p,&p,token);
2178            if (*token == ',')
2179              GetMagickToken(p,&p,token);
2180          }
2181          number_arguments=(size_t) x;
2182          arguments=(double *) AcquireQuantumMemory(number_arguments,
2183            sizeof(*arguments));
2184          if (arguments == (double *) NULL)
2185            ThrowWandFatalException(ResourceLimitFatalError,
2186              "MemoryAllocationFailed",(*image)->filename);
2187          (void) ResetMagickMemory(arguments,0,number_arguments*
2188            sizeof(*arguments));
2189          p=(char *) args;
2190          for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2191          {
2192            GetMagickToken(p,&p,token);
2193            if (*token == ',')
2194              GetMagickToken(p,&p,token);
2195            arguments[x]=InterpretLocaleValue(token,(char **) NULL);
2196          }
2197          args=DestroyString(args);
2198          new_image=DistortImage(*image,method,number_arguments,arguments,
2199            (*argv[0] == '+') ? MagickTrue : MagickFalse,exception);
2200          arguments=(double *) RelinquishMagickMemory(arguments);
2201          break;
2202        }
2203      if (LocaleCompare("dither",argv[0]+1) == 0)
2204        {
2205          if (*argv[0] == '+')
2206            {
2207              quantize_info->dither=MagickFalse;
2208              break;
2209            }
2210          quantize_info->dither=MagickTrue;
2211          quantize_info->dither_method=(DitherMethod) ParseCommandOption(
2212            MagickDitherOptions,MagickFalse,argv[1]);
2213          if (quantize_info->dither_method == NoDitherMethod)
2214            quantize_info->dither=MagickFalse;
2215          break;
2216        }
2217      if (LocaleCompare("draw",argv[0]+1) == 0)
2218        {
2219          /*
2220            Draw image.
2221          */
2222          (void) SyncImageSettings(image_info,*image);
2223          (void) CloneString(&draw_info->primitive,argv[1]);
2224          (void) DrawImage(*image,draw_info,exception);
2225          break;
2226        }
2227      break;
2228    }
2229    case 'e':
2230    {
2231      if (LocaleCompare("edge",argv[0]+1) == 0)
2232        {
2233          /*
2234            Enhance edges in the image.
2235          */
2236          (void) SyncImageSettings(image_info,*image);
2237          flags=ParseGeometry(argv[1],&geometry_info);
2238          if ((flags & SigmaValue) == 0)
2239            geometry_info.sigma=1.0;
2240          new_image=EdgeImage(*image,geometry_info.rho,
2241            geometry_info.sigma,exception);
2242          break;
2243        }
2244      if (LocaleCompare("emboss",argv[0]+1) == 0)
2245        {
2246          /*
2247            Gaussian embossen image.
2248          */
2249          (void) SyncImageSettings(image_info,*image);
2250          flags=ParseGeometry(argv[1],&geometry_info);
2251          if ((flags & SigmaValue) == 0)
2252            geometry_info.sigma=1.0;
2253          new_image=EmbossImage(*image,geometry_info.rho,
2254            geometry_info.sigma,exception);
2255          break;
2256        }
2257      if (LocaleCompare("encipher",argv[0]+1) == 0)
2258        {
2259          StringInfo
2260            *passkey;
2261
2262          /*
2263            Encipher pixels.
2264          */
2265          (void) SyncImageSettings(image_info,*image);
2266          passkey=FileToStringInfo(argv[1],~0,exception);
2267          if (passkey != (StringInfo *) NULL)
2268            {
2269              (void) PasskeyEncipherImage(*image,passkey,exception);
2270              passkey=DestroyStringInfo(passkey);
2271            }
2272          break;
2273        }
2274      if (LocaleCompare("encoding",argv[0]+1) == 0)
2275        {
2276          (void) CloneString(&draw_info->encoding,argv[1]);
2277          break;
2278        }
2279      if (LocaleCompare("enhance",argv[0]+1) == 0)
2280        {
2281          /*
2282            Enhance image.
2283          */
2284          (void) SyncImageSettings(image_info,*image);
2285          new_image=EnhanceImage(*image,exception);
2286          break;
2287        }
2288      if (LocaleCompare("equalize",argv[0]+1) == 0)
2289        {
2290          /*
2291            Equalize image.
2292          */
2293          (void) SyncImageSettings(image_info,*image);
2294          (void) EqualizeImage(*image,exception);
2295          break;
2296        }
2297      if (LocaleCompare("evaluate",argv[0]+1) == 0)
2298        {
2299          double
2300            constant;
2301
2302          MagickEvaluateOperator
2303            op;
2304
2305          (void) SyncImageSettings(image_info,*image);
2306          op=(MagickEvaluateOperator) ParseCommandOption(
2307            MagickEvaluateOptions,MagickFalse,argv[1]);
2308          constant=SiPrefixToDouble(argv[2],QuantumRange);
2309          (void) EvaluateImage(*image,op,constant,exception);
2310          break;
2311        }
2312      if (LocaleCompare("extent",argv[0]+1) == 0)
2313        {
2314          /*
2315            Set the image extent.
2316          */
2317          (void) SyncImageSettings(image_info,*image);
2318          flags=ParseGravityGeometry(*image,argv[1],&geometry,exception);
2319          if (geometry.width == 0)
2320            geometry.width=(*image)->columns;
2321          if (geometry.height == 0)
2322            geometry.height=(*image)->rows;
2323          new_image=ExtentImage(*image,&geometry,exception);
2324          break;
2325        }
2326      break;
2327    }
2328    case 'f':
2329    {
2330      if (LocaleCompare("family",argv[0]+1) == 0)
2331        {
2332          if (*argv[0] == '+')
2333            {
2334              if (draw_info->family != (char *) NULL)
2335                draw_info->family=DestroyString(draw_info->family);
2336              break;
2337            }
2338          (void) CloneString(&draw_info->family,argv[1]);
2339          break;
2340        }
2341      if (LocaleCompare("features",argv[0]+1) == 0)
2342        {
2343          if (*argv[0] == '+')
2344            {
2345              (void) DeleteImageArtifact(*image,"identify:features");
2346              break;
2347            }
2348          (void) SetImageArtifact(*image,"identify:features",argv[1]);
2349          break;
2350        }
2351      if (LocaleCompare("fill",argv[0]+1) == 0)
2352        {
2353          ExceptionInfo
2354            *sans;
2355
2356          GetPixelInfo(*image,&fill);
2357          if (*argv[0] == '+')
2358            {
2359              (void) QueryMagickColorCompliance("none",AllCompliance,&fill,
2360                 exception);
2361              (void) QueryColorCompliance("none",AllCompliance,&draw_info->fill,
2362                exception);
2363              if (draw_info->fill_pattern != (Image *) NULL)
2364                draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
2365              break;
2366            }
2367          sans=AcquireExceptionInfo();
2368          (void) QueryMagickColorCompliance(argv[1],AllCompliance,&fill,sans);
2369          status=QueryColorCompliance(argv[1],AllCompliance,&draw_info->fill,sans);
2370          sans=DestroyExceptionInfo(sans);
2371          if (status == MagickFalse)
2372            draw_info->fill_pattern=GetImageCache(image_info,argv[1],
2373              exception);
2374          break;
2375        }
2376      if (LocaleCompare("flip",argv[0]+1) == 0)
2377        {
2378          /*
2379            Flip image scanlines.
2380          */
2381          (void) SyncImageSettings(image_info,*image);
2382          new_image=FlipImage(*image,exception);
2383          break;
2384        }
2385      if (LocaleCompare("flop",argv[0]+1) == 0)
2386        {
2387          /*
2388            Flop image scanlines.
2389          */
2390          (void) SyncImageSettings(image_info,*image);
2391          new_image=FlopImage(*image,exception);
2392          break;
2393        }
2394      if (LocaleCompare("floodfill",argv[0]+1) == 0)
2395        {
2396          PixelInfo
2397            target;
2398
2399          /*
2400            Floodfill image.
2401          */
2402          (void) SyncImageSettings(image_info,*image);
2403          (void) ParsePageGeometry(*image,argv[1],&geometry,exception);
2404          (void) QueryMagickColorCompliance(argv[2],AllCompliance,&target,
2405                        exception);
2406          (void) FloodfillPaintImage(*image,draw_info,&target,geometry.x,
2407            geometry.y,*argv[0] == '-' ? MagickFalse : MagickTrue,exception);
2408          break;
2409        }
2410      if (LocaleCompare("font",argv[0]+1) == 0)
2411        {
2412          if (*argv[0] == '+')
2413            {
2414              if (draw_info->font != (char *) NULL)
2415                draw_info->font=DestroyString(draw_info->font);
2416              break;
2417            }
2418          (void) CloneString(&draw_info->font,argv[1]);
2419          break;
2420        }
2421      if (LocaleCompare("format",argv[0]+1) == 0)
2422        {
2423          format=argv[1];
2424          break;
2425        }
2426      if (LocaleCompare("frame",argv[0]+1) == 0)
2427        {
2428          FrameInfo
2429            frame_info;
2430
2431          /*
2432            Surround image with an ornamental border.
2433          */
2434          (void) SyncImageSettings(image_info,*image);
2435          flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
2436          frame_info.width=geometry.width;
2437          frame_info.height=geometry.height;
2438          if ((flags & HeightValue) == 0)
2439            frame_info.height=geometry.width;
2440          frame_info.outer_bevel=geometry.x;
2441          frame_info.inner_bevel=geometry.y;
2442          frame_info.x=(ssize_t) frame_info.width;
2443          frame_info.y=(ssize_t) frame_info.height;
2444          frame_info.width=(*image)->columns+2*frame_info.width;
2445          frame_info.height=(*image)->rows+2*frame_info.height;
2446          new_image=FrameImage(*image,&frame_info,compose,exception);
2447          break;
2448        }
2449      if (LocaleCompare("function",argv[0]+1) == 0)
2450        {
2451          char
2452            *arguments,
2453            token[MaxTextExtent];
2454
2455          const char
2456            *p;
2457
2458          double
2459            *parameters;
2460
2461          MagickFunction
2462            function;
2463
2464          register ssize_t
2465            x;
2466
2467          size_t
2468            number_parameters;
2469
2470          /*
2471            Function Modify Image Values
2472          */
2473          (void) SyncImageSettings(image_info,*image);
2474          function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
2475            MagickFalse,argv[1]);
2476          arguments=InterpretImageProperties(image_info,*image,argv[2],
2477            exception);
2478          if (arguments == (char *) NULL)
2479            break;
2480          p=(char *) arguments;
2481          for (x=0; *p != '\0'; x++)
2482          {
2483            GetMagickToken(p,&p,token);
2484            if (*token == ',')
2485              GetMagickToken(p,&p,token);
2486          }
2487          number_parameters=(size_t) x;
2488          parameters=(double *) AcquireQuantumMemory(number_parameters,
2489            sizeof(*parameters));
2490          if (parameters == (double *) NULL)
2491            ThrowWandFatalException(ResourceLimitFatalError,
2492              "MemoryAllocationFailed",(*image)->filename);
2493          (void) ResetMagickMemory(parameters,0,number_parameters*
2494            sizeof(*parameters));
2495          p=(char *) arguments;
2496          for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2497          {
2498            GetMagickToken(p,&p,token);
2499            if (*token == ',')
2500              GetMagickToken(p,&p,token);
2501            parameters[x]=InterpretLocaleValue(token,(char **) NULL);
2502          }
2503          arguments=DestroyString(arguments);
2504          (void) FunctionImage(*image,function,number_parameters,parameters,
2505            exception);
2506          parameters=(double *) RelinquishMagickMemory(parameters);
2507          break;
2508        }
2509      break;
2510    }
2511    case 'g':
2512    {
2513      if (LocaleCompare("gamma",argv[0]+1) == 0)
2514        {
2515          /*
2516            Gamma image.
2517          */
2518          (void) SyncImageSettings(image_info,*image);
2519          if (*argv[0] == '+')
2520            (*image)->gamma=InterpretLocaleValue(argv[1],(char **) NULL);
2521          else
2522            (void) GammaImage(*image,InterpretLocaleValue(argv[1],
2523              (char **) NULL),exception);
2524          break;
2525        }
2526      if ((LocaleCompare("gaussian-blur",argv[0]+1) == 0) ||
2527          (LocaleCompare("gaussian",argv[0]+1) == 0))
2528        {
2529          /*
2530            Gaussian blur image.
2531          */
2532          (void) SyncImageSettings(image_info,*image);
2533          flags=ParseGeometry(argv[1],&geometry_info);
2534          if ((flags & SigmaValue) == 0)
2535            geometry_info.sigma=1.0;
2536          if ((flags & XiValue) == 0)
2537            geometry_info.xi=0.0;
2538          new_image=GaussianBlurImage(*image,geometry_info.rho,
2539            geometry_info.sigma,geometry_info.xi,exception);
2540          break;
2541        }
2542      if (LocaleCompare("geometry",argv[0]+1) == 0)
2543        {
2544            /*
2545              Record Image offset, Resize last image.
2546            */
2547          (void) SyncImageSettings(image_info,*image);
2548          if (*argv[0] == '+')
2549            {
2550              if ((*image)->geometry != (char *) NULL)
2551                (*image)->geometry=DestroyString((*image)->geometry);
2552              break;
2553            }
2554          flags=ParseRegionGeometry(*image,argv[1],&geometry,exception);
2555          if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2556            (void) CloneString(&(*image)->geometry,argv[1]);
2557          else
2558            new_image=ResizeImage(*image,geometry.width,geometry.height,
2559              (*image)->filter,(*image)->blur,exception);
2560          break;
2561        }
2562      if (LocaleCompare("gravity",argv[0]+1) == 0)
2563        {
2564          if (*argv[0] == '+')
2565            {
2566              draw_info->gravity=UndefinedGravity;
2567              break;
2568            }
2569          draw_info->gravity=(GravityType) ParseCommandOption(
2570            MagickGravityOptions,MagickFalse,argv[1]);
2571          break;
2572        }
2573      break;
2574    }
2575    case 'h':
2576    {
2577      if (LocaleCompare("highlight-color",argv[0]+1) == 0)
2578        {
2579          (void) SetImageArtifact(*image,argv[0]+1,argv[1]);
2580          break;
2581        }
2582      break;
2583    }
2584    case 'i':
2585    {
2586      if (LocaleCompare("identify",argv[0]+1) == 0)
2587        {
2588          char
2589            *text;
2590
2591          (void) SyncImageSettings(image_info,*image);
2592          if (format == (char *) NULL)
2593            {
2594              (void) IdentifyImage(*image,stdout,image_info->verbose,
2595                exception);
2596              break;
2597            }
2598          text=InterpretImageProperties(image_info,*image,format,
2599            exception);
2600          if (text == (char *) NULL)
2601            break;
2602          (void) fputs(text,stdout);
2603          (void) fputc('\n',stdout);
2604          text=DestroyString(text);
2605          break;
2606        }
2607      if (LocaleCompare("implode",argv[0]+1) == 0)
2608        {
2609          /*
2610            Implode image.
2611          */
2612          (void) SyncImageSettings(image_info,*image);
2613          (void) ParseGeometry(argv[1],&geometry_info);
2614          new_image=ImplodeImage(*image,geometry_info.rho,
2615            interpolate_method,exception);
2616          break;
2617        }
2618      if (LocaleCompare("interline-spacing",argv[0]+1) == 0)
2619        {
2620          if (*argv[0] == '+')
2621            (void) ParseGeometry("0",&geometry_info);
2622          else
2623            (void) ParseGeometry(argv[1],&geometry_info);
2624          draw_info->interline_spacing=geometry_info.rho;
2625          break;
2626        }
2627      if (LocaleCompare("interpolate",argv[0]+1) == 0)
2628        {
2629          interpolate_method=(PixelInterpolateMethod) ParseCommandOption(
2630            MagickInterpolateOptions,MagickFalse,argv[1]);
2631          break;
2632        }
2633      if (LocaleCompare("interword-spacing",argv[0]+1) == 0)
2634        {
2635          if (*argv[0] == '+')
2636            (void) ParseGeometry("0",&geometry_info);
2637          else
2638            (void) ParseGeometry(argv[1],&geometry_info);
2639          draw_info->interword_spacing=geometry_info.rho;
2640          break;
2641        }
2642      break;
2643    }
2644    case 'k':
2645    {
2646      if (LocaleCompare("kerning",argv[0]+1) == 0)
2647        {
2648          if (*argv[0] == '+')
2649            (void) ParseGeometry("0",&geometry_info);
2650          else
2651            (void) ParseGeometry(argv[1],&geometry_info);
2652          draw_info->kerning=geometry_info.rho;
2653          break;
2654        }
2655      break;
2656    }
2657    case 'l':
2658    {
2659      if (LocaleCompare("lat",argv[0]+1) == 0)
2660        {
2661          /*
2662            Local adaptive threshold image.
2663          */
2664          (void) SyncImageSettings(image_info,*image);
2665          flags=ParseGeometry(argv[1],&geometry_info);
2666          if ((flags & PercentValue) != 0)
2667            geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2668          new_image=AdaptiveThresholdImage(*image,(size_t)
2669            geometry_info.rho,(size_t) geometry_info.sigma,(double)
2670            geometry_info.xi,exception);
2671          break;
2672        }
2673      if (LocaleCompare("level",argv[0]+1) == 0)
2674        {
2675          MagickRealType
2676            black_point,
2677            gamma,
2678            white_point;
2679
2680          MagickStatusType
2681            flags;
2682
2683          /*
2684            Parse levels.
2685          */
2686          (void) SyncImageSettings(image_info,*image);
2687          flags=ParseGeometry(argv[1],&geometry_info);
2688          black_point=geometry_info.rho;
2689          white_point=(MagickRealType) QuantumRange;
2690          if ((flags & SigmaValue) != 0)
2691            white_point=geometry_info.sigma;
2692          gamma=1.0;
2693          if ((flags & XiValue) != 0)
2694            gamma=geometry_info.xi;
2695          if ((flags & PercentValue) != 0)
2696            {
2697              black_point*=(MagickRealType) (QuantumRange/100.0);
2698              white_point*=(MagickRealType) (QuantumRange/100.0);
2699            }
2700          if ((flags & SigmaValue) == 0)
2701            white_point=(MagickRealType) QuantumRange-black_point;
2702          if ((*argv[0] == '+') || ((flags & AspectValue) != 0))
2703            (void) LevelizeImage(*image,black_point,white_point,gamma,
2704              exception);
2705          else
2706            (void) LevelImage(*image,black_point,white_point,gamma,
2707              exception);
2708          InheritException(exception,&(*image)->exception);
2709          break;
2710        }
2711      if (LocaleCompare("level-colors",argv[0]+1) == 0)
2712        {
2713          char
2714            token[MaxTextExtent];
2715
2716          const char
2717            *p;
2718
2719          PixelInfo
2720            black_point,
2721            white_point;
2722
2723          p=(const char *) argv[1];
2724          GetMagickToken(p,&p,token);  /* get black point color */
2725          if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2726            (void) QueryMagickColorCompliance(token,AllCompliance,
2727                      &black_point,exception);
2728          else
2729            (void) QueryMagickColorCompliance("#000000",AllCompliance,
2730                      &black_point,exception);
2731          if (isalpha((int) token[0]) || (token[0] == '#'))
2732            GetMagickToken(p,&p,token);
2733          if (*token == '\0')
2734            white_point=black_point; /* set everything to that color */
2735          else
2736            {
2737              if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2738                GetMagickToken(p,&p,token); /* Get white point color. */
2739              if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2740                (void) QueryMagickColorCompliance(token,AllCompliance,
2741                           &white_point,exception);
2742              else
2743                (void) QueryMagickColorCompliance("#ffffff",AllCompliance,
2744                           &white_point,exception);
2745            }
2746          (void) LevelImageColors(*image,&black_point,&white_point,
2747            *argv[0] == '+' ? MagickTrue : MagickFalse,exception);
2748          break;
2749        }
2750      if (LocaleCompare("linear-stretch",argv[0]+1) == 0)
2751        {
2752          double
2753            black_point,
2754            white_point;
2755
2756          MagickStatusType
2757            flags;
2758
2759          (void) SyncImageSettings(image_info,*image);
2760          flags=ParseGeometry(argv[1],&geometry_info);
2761          black_point=geometry_info.rho;
2762          white_point=(MagickRealType) (*image)->columns*(*image)->rows;
2763          if ((flags & SigmaValue) != 0)
2764            white_point=geometry_info.sigma;
2765          if ((flags & PercentValue) != 0)
2766            {
2767              black_point*=(double) (*image)->columns*(*image)->rows/100.0;
2768              white_point*=(double) (*image)->columns*(*image)->rows/100.0;
2769            }
2770          if ((flags & SigmaValue) == 0)
2771            white_point=(MagickRealType) (*image)->columns*(*image)->rows-
2772              black_point;
2773          (void) LinearStretchImage(*image,black_point,white_point,exception);
2774          InheritException(exception,&(*image)->exception);
2775          break;
2776        }
2777      if (LocaleCompare("linewidth",argv[0]+1) == 0)
2778        {
2779          draw_info->stroke_width=InterpretLocaleValue(argv[1],
2780            (char **) NULL);
2781          break;
2782        }
2783      if (LocaleCompare("liquid-rescale",argv[0]+1) == 0)
2784        {
2785          /*
2786            Liquid rescale image.
2787          */
2788          (void) SyncImageSettings(image_info,*image);
2789          flags=ParseRegionGeometry(*image,argv[1],&geometry,exception);
2790          if ((flags & XValue) == 0)
2791            geometry.x=1;
2792          if ((flags & YValue) == 0)
2793            geometry.y=0;
2794          new_image=LiquidRescaleImage(*image,geometry.width,
2795            geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2796          break;
2797        }
2798      if (LocaleCompare("lowlight-color",argv[0]+1) == 0)
2799        {
2800          (void) SetImageArtifact(*image,argv[0]+1,argv[1]);
2801          break;
2802        }
2803      break;
2804    }
2805    case 'm':
2806    {
2807      if (LocaleCompare("map",argv[0]+1) == 0)
2808        {
2809          Image
2810            *remap_image;
2811
2812          /*
2813            Transform image colors to match this set of colors.
2814          */
2815          (void) SyncImageSettings(image_info,*image);
2816          if (*argv[0] == '+')
2817            break;
2818          remap_image=GetImageCache(image_info,argv[1],exception);
2819          if (remap_image == (Image *) NULL)
2820            break;
2821          (void) RemapImage(quantize_info,*image,remap_image,exception);
2822          remap_image=DestroyImage(remap_image);
2823          break;
2824        }
2825      if (LocaleCompare("mask",argv[0]+1) == 0)
2826        {
2827          Image
2828            *mask;
2829
2830          (void) SyncImageSettings(image_info,*image);
2831          if (*argv[0] == '+')
2832            {
2833              /*
2834                Remove a mask.
2835              */
2836              (void) SetImageMask(*image,(Image *) NULL,exception);
2837              break;
2838            }
2839          /*
2840            Set the image mask.
2841          */
2842          mask=GetImageCache(image_info,argv[1],exception);
2843          if (mask == (Image *) NULL)
2844            break;
2845          (void) SetImageMask(*image,mask,exception);
2846          mask=DestroyImage(mask);
2847          break;
2848        }
2849      if (LocaleCompare("matte",argv[0]+1) == 0)
2850        {
2851          (void) SetImageAlphaChannel(*image,(*argv[0] == '-') ?
2852            SetAlphaChannel : DeactivateAlphaChannel,exception);
2853          break;
2854        }
2855      if (LocaleCompare("median",argv[0]+1) == 0)
2856        {
2857          /*
2858            Median filter image.
2859          */
2860          (void) SyncImageSettings(image_info,*image);
2861          flags=ParseGeometry(argv[1],&geometry_info);
2862          if ((flags & SigmaValue) == 0)
2863            geometry_info.sigma=geometry_info.rho;
2864          new_image=StatisticImage(*image,MedianStatistic,(size_t)
2865            geometry_info.rho,(size_t) geometry_info.sigma,exception);
2866          break;
2867        }
2868      if (LocaleCompare("mode",argv[0]+1) == 0)
2869        {
2870          /*
2871            Mode image.
2872          */
2873          (void) SyncImageSettings(image_info,*image);
2874          flags=ParseGeometry(argv[1],&geometry_info);
2875          if ((flags & SigmaValue) == 0)
2876            geometry_info.sigma=geometry_info.rho;
2877          new_image=StatisticImage(*image,ModeStatistic,(size_t)
2878            geometry_info.rho,(size_t) geometry_info.sigma,exception);
2879          break;
2880        }
2881      if (LocaleCompare("modulate",argv[0]+1) == 0)
2882        {
2883          (void) SyncImageSettings(image_info,*image);
2884          (void) ModulateImage(*image,argv[1],exception);
2885          break;
2886        }
2887      if (LocaleCompare("monitor",argv[0]+1) == 0)
2888        {
2889          if (*argv[0] == '+')
2890            {
2891              (void) SetImageProgressMonitor(*image,
2892                (MagickProgressMonitor) NULL,(void *) NULL);
2893              break;
2894            }
2895          (void) SetImageProgressMonitor(*image,MonitorProgress,
2896            (void *) NULL);
2897          break;
2898        }
2899      if (LocaleCompare("monochrome",argv[0]+1) == 0)
2900        {
2901          (void) SyncImageSettings(image_info,*image);
2902          (void) SetImageType(*image,BilevelType,exception);
2903          break;
2904        }
2905      if (LocaleCompare("morphology",argv[0]+1) == 0)
2906        {
2907          char
2908            token[MaxTextExtent];
2909
2910          const char
2911            *p;
2912
2913          KernelInfo
2914            *kernel;
2915
2916          MorphologyMethod
2917            method;
2918
2919          ssize_t
2920            iterations;
2921
2922          /*
2923            Morphological Image Operation
2924          */
2925          (void) SyncImageSettings(image_info,*image);
2926          p=argv[1];
2927          GetMagickToken(p,&p,token);
2928          method=(MorphologyMethod) ParseCommandOption(
2929            MagickMorphologyOptions,MagickFalse,token);
2930          iterations=1L;
2931          GetMagickToken(p,&p,token);
2932          if ((*p == ':') || (*p == ','))
2933            GetMagickToken(p,&p,token);
2934          if ((*p != '\0'))
2935            iterations=(ssize_t) StringToLong(p);
2936          kernel=AcquireKernelInfo(argv[2]);
2937          if (kernel == (KernelInfo *) NULL)
2938            {
2939              (void) ThrowMagickException(exception,GetMagickModule(),
2940                OptionError,"UnabletoParseKernel","morphology");
2941              status=MagickFalse;
2942              break;
2943            }
2944          new_image=MorphologyImage(*image,method,iterations,kernel,
2945            exception);
2946          kernel=DestroyKernelInfo(kernel);
2947          break;
2948        }
2949      if (LocaleCompare("motion-blur",argv[0]+1) == 0)
2950        {
2951          /*
2952            Motion blur image.
2953          */
2954          (void) SyncImageSettings(image_info,*image);
2955          flags=ParseGeometry(argv[1],&geometry_info);
2956          if ((flags & SigmaValue) == 0)
2957            geometry_info.sigma=1.0;
2958          new_image=MotionBlurImage(*image,geometry_info.rho,
2959            geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2960            exception);
2961          break;
2962        }
2963      break;
2964    }
2965    case 'n':
2966    {
2967      if (LocaleCompare("negate",argv[0]+1) == 0)
2968        {
2969          (void) SyncImageSettings(image_info,*image);
2970          (void) NegateImage(*image,*argv[0] == '+' ? MagickTrue :
2971            MagickFalse,exception);
2972          break;
2973        }
2974      if (LocaleCompare("noise",argv[0]+1) == 0)
2975        {
2976          (void) SyncImageSettings(image_info,*image);
2977          if (*argv[0] == '-')
2978            {
2979              flags=ParseGeometry(argv[1],&geometry_info);
2980              if ((flags & SigmaValue) == 0)
2981                geometry_info.sigma=geometry_info.rho;
2982              new_image=StatisticImage(*image,NonpeakStatistic,(size_t)
2983                geometry_info.rho,(size_t) geometry_info.sigma,exception);
2984            }
2985          else
2986            {
2987              NoiseType
2988                noise;
2989
2990              noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
2991                MagickFalse,argv[1]);
2992              new_image=AddNoiseImage(*image,noise,exception);
2993            }
2994          break;
2995        }
2996      if (LocaleCompare("normalize",argv[0]+1) == 0)
2997        {
2998          (void) SyncImageSettings(image_info,*image);
2999          (void) NormalizeImage(*image,exception);
3000          break;
3001        }
3002      break;
3003    }
3004    case 'o':
3005    {
3006      if (LocaleCompare("opaque",argv[0]+1) == 0)
3007        {
3008          PixelInfo
3009            target;
3010
3011          (void) SyncImageSettings(image_info,*image);
3012          (void) QueryMagickColorCompliance(argv[1],AllCompliance,&target,
3013                       exception);
3014          (void) OpaquePaintImage(*image,&target,&fill,*argv[0] == '-' ?
3015            MagickFalse : MagickTrue,exception);
3016          break;
3017        }
3018      if (LocaleCompare("ordered-dither",argv[0]+1) == 0)
3019        {
3020          (void) SyncImageSettings(image_info,*image);
3021          (void) OrderedPosterizeImage(*image,argv[1],exception);
3022          break;
3023        }
3024      break;
3025    }
3026    case 'p':
3027    {
3028      if (LocaleCompare("paint",argv[0]+1) == 0)
3029        {
3030          (void) SyncImageSettings(image_info,*image);
3031          (void) ParseGeometry(argv[1],&geometry_info);
3032          new_image=OilPaintImage(*image,geometry_info.rho,
3033            geometry_info.sigma,exception);
3034          break;
3035        }
3036      if (LocaleCompare("pen",argv[0]+1) == 0)
3037        {
3038          if (*argv[0] == '+')
3039            {
3040              (void) QueryColorCompliance("none",AllCompliance,&draw_info->fill,
3041                 exception);
3042              break;
3043            }
3044          (void) QueryColorCompliance(argv[1],AllCompliance,&draw_info->fill,
3045                 exception);
3046          break;
3047        }
3048      if (LocaleCompare("pointsize",argv[0]+1) == 0)
3049        {
3050          if (*argv[0] == '+')
3051            (void) ParseGeometry("12",&geometry_info);
3052          else
3053            (void) ParseGeometry(argv[1],&geometry_info);
3054          draw_info->pointsize=geometry_info.rho;
3055          break;
3056        }
3057      if (LocaleCompare("polaroid",argv[0]+1) == 0)
3058        {
3059          double
3060            angle;
3061
3062          RandomInfo
3063            *random_info;
3064
3065          /*
3066            Simulate a Polaroid picture.
3067          */
3068          (void) SyncImageSettings(image_info,*image);
3069          random_info=AcquireRandomInfo();
3070          angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
3071          random_info=DestroyRandomInfo(random_info);
3072          if (*argv[0] == '-')
3073            {
3074              SetGeometryInfo(&geometry_info);
3075              flags=ParseGeometry(argv[1],&geometry_info);
3076              angle=geometry_info.rho;
3077            }
3078          new_image=PolaroidImage(*image,draw_info,angle,
3079            interpolate_method,exception);
3080          break;
3081        }
3082      if (LocaleCompare("posterize",argv[0]+1) == 0)
3083        {
3084          /*
3085            Posterize image.
3086          */
3087          (void) SyncImageSettings(image_info,*image);
3088          (void) PosterizeImage(*image,StringToUnsignedLong(argv[1]),
3089            quantize_info->dither,exception);
3090          break;
3091        }
3092      if (LocaleCompare("preview",argv[0]+1) == 0)
3093        {
3094          PreviewType
3095            preview_type;
3096
3097          /*
3098            Preview image.
3099          */
3100          (void) SyncImageSettings(image_info,*image);
3101          if (*argv[0] == '+')
3102            preview_type=UndefinedPreview;
3103          else
3104            preview_type=(PreviewType) ParseCommandOption(
3105              MagickPreviewOptions,MagickFalse,argv[1]);
3106          new_image=PreviewImage(*image,preview_type,exception);
3107          break;
3108        }
3109      if (LocaleCompare("profile",argv[0]+1) == 0)
3110        {
3111          const char
3112            *name;
3113
3114          const StringInfo
3115            *profile;
3116
3117          Image
3118            *profile_image;
3119
3120          ImageInfo
3121            *profile_info;
3122
3123          (void) SyncImageSettings(image_info,*image);
3124          if (*argv[0] == '+')
3125            {
3126              /*
3127                Remove a profile from the image.
3128              */
3129              (void) ProfileImage(*image,argv[1],(const unsigned char *)
3130                NULL,0,MagickTrue);
3131              InheritException(exception,&(*image)->exception);
3132              break;
3133            }
3134          /*
3135            Associate a profile with the image.
3136          */
3137          profile_info=CloneImageInfo(image_info);
3138          profile=GetImageProfile(*image,"iptc");
3139          if (profile != (StringInfo *) NULL)
3140            profile_info->profile=(void *) CloneStringInfo(profile);
3141          profile_image=GetImageCache(profile_info,argv[1],exception);
3142          profile_info=DestroyImageInfo(profile_info);
3143          if (profile_image == (Image *) NULL)
3144            {
3145              StringInfo
3146                *profile;
3147
3148              profile_info=CloneImageInfo(image_info);
3149              (void) CopyMagickString(profile_info->filename,argv[1],
3150                MaxTextExtent);
3151              profile=FileToStringInfo(profile_info->filename,~0UL,exception);
3152              if (profile != (StringInfo *) NULL)
3153                {
3154                  (void) ProfileImage(*image,profile_info->magick,
3155                    GetStringInfoDatum(profile),(size_t)
3156                    GetStringInfoLength(profile),MagickFalse);
3157                  profile=DestroyStringInfo(profile);
3158                }
3159              profile_info=DestroyImageInfo(profile_info);
3160              break;
3161            }
3162          ResetImageProfileIterator(profile_image);
3163          name=GetNextImageProfile(profile_image);
3164          while (name != (const char *) NULL)
3165          {
3166            profile=GetImageProfile(profile_image,name);
3167            if (profile != (StringInfo *) NULL)
3168              (void) ProfileImage(*image,name,GetStringInfoDatum(profile),
3169                (size_t) GetStringInfoLength(profile),MagickFalse);
3170            name=GetNextImageProfile(profile_image);
3171          }
3172          profile_image=DestroyImage(profile_image);
3173          break;
3174        }
3175      break;
3176    }
3177    case 'q':
3178    {
3179      if (LocaleCompare("quantize",argv[0]+1) == 0)
3180        {
3181          if (*argv[0] == '+')
3182            {
3183              quantize_info->colorspace=UndefinedColorspace;
3184              break;
3185            }
3186          quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
3187            MagickColorspaceOptions,MagickFalse,argv[1]);
3188          break;
3189        }
3190      break;
3191    }
3192    case 'r':
3193    {
3194      if (LocaleCompare("radial-blur",argv[0]+1) == 0)
3195        {
3196          /*
3197            Radial blur image.
3198          */
3199          (void) SyncImageSettings(image_info,*image);
3200          flags=ParseGeometry(argv[1],&geometry_info);
3201          new_image=RadialBlurImage(*image,geometry_info.rho,
3202            geometry_info.sigma,exception);
3203          break;
3204        }
3205      if (LocaleCompare("raise",argv[0]+1) == 0)
3206        {
3207          /*
3208            Surround image with a raise of solid color.
3209          */
3210          flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
3211          if ((flags & SigmaValue) == 0)
3212            geometry.height=geometry.width;
3213          (void) RaiseImage(*image,&geometry,*argv[0] == '-' ? MagickTrue :
3214            MagickFalse,exception);
3215          break;
3216        }
3217      if (LocaleCompare("random-threshold",argv[0]+1) == 0)
3218        {
3219          /*
3220            Threshold image.
3221          */
3222          (void) SyncImageSettings(image_info,*image);
3223          (void) RandomThresholdImage(*image,argv[1],exception);
3224          break;
3225        }
3226      if (LocaleCompare("recolor",argv[0]+1) == 0)
3227        {
3228          KernelInfo
3229            *kernel;
3230
3231          (void) SyncImageSettings(image_info,*image);
3232          kernel=AcquireKernelInfo(argv[1]);
3233          if (kernel == (KernelInfo *) NULL)
3234            break;
3235          new_image=ColorMatrixImage(*image,kernel,exception);
3236          kernel=DestroyKernelInfo(kernel);
3237          break;
3238        }
3239      if (LocaleCompare("render",argv[0]+1) == 0)
3240        {
3241          (void) SyncImageSettings(image_info,*image);
3242          draw_info->render=(*argv[0] == '+') ? MagickTrue : MagickFalse;
3243          break;
3244        }
3245      if (LocaleCompare("remap",argv[0]+1) == 0)
3246        {
3247          Image
3248            *remap_image;
3249
3250          /*
3251            Transform image colors to match this set of colors.
3252          */
3253          (void) SyncImageSettings(image_info,*image);
3254          if (*argv[0] == '+')
3255            break;
3256          remap_image=GetImageCache(image_info,argv[1],exception);
3257          if (remap_image == (Image *) NULL)
3258            break;
3259          (void) RemapImage(quantize_info,*image,remap_image,exception);
3260          remap_image=DestroyImage(remap_image);
3261          break;
3262        }
3263      if (LocaleCompare("repage",argv[0]+1) == 0)
3264        {
3265          if (*argv[0] == '+')
3266            {
3267              (void) ParseAbsoluteGeometry("0x0+0+0",&(*image)->page);
3268              break;
3269            }
3270          (void) ResetImagePage(*image,argv[1]);
3271          InheritException(exception,&(*image)->exception);
3272          break;
3273        }
3274      if (LocaleCompare("resample",argv[0]+1) == 0)
3275        {
3276          /*
3277            Resample image.
3278          */
3279          (void) SyncImageSettings(image_info,*image);
3280          flags=ParseGeometry(argv[1],&geometry_info);
3281          if ((flags & SigmaValue) == 0)
3282            geometry_info.sigma=geometry_info.rho;
3283          new_image=ResampleImage(*image,geometry_info.rho,
3284            geometry_info.sigma,(*image)->filter,(*image)->blur,exception);
3285          break;
3286        }
3287      if (LocaleCompare("resize",argv[0]+1) == 0)
3288        {
3289          /*
3290            Resize image.
3291          */
3292          (void) SyncImageSettings(image_info,*image);
3293          (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3294          new_image=ResizeImage(*image,geometry.width,geometry.height,
3295            (*image)->filter,(*image)->blur,exception);
3296          break;
3297        }
3298      if (LocaleCompare("roll",argv[0]+1) == 0)
3299        {
3300          /*
3301            Roll image.
3302          */
3303          (void) SyncImageSettings(image_info,*image);
3304          (void) ParsePageGeometry(*image,argv[1],&geometry,exception);
3305          new_image=RollImage(*image,geometry.x,geometry.y,exception);
3306          break;
3307        }
3308      if (LocaleCompare("rotate",argv[0]+1) == 0)
3309        {
3310          char
3311            *geometry;
3312
3313          /*
3314            Check for conditional image rotation.
3315          */
3316          (void) SyncImageSettings(image_info,*image);
3317          if (strchr(argv[1],'>') != (char *) NULL)
3318            if ((*image)->columns <= (*image)->rows)
3319              break;
3320          if (strchr(argv[1],'<') != (char *) NULL)
3321            if ((*image)->columns >= (*image)->rows)
3322              break;
3323          /*
3324            Rotate image.
3325          */
3326          geometry=ConstantString(argv[1]);
3327          (void) SubstituteString(&geometry,">","");
3328          (void) SubstituteString(&geometry,"<","");
3329          (void) ParseGeometry(geometry,&geometry_info);
3330          geometry=DestroyString(geometry);
3331          new_image=RotateImage(*image,geometry_info.rho,exception);
3332          break;
3333        }
3334      break;
3335    }
3336    case 's':
3337    {
3338      if (LocaleCompare("sample",argv[0]+1) == 0)
3339        {
3340          /*
3341            Sample image with pixel replication.
3342          */
3343          (void) SyncImageSettings(image_info,*image);
3344          (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3345          new_image=SampleImage(*image,geometry.width,geometry.height,
3346            exception);
3347          break;
3348        }
3349      if (LocaleCompare("scale",argv[0]+1) == 0)
3350        {
3351          /*
3352            Resize image.
3353          */
3354          (void) SyncImageSettings(image_info,*image);
3355          (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3356          new_image=ScaleImage(*image,geometry.width,geometry.height,
3357            exception);
3358          break;
3359        }
3360      if (LocaleCompare("selective-blur",argv[0]+1) == 0)
3361        {
3362          /*
3363            Selectively blur pixels within a contrast threshold.
3364          */
3365          (void) SyncImageSettings(image_info,*image);
3366          flags=ParseGeometry(argv[1],&geometry_info);
3367          if ((flags & PercentValue) != 0)
3368            geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3369          new_image=SelectiveBlurImage(*image,geometry_info.rho,
3370            geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3371          break;
3372        }
3373      if (LocaleCompare("separate",argv[0]+1) == 0)
3374        {
3375          /*
3376            Break channels into separate images.
3377            WARNING: This can generate multiple images!
3378          */
3379          (void) SyncImageSettings(image_info,*image);
3380          new_image=SeparateImages(*image,exception);
3381          break;
3382        }
3383      if (LocaleCompare("sepia-tone",argv[0]+1) == 0)
3384        {
3385          double
3386            threshold;
3387
3388          /*
3389            Sepia-tone image.
3390          */
3391          (void) SyncImageSettings(image_info,*image);
3392          threshold=SiPrefixToDouble(argv[1],QuantumRange);
3393          new_image=SepiaToneImage(*image,threshold,exception);
3394          break;
3395        }
3396      if (LocaleCompare("segment",argv[0]+1) == 0)
3397        {
3398          /*
3399            Segment image.
3400          */
3401          (void) SyncImageSettings(image_info,*image);
3402          flags=ParseGeometry(argv[1],&geometry_info);
3403          if ((flags & SigmaValue) == 0)
3404            geometry_info.sigma=1.0;
3405          (void) SegmentImage(*image,(*image)->colorspace,
3406            image_info->verbose,geometry_info.rho,geometry_info.sigma,
3407            exception);
3408          break;
3409        }
3410      if (LocaleCompare("set",argv[0]+1) == 0)
3411        {
3412          char
3413            *value;
3414
3415          if (*argv[0] == '+')
3416            {
3417              if (LocaleNCompare(argv[1],"registry:",9) == 0)
3418                (void) DeleteImageRegistry(argv[1]+9);
3419              else
3420                if (LocaleNCompare(argv[1],"argv[0]:",7) == 0)
3421                  {
3422                    (void) DeleteImageOption(image_info,argv[1]+7);
3423                    (void) DeleteImageArtifact(*image,argv[1]+7);
3424                  }
3425                else
3426                  (void) DeleteImageProperty(*image,argv[1]);
3427              break;
3428            }
3429          value=InterpretImageProperties(image_info,*image,argv[2],
3430            exception);
3431          if (value == (char *) NULL)
3432            break;
3433          if (LocaleNCompare(argv[1],"registry:",9) == 0)
3434            (void) SetImageRegistry(StringRegistryType,argv[1]+9,value,
3435              exception);
3436          else
3437            if (LocaleNCompare(argv[1],"option:",7) == 0)
3438              {
3439                (void) SetImageOption(image_info,argv[1]+7,value);
3440                (void) SetImageArtifact(*image,argv[1]+7,value);
3441              }
3442            else
3443              (void) SetImageProperty(*image,argv[1],value);
3444          value=DestroyString(value);
3445          break;
3446        }
3447      if (LocaleCompare("shade",argv[0]+1) == 0)
3448        {
3449          /*
3450            Shade image.
3451          */
3452          (void) SyncImageSettings(image_info,*image);
3453          flags=ParseGeometry(argv[1],&geometry_info);
3454          if ((flags & SigmaValue) == 0)
3455            geometry_info.sigma=1.0;
3456          new_image=ShadeImage(*image,(*argv[0] == '-') ? MagickTrue :
3457            MagickFalse,geometry_info.rho,geometry_info.sigma,exception);
3458          break;
3459        }
3460      if (LocaleCompare("shadow",argv[0]+1) == 0)
3461        {
3462          /*
3463            Shadow image.
3464          */
3465          (void) SyncImageSettings(image_info,*image);
3466          flags=ParseGeometry(argv[1],&geometry_info);
3467          if ((flags & SigmaValue) == 0)
3468            geometry_info.sigma=1.0;
3469          if ((flags & XiValue) == 0)
3470            geometry_info.xi=4.0;
3471          if ((flags & PsiValue) == 0)
3472            geometry_info.psi=4.0;
3473          new_image=ShadowImage(*image,geometry_info.rho,
3474            geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3475            ceil(geometry_info.psi-0.5),exception);
3476          break;
3477        }
3478      if (LocaleCompare("sharpen",argv[0]+1) == 0)
3479        {
3480          /*
3481            Sharpen image.
3482          */
3483          (void) SyncImageSettings(image_info,*image);
3484          flags=ParseGeometry(argv[1],&geometry_info);
3485          if ((flags & SigmaValue) == 0)
3486            geometry_info.sigma=1.0;
3487          if ((flags & XiValue) == 0)
3488            geometry_info.xi=0.0;
3489          new_image=SharpenImage(*image,geometry_info.rho,
3490            geometry_info.sigma,geometry_info.xi,exception);
3491          break;
3492        }
3493      if (LocaleCompare("shave",argv[0]+1) == 0)
3494        {
3495          /*
3496            Shave the image edges.
3497          */
3498          (void) SyncImageSettings(image_info,*image);
3499          flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
3500          new_image=ShaveImage(*image,&geometry,exception);
3501          break;
3502        }
3503      if (LocaleCompare("shear",argv[0]+1) == 0)
3504        {
3505          /*
3506            Shear image.
3507          */
3508          (void) SyncImageSettings(image_info,*image);
3509          flags=ParseGeometry(argv[1],&geometry_info);
3510          if ((flags & SigmaValue) == 0)
3511            geometry_info.sigma=geometry_info.rho;
3512          new_image=ShearImage(*image,geometry_info.rho,
3513            geometry_info.sigma,exception);
3514          break;
3515        }
3516      if (LocaleCompare("sigmoidal-contrast",argv[0]+1) == 0)
3517        {
3518          /*
3519            Sigmoidal non-linearity contrast control.
3520          */
3521          (void) SyncImageSettings(image_info,*image);
3522          flags=ParseGeometry(argv[1],&geometry_info);
3523          if ((flags & SigmaValue) == 0)
3524            geometry_info.sigma=(double) QuantumRange/2.0;
3525          if ((flags & PercentValue) != 0)
3526            geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3527              100.0;
3528          (void) SigmoidalContrastImage(*image,(*argv[0] == '-') ?
3529            MagickTrue : MagickFalse,geometry_info.rho,geometry_info.sigma,
3530            exception);
3531          break;
3532        }
3533      if (LocaleCompare("sketch",argv[0]+1) == 0)
3534        {
3535          /*
3536            Sketch image.
3537          */
3538          (void) SyncImageSettings(image_info,*image);
3539          flags=ParseGeometry(argv[1],&geometry_info);
3540          if ((flags & SigmaValue) == 0)
3541            geometry_info.sigma=1.0;
3542          new_image=SketchImage(*image,geometry_info.rho,
3543            geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3544          break;
3545        }
3546      if (LocaleCompare("solarize",argv[0]+1) == 0)
3547        {
3548          double
3549            threshold;
3550
3551          (void) SyncImageSettings(image_info,*image);
3552          threshold=SiPrefixToDouble(argv[1],QuantumRange);
3553          (void) SolarizeImage(*image,threshold,exception);
3554          break;
3555        }
3556      if (LocaleCompare("sparse-color",argv[0]+1) == 0)
3557        {
3558          SparseColorMethod
3559            method;
3560
3561          char
3562            *arguments;
3563
3564          /*
3565            Sparse Color Interpolated Gradient
3566          */
3567          (void) SyncImageSettings(image_info,*image);
3568          method=(SparseColorMethod) ParseCommandOption(
3569            MagickSparseColorOptions,MagickFalse,argv[1]);
3570          arguments=InterpretImageProperties(image_info,*image,argv[2],
3571            exception);
3572          if (arguments == (char *) NULL)
3573            break;
3574          new_image=SparseColorOption(*image,method,arguments,
3575            argv[0][0] == '+' ? MagickTrue : MagickFalse,exception);
3576          arguments=DestroyString(arguments);
3577          break;
3578        }
3579      if (LocaleCompare("splice",argv[0]+1) == 0)
3580        {
3581          /*
3582            Splice a solid color into the image.
3583          */
3584          (void) SyncImageSettings(image_info,*image);
3585          (void) ParseGravityGeometry(*image,argv[1],&geometry,exception);
3586          new_image=SpliceImage(*image,&geometry,exception);
3587          break;
3588        }
3589      if (LocaleCompare("spread",argv[0]+1) == 0)
3590        {
3591          /*
3592            Spread an image.
3593          */
3594          (void) SyncImageSettings(image_info,*image);
3595          (void) ParseGeometry(argv[1],&geometry_info);
3596          new_image=SpreadImage(*image,geometry_info.rho,
3597            interpolate_method,exception);
3598          break;
3599        }
3600      if (LocaleCompare("statistic",argv[0]+1) == 0)
3601        {
3602          StatisticType
3603            type;
3604
3605          (void) SyncImageSettings(image_info,*image);
3606          type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
3607            MagickFalse,argv[1]);
3608          (void) ParseGeometry(argv[2],&geometry_info);
3609          new_image=StatisticImage(*image,type,(size_t) geometry_info.rho,
3610            (size_t) geometry_info.sigma,exception);
3611          break;
3612        }
3613      if (LocaleCompare("stretch",argv[0]+1) == 0)
3614        {
3615          if (*argv[0] == '+')
3616            {
3617              draw_info->stretch=UndefinedStretch;
3618              break;
3619            }
3620          draw_info->stretch=(StretchType) ParseCommandOption(
3621            MagickStretchOptions,MagickFalse,argv[1]);
3622          break;
3623        }
3624      if (LocaleCompare("strip",argv[0]+1) == 0)
3625        {
3626          /*
3627            Strip image of profiles and comments.
3628          */
3629          (void) SyncImageSettings(image_info,*image);
3630          (void) StripImage(*image);
3631          InheritException(exception,&(*image)->exception);
3632          break;
3633        }
3634      if (LocaleCompare("stroke",argv[0]+1) == 0)
3635        {
3636          ExceptionInfo
3637            *sans;
3638
3639          if (*argv[0] == '+')
3640            {
3641              (void) QueryColorCompliance("none",AllCompliance,&draw_info->stroke,
3642                exception);
3643              if (draw_info->stroke_pattern != (Image *) NULL)
3644                draw_info->stroke_pattern=DestroyImage(
3645                  draw_info->stroke_pattern);
3646              break;
3647            }
3648          sans=AcquireExceptionInfo();
3649          status=QueryColorCompliance(argv[1],AllCompliance,&draw_info->stroke,sans);
3650          sans=DestroyExceptionInfo(sans);
3651          if (status == MagickFalse)
3652            draw_info->stroke_pattern=GetImageCache(image_info,argv[1],
3653              exception);
3654          break;
3655        }
3656      if (LocaleCompare("strokewidth",argv[0]+1) == 0)
3657        {
3658          draw_info->stroke_width=InterpretLocaleValue(argv[1],
3659            (char **) NULL);
3660          break;
3661        }
3662      if (LocaleCompare("style",argv[0]+1) == 0)
3663        {
3664          if (*argv[0] == '+')
3665            {
3666              draw_info->style=UndefinedStyle;
3667              break;
3668            }
3669          draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
3670            MagickFalse,argv[1]);
3671          break;
3672        }
3673      if (LocaleCompare("swirl",argv[0]+1) == 0)
3674        {
3675          /*
3676            Swirl image.
3677          */
3678          (void) SyncImageSettings(image_info,*image);
3679          (void) ParseGeometry(argv[1],&geometry_info);
3680          new_image=SwirlImage(*image,geometry_info.rho,
3681            interpolate_method,exception);
3682          break;
3683        }
3684      break;
3685    }
3686    case 't':
3687    {
3688      if (LocaleCompare("threshold",argv[0]+1) == 0)
3689        {
3690          double
3691            threshold;
3692
3693          /*
3694            Threshold image.
3695          */
3696          (void) SyncImageSettings(image_info,*image);
3697          if (*argv[0] == '+')
3698            threshold=(double) QuantumRange/2;
3699          else
3700            threshold=SiPrefixToDouble(argv[1],QuantumRange);
3701          (void) BilevelImage(*image,threshold);
3702          InheritException(exception,&(*image)->exception);
3703          break;
3704        }
3705      if (LocaleCompare("thumbnail",argv[0]+1) == 0)
3706        {
3707          /*
3708            Thumbnail image.
3709          */
3710          (void) SyncImageSettings(image_info,*image);
3711          (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3712          new_image=ThumbnailImage(*image,geometry.width,geometry.height,
3713            exception);
3714          break;
3715        }
3716      if (LocaleCompare("tile",argv[0]+1) == 0)
3717        {
3718          if (*argv[0] == '+')
3719            {
3720              if (draw_info->fill_pattern != (Image *) NULL)
3721                draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
3722              break;
3723            }
3724          draw_info->fill_pattern=GetImageCache(image_info,argv[1],
3725            exception);
3726          break;
3727        }
3728      if (LocaleCompare("tint",argv[0]+1) == 0)
3729        {
3730          /*
3731            Tint the image.
3732          */
3733          (void) SyncImageSettings(image_info,*image);
3734          new_image=TintImage(*image,argv[1],&fill,exception);
3735          break;
3736        }
3737      if (LocaleCompare("transform",argv[0]+1) == 0)
3738        {
3739          /*
3740            Affine transform image.
3741          */
3742          (void) SyncImageSettings(image_info,*image);
3743          new_image=AffineTransformImage(*image,&draw_info->affine,
3744            exception);
3745          break;
3746        }
3747      if (LocaleCompare("transparent",argv[0]+1) == 0)
3748        {
3749          PixelInfo
3750            target;
3751
3752          (void) SyncImageSettings(image_info,*image);
3753          (void) QueryMagickColorCompliance(argv[1],AllCompliance,&target,
3754                       exception);
3755          (void) TransparentPaintImage(*image,&target,(Quantum)
3756            TransparentAlpha,*argv[0] == '-' ? MagickFalse : MagickTrue,
3757            &(*image)->exception);
3758          break;
3759        }
3760      if (LocaleCompare("transpose",argv[0]+1) == 0)
3761        {
3762          /*
3763            Transpose image scanlines.
3764          */
3765          (void) SyncImageSettings(image_info,*image);
3766          new_image=TransposeImage(*image,exception);
3767          break;
3768        }
3769      if (LocaleCompare("transverse",argv[0]+1) == 0)
3770        {
3771          /*
3772            Transverse image scanlines.
3773          */
3774          (void) SyncImageSettings(image_info,*image);
3775          new_image=TransverseImage(*image,exception);
3776          break;
3777        }
3778      if (LocaleCompare("treedepth",argv[0]+1) == 0)
3779        {
3780          quantize_info->tree_depth=StringToUnsignedLong(argv[1]);
3781          break;
3782        }
3783      if (LocaleCompare("trim",argv[0]+1) == 0)
3784        {
3785          /*
3786            Trim image.
3787          */
3788          (void) SyncImageSettings(image_info,*image);
3789          new_image=TrimImage(*image,exception);
3790          break;
3791        }
3792      if (LocaleCompare("type",argv[0]+1) == 0)
3793        {
3794          ImageType
3795            type;
3796
3797          (void) SyncImageSettings(image_info,*image);
3798          if (*argv[0] == '+')
3799            type=UndefinedType;
3800          else
3801            type=(ImageType) ParseCommandOption(MagickTypeOptions,MagickFalse,
3802              argv[1]);
3803          (*image)->type=UndefinedType;
3804          (void) SetImageType(*image,type,exception);
3805          break;
3806        }
3807      break;
3808    }
3809    case 'u':
3810    {
3811      if (LocaleCompare("undercolor",argv[0]+1) == 0)
3812        {
3813          (void) QueryColorCompliance(argv[1],AllCompliance,&draw_info->undercolor,
3814            exception);
3815          break;
3816        }
3817      if (LocaleCompare("unique",argv[0]+1) == 0)
3818        {
3819          if (*argv[0] == '+')
3820            {
3821              (void) DeleteImageArtifact(*image,"identify:unique-colors");
3822              break;
3823            }
3824          (void) SetImageArtifact(*image,"identify:unique-colors","true");
3825          (void) SetImageArtifact(*image,"verbose","true");
3826          break;
3827        }
3828      if (LocaleCompare("unique-colors",argv[0]+1) == 0)
3829        {
3830          /*
3831            Unique image colors.
3832          */
3833          (void) SyncImageSettings(image_info,*image);
3834          new_image=UniqueImageColors(*image,exception);
3835          break;
3836        }
3837      if (LocaleCompare("unsharp",argv[0]+1) == 0)
3838        {
3839          /*
3840            Unsharp mask image.
3841          */
3842          (void) SyncImageSettings(image_info,*image);
3843          flags=ParseGeometry(argv[1],&geometry_info);
3844          if ((flags & SigmaValue) == 0)
3845            geometry_info.sigma=1.0;
3846          if ((flags & XiValue) == 0)
3847            geometry_info.xi=1.0;
3848          if ((flags & PsiValue) == 0)
3849            geometry_info.psi=0.05;
3850          new_image=UnsharpMaskImage(*image,geometry_info.rho,
3851            geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3852          break;
3853        }
3854      break;
3855    }
3856    case 'v':
3857    {
3858      if (LocaleCompare("verbose",argv[0]+1) == 0)
3859        {
3860          (void) SetImageArtifact(*image,argv[0]+1,
3861            *argv[0] == '+' ? "false" : "true");
3862          break;
3863        }
3864      if (LocaleCompare("vignette",argv[0]+1) == 0)
3865        {
3866          /*
3867            Vignette image.
3868          */
3869          (void) SyncImageSettings(image_info,*image);
3870          flags=ParseGeometry(argv[1],&geometry_info);
3871          if ((flags & SigmaValue) == 0)
3872            geometry_info.sigma=1.0;
3873          if ((flags & XiValue) == 0)
3874            geometry_info.xi=0.1*(*image)->columns;
3875          if ((flags & PsiValue) == 0)
3876            geometry_info.psi=0.1*(*image)->rows;
3877          new_image=VignetteImage(*image,geometry_info.rho,
3878            geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3879            ceil(geometry_info.psi-0.5),exception);
3880          break;
3881        }
3882      if (LocaleCompare("virtual-pixel",argv[0]+1) == 0)
3883        {
3884          if (*argv[0] == '+')
3885            {
3886              (void) SetImageVirtualPixelMethod(*image,
3887                UndefinedVirtualPixelMethod);
3888              break;
3889            }
3890          (void) SetImageVirtualPixelMethod(*image,(VirtualPixelMethod)
3891            ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
3892            argv[1]));
3893          break;
3894        }
3895      break;
3896    }
3897    case 'w':
3898    {
3899      if (LocaleCompare("wave",argv[0]+1) == 0)
3900        {
3901          /*
3902            Wave image.
3903          */
3904          (void) SyncImageSettings(image_info,*image);
3905          flags=ParseGeometry(argv[1],&geometry_info);
3906          if ((flags & SigmaValue) == 0)
3907            geometry_info.sigma=1.0;
3908          new_image=WaveImage(*image,geometry_info.rho,
3909            geometry_info.sigma,interpolate_method,exception);
3910          break;
3911        }
3912      if (LocaleCompare("weight",argv[0]+1) == 0)
3913        {
3914          draw_info->weight=StringToUnsignedLong(argv[1]);
3915          if (LocaleCompare(argv[1],"all") == 0)
3916            draw_info->weight=0;
3917          if (LocaleCompare(argv[1],"bold") == 0)
3918            draw_info->weight=700;
3919          if (LocaleCompare(argv[1],"bolder") == 0)
3920            if (draw_info->weight <= 800)
3921              draw_info->weight+=100;
3922          if (LocaleCompare(argv[1],"lighter") == 0)
3923            if (draw_info->weight >= 100)
3924              draw_info->weight-=100;
3925          if (LocaleCompare(argv[1],"normal") == 0)
3926            draw_info->weight=400;
3927          break;
3928        }
3929      if (LocaleCompare("white-threshold",argv[0]+1) == 0)
3930        {
3931          /*
3932            White threshold image.
3933          */
3934          (void) SyncImageSettings(image_info,*image);
3935          (void) WhiteThresholdImage(*image,argv[1],exception);
3936          InheritException(exception,&(*image)->exception);
3937          break;
3938        }
3939      break;
3940    }
3941    default:
3942      break;
3943  }
3944  /*
3945     Replace current image with any image that was generated
3946  */
3947  if (new_image != (Image *) NULL)
3948    ReplaceImageInListReturnLast(image,new_image);
3949
3950  /*
3951    Free resources.
3952  */
3953  quantize_info=DestroyQuantizeInfo(quantize_info);
3954  draw_info=DestroyDrawInfo(draw_info);
3955  status=(MagickStatusType) ((*image)->exception.severity ==
3956    UndefinedException ? 1 : 0);
3957  return(status == 0 ? MagickFalse : MagickTrue);
3958}
3959
3960/*
3961%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3962%                                                                             %
3963%                                                                             %
3964%                                                                             %
3965+     S e q u e n c e O p e r a t i o n I m a g e s                           %
3966%                                                                             %
3967%                                                                             %
3968%                                                                             %
3969%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3970%
3971%  SequenceOperationImages() applies a single operation that apply to the
3972%  entire image list (e.g. -append, -layers, -coalesce, etc.).
3973%
3974%  The format of the MogrifyImage method is:
3975%
3976%    MagickBooleanType SequenceOperationImages(ImageInfo *image_info,
3977%        const int argc, const char **argv,Image **images,
3978%        ExceptionInfo *exception)
3979%
3980%  A description of each parameter follows:
3981%
3982%    o image_info: the image info..
3983%
3984%    o argc: Specifies a pointer to an integer describing the number of
3985%      elements in the argument vector.
3986%
3987%    o argv: Specifies a pointer to a text array containing the command line
3988%      arguments.
3989%
3990%    o images: pointer to pointer of the first image in image list.
3991%
3992%    o exception: return any errors or warnings in this structure.
3993%
3994*/
3995WandExport MagickBooleanType SequenceOperationImages(ImageInfo *image_info,
3996  const int argc,const char **argv,Image **images,ExceptionInfo *exception)
3997{
3998
3999  MagickStatusType
4000    status;
4001
4002  QuantizeInfo
4003    *quantize_info;
4004
4005  assert(image_info != (ImageInfo *) NULL);
4006  assert(image_info->signature == MagickSignature);
4007  assert(images != (Image **) NULL);
4008  assert((*images)->previous == (Image *) NULL);
4009  assert((*images)->signature == MagickSignature);
4010  if ((*images)->debug != MagickFalse)
4011    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4012      (*images)->filename);
4013  if ((argc <= 0) || (*argv == (char *) NULL))
4014    return(MagickTrue);
4015  status=MagickTrue;
4016
4017  switch (*(argv[0]+1))
4018  {
4019    case 'a':
4020    {
4021      if (LocaleCompare("affinity",argv[0]+1) == 0)
4022        {
4023          (void) SyncImagesSettings(image_info,*images);
4024          if (*argv[0] == '+')
4025            {
4026              (void) RemapImages(quantize_info,*images,(Image *) NULL,
4027                exception);
4028              break;
4029            }
4030          break;
4031        }
4032      if (LocaleCompare("append",argv[0]+1) == 0)
4033        {
4034          Image
4035            *append_image;
4036
4037          (void) SyncImagesSettings(image_info,*images);
4038          append_image=AppendImages(*images,*argv[0] == '-' ? MagickTrue :
4039            MagickFalse,exception);
4040          if (append_image == (Image *) NULL)
4041            {
4042              status=MagickFalse;
4043              break;
4044            }
4045          *images=DestroyImageList(*images);
4046          *images=append_image;
4047          break;
4048        }
4049      if (LocaleCompare("average",argv[0]+1) == 0)
4050        {
4051          Image
4052            *average_image;
4053
4054          /*
4055            Average an image sequence (deprecated).
4056          */
4057          (void) SyncImagesSettings(image_info,*images);
4058          average_image=EvaluateImages(*images,MeanEvaluateOperator,
4059            exception);
4060          if (average_image == (Image *) NULL)
4061            {
4062              status=MagickFalse;
4063              break;
4064            }
4065          *images=DestroyImageList(*images);
4066          *images=average_image;
4067          break;
4068        }
4069      break;
4070    }
4071    case 'c':
4072    {
4073      if (LocaleCompare("channel",argv[0]+1) == 0)
4074        {
4075          ChannelType
4076            channel;
4077
4078          if (*argv[0] == '+')
4079            {
4080              channel=DefaultChannels;
4081              break;
4082            }
4083          channel=(ChannelType) ParseChannelOption(argv[1]);
4084          SetPixelChannelMap(*images,channel);
4085          break;
4086        }
4087      if (LocaleCompare("clut",argv[0]+1) == 0)
4088        {
4089          Image
4090            *clut_image,
4091            *image;
4092
4093          (void) SyncImagesSettings(image_info,*images);
4094          image=RemoveFirstImageFromList(images);
4095          clut_image=RemoveFirstImageFromList(images);
4096          if (clut_image == (Image *) NULL)
4097            {
4098              status=MagickFalse;
4099              break;
4100            }
4101          (void) ClutImage(image,clut_image,interpolate_method,exception);
4102          clut_image=DestroyImage(clut_image);
4103          *images=DestroyImageList(*images);
4104          *images=image;
4105          break;
4106        }
4107      if (LocaleCompare("coalesce",argv[0]+1) == 0)
4108        {
4109          Image
4110            *coalesce_image;
4111
4112          (void) SyncImagesSettings(image_info,*images);
4113          coalesce_image=CoalesceImages(*images,exception);
4114          if (coalesce_image == (Image *) NULL)
4115            {
4116              status=MagickFalse;
4117              break;
4118            }
4119          *images=DestroyImageList(*images);
4120          *images=coalesce_image;
4121          break;
4122        }
4123      if (LocaleCompare("combine",argv[0]+1) == 0)
4124        {
4125          Image
4126            *combine_image;
4127
4128          (void) SyncImagesSettings(image_info,*images);
4129          combine_image=CombineImages(*images,exception);
4130          if (combine_image == (Image *) NULL)
4131            {
4132              status=MagickFalse;
4133              break;
4134            }
4135          *images=DestroyImageList(*images);
4136          *images=combine_image;
4137          break;
4138        }
4139      if (LocaleCompare("composite",argv[0]+1) == 0)
4140        {
4141          Image
4142            *mask_image,
4143            *composite_image,
4144            *image;
4145
4146          RectangleInfo
4147            geometry;
4148
4149          (void) SyncImagesSettings(image_info,*images);
4150          image=RemoveFirstImageFromList(images);
4151          composite_image=RemoveFirstImageFromList(images);
4152          if (composite_image == (Image *) NULL)
4153            {
4154              status=MagickFalse;
4155              break;
4156            }
4157          (void) TransformImage(&composite_image,(char *) NULL,
4158            composite_image->geometry);
4159          SetGeometry(composite_image,&geometry);
4160          (void) ParseAbsoluteGeometry(composite_image->geometry,&geometry);
4161          GravityAdjustGeometry(image->columns,image->rows,image->gravity,
4162            &geometry);
4163          mask_image=RemoveFirstImageFromList(images);
4164          if (mask_image != (Image *) NULL)
4165            {
4166              if ((image->compose == DisplaceCompositeOp) ||
4167                  (image->compose == DistortCompositeOp))
4168                {
4169                  /*
4170                    Merge Y displacement into X displacement image.
4171                  */
4172                  (void) CompositeImage(composite_image,CopyGreenCompositeOp,
4173                    mask_image,0,0);
4174                  mask_image=DestroyImage(mask_image);
4175                }
4176              else
4177                {
4178                  /*
4179                    Set a blending mask for the composition.
4180                    Posible error, what if image->mask already set.
4181                  */
4182                  image->mask=mask_image;
4183                  (void) NegateImage(image->mask,MagickFalse,exception);
4184                }
4185            }
4186          (void) CompositeImage(image,image->compose,composite_image,
4187            geometry.x,geometry.y);
4188          if (mask_image != (Image *) NULL)
4189            mask_image=image->mask=DestroyImage(image->mask);
4190          composite_image=DestroyImage(composite_image);
4191          InheritException(exception,&image->exception);
4192          *images=DestroyImageList(*images);
4193          *images=image;
4194          break;
4195        }
4196      break;
4197    }
4198    case 'd':
4199    {
4200      if (LocaleCompare("deconstruct",argv[0]+1) == 0)
4201        {
4202          Image
4203            *deconstruct_image;
4204
4205          (void) SyncImagesSettings(image_info,*images);
4206          deconstruct_image=CompareImagesLayers(*images,CompareAnyLayer,
4207            exception);
4208          if (deconstruct_image == (Image *) NULL)
4209            {
4210              status=MagickFalse;
4211              break;
4212            }
4213          *images=DestroyImageList(*images);
4214          *images=deconstruct_image;
4215          break;
4216        }
4217      if (LocaleCompare("delete",argv[0]+1) == 0)
4218        {
4219          if (*argv[0] == '+')
4220            DeleteImages(images,"-1",exception);
4221          else
4222            DeleteImages(images,argv[1],exception);
4223          break;
4224        }
4225      if (LocaleCompare("dither",argv[0]+1) == 0)
4226        {
4227          if (*argv[0] == '+')
4228            {
4229              quantize_info->dither=MagickFalse;
4230              break;
4231            }
4232          quantize_info->dither=MagickTrue;
4233          quantize_info->dither_method=(DitherMethod) ParseCommandOption(
4234            MagickDitherOptions,MagickFalse,argv[1]);
4235          break;
4236        }
4237      if (LocaleCompare("duplicate",argv[0]+1) == 0)
4238        {
4239          Image
4240            *duplicate_images;
4241
4242          if (*argv[0] == '+')
4243            duplicate_images=DuplicateImages(*images,1,"-1",exception);
4244          else
4245            {
4246              const char
4247                *p;
4248
4249              size_t
4250                number_duplicates;
4251
4252              number_duplicates=(size_t) StringToLong(argv[1]);
4253              p=strchr(argv[1],',');
4254              if (p == (const char *) NULL)
4255                duplicate_images=DuplicateImages(*images,number_duplicates,
4256                  "-1",exception);
4257              else
4258                duplicate_images=DuplicateImages(*images,number_duplicates,p,
4259                  exception);
4260            }
4261          AppendImageToList(images, duplicate_images);
4262          (void) SyncImagesSettings(image_info,*images);
4263          break;
4264        }
4265      break;
4266    }
4267    case 'e':
4268    {
4269      if (LocaleCompare("evaluate-sequence",argv[0]+1) == 0)
4270        {
4271          Image
4272            *evaluate_image;
4273
4274          MagickEvaluateOperator
4275            op;
4276
4277          (void) SyncImageSettings(image_info,*images);
4278          op=(MagickEvaluateOperator) ParseCommandOption(
4279            MagickEvaluateOptions,MagickFalse,argv[1]);
4280          evaluate_image=EvaluateImages(*images,op,exception);
4281          if (evaluate_image == (Image *) NULL)
4282            {
4283              status=MagickFalse;
4284              break;
4285            }
4286          *images=DestroyImageList(*images);
4287          *images=evaluate_image;
4288          break;
4289        }
4290      break;
4291    }
4292    case 'f':
4293    {
4294      if (LocaleCompare("fft",argv[0]+1) == 0)
4295        {
4296          Image
4297            *fourier_image;
4298
4299          /*
4300            Implements the discrete Fourier transform (DFT).
4301          */
4302          (void) SyncImageSettings(image_info,*images);
4303          fourier_image=ForwardFourierTransformImage(*images,*argv[0] == '-' ?
4304            MagickTrue : MagickFalse,exception);
4305          if (fourier_image == (Image *) NULL)
4306            break;
4307          *images=DestroyImage(*images);
4308          *images=fourier_image;
4309          break;
4310        }
4311      if (LocaleCompare("flatten",argv[0]+1) == 0)
4312        {
4313          Image
4314            *flatten_image;
4315
4316          (void) SyncImagesSettings(image_info,*images);
4317          flatten_image=MergeImageLayers(*images,FlattenLayer,exception);
4318          if (flatten_image == (Image *) NULL)
4319            break;
4320          *images=DestroyImageList(*images);
4321          *images=flatten_image;
4322          break;
4323        }
4324      if (LocaleCompare("fx",argv[0]+1) == 0)
4325        {
4326          Image
4327            *fx_image;
4328
4329          (void) SyncImagesSettings(image_info,*images);
4330          fx_image=FxImage(*images,argv[1],exception);
4331          if (fx_image == (Image *) NULL)
4332            {
4333              status=MagickFalse;
4334              break;
4335            }
4336          *images=DestroyImageList(*images);
4337          *images=fx_image;
4338          break;
4339        }
4340      break;
4341    }
4342    case 'h':
4343    {
4344      if (LocaleCompare("hald-clut",argv[0]+1) == 0)
4345        {
4346          Image
4347            *hald_image,
4348            *image;
4349
4350          (void) SyncImagesSettings(image_info,*images);
4351          image=RemoveFirstImageFromList(images);
4352          hald_image=RemoveFirstImageFromList(images);
4353          if (hald_image == (Image *) NULL)
4354            {
4355              status=MagickFalse;
4356              break;
4357            }
4358          (void) HaldClutImage(image,hald_image,exception);
4359          hald_image=DestroyImage(hald_image);
4360          if (*images != (Image *) NULL)
4361            *images=DestroyImageList(*images);
4362          *images=image;
4363          break;
4364        }
4365      break;
4366    }
4367    case 'i':
4368    {
4369      if (LocaleCompare("ift",argv[0]+1) == 0)
4370        {
4371          Image
4372            *fourier_image,
4373            *magnitude_image,
4374            *phase_image;
4375
4376          /*
4377            Implements the inverse fourier discrete Fourier transform (DFT).
4378          */
4379          (void) SyncImagesSettings(image_info,*images);
4380          magnitude_image=RemoveFirstImageFromList(images);
4381          phase_image=RemoveFirstImageFromList(images);
4382          if (phase_image == (Image *) NULL)
4383            {
4384              status=MagickFalse;
4385              break;
4386            }
4387          fourier_image=InverseFourierTransformImage(magnitude_image,
4388            phase_image,*argv[0] == '-' ? MagickTrue : MagickFalse,exception);
4389          if (fourier_image == (Image *) NULL)
4390            break;
4391          if (*images != (Image *) NULL)
4392            *images=DestroyImage(*images);
4393          *images=fourier_image;
4394          break;
4395        }
4396      if (LocaleCompare("insert",argv[0]+1) == 0)
4397        {
4398          Image
4399            *p,
4400            *q;
4401
4402          index=0;
4403          if (*argv[0] != '+')
4404            index=(ssize_t) StringToLong(argv[1]);
4405          p=RemoveLastImageFromList(images);
4406          if (p == (Image *) NULL)
4407            {
4408              (void) ThrowMagickException(exception,GetMagickModule(),
4409                OptionError,"NoSuchImage","`%s'",argv[1]);
4410              status=MagickFalse;
4411              break;
4412            }
4413          q=p;
4414          if (index == 0)
4415            PrependImageToList(images,q);
4416          else
4417            if (index == (ssize_t) GetImageListLength(*images))
4418              AppendImageToList(images,q);
4419            else
4420              {
4421                 q=GetImageFromList(*images,index-1);
4422                 if (q == (Image *) NULL)
4423                   {
4424                     (void) ThrowMagickException(exception,GetMagickModule(),
4425                       OptionError,"NoSuchImage","`%s'",argv[1]);
4426                     status=MagickFalse;
4427                     break;
4428                   }
4429                InsertImageInList(&q,p);
4430              }
4431          *images=GetFirstImageInList(q);
4432          break;
4433        }
4434      if (LocaleCompare("interpolate",argv[0]+1) == 0)
4435        {
4436          interpolate_method=(PixelInterpolateMethod) ParseCommandOption(
4437            MagickInterpolateOptions,MagickFalse,argv[1]);
4438          break;
4439        }
4440      break;
4441    }
4442    case 'l':
4443    {
4444      if (LocaleCompare("layers",argv[0]+1) == 0)
4445        {
4446          Image
4447            *layers;
4448
4449          ImageLayerMethod
4450            method;
4451
4452          (void) SyncImagesSettings(image_info,*images);
4453          layers=(Image *) NULL;
4454          method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
4455            MagickFalse,argv[1]);
4456          switch (method)
4457          {
4458            case CoalesceLayer:
4459            {
4460              layers=CoalesceImages(*images,exception);
4461              break;
4462            }
4463            case CompareAnyLayer:
4464            case CompareClearLayer:
4465            case CompareOverlayLayer:
4466            default:
4467            {
4468              layers=CompareImagesLayers(*images,method,exception);
4469              break;
4470            }
4471            case MergeLayer:
4472            case FlattenLayer:
4473            case MosaicLayer:
4474            case TrimBoundsLayer:
4475            {
4476              layers=MergeImageLayers(*images,method,exception);
4477              break;
4478            }
4479            case DisposeLayer:
4480            {
4481              layers=DisposeImages(*images,exception);
4482              break;
4483            }
4484            case OptimizeImageLayer:
4485            {
4486              layers=OptimizeImageLayers(*images,exception);
4487              break;
4488            }
4489            case OptimizePlusLayer:
4490            {
4491              layers=OptimizePlusImageLayers(*images,exception);
4492              break;
4493            }
4494            case OptimizeTransLayer:
4495            {
4496              OptimizeImageTransparency(*images,exception);
4497              break;
4498            }
4499            case RemoveDupsLayer:
4500            {
4501              RemoveDuplicateLayers(images,exception);
4502              break;
4503            }
4504            case RemoveZeroLayer:
4505            {
4506              RemoveZeroDelayLayers(images,exception);
4507              break;
4508            }
4509            case OptimizeLayer:
4510            {
4511              /*
4512                General Purpose, GIF Animation Optimizer.
4513              */
4514              layers=CoalesceImages(*images,exception);
4515              if (layers == (Image *) NULL)
4516                {
4517                  status=MagickFalse;
4518                  break;
4519                }
4520              *images=DestroyImageList(*images);
4521              *images=layers;
4522              layers=OptimizeImageLayers(*images,exception);
4523              if (layers == (Image *) NULL)
4524                {
4525                  status=MagickFalse;
4526                  break;
4527                }
4528              *images=DestroyImageList(*images);
4529              *images=layers;
4530              layers=(Image *) NULL;
4531              OptimizeImageTransparency(*images,exception);
4532              (void) RemapImages(quantize_info,*images,(Image *) NULL,
4533                exception);
4534              break;
4535            }
4536            case CompositeLayer:
4537            {
4538              CompositeOperator
4539                compose;
4540
4541              Image
4542                *source;
4543
4544              RectangleInfo
4545                geometry;
4546
4547              /*
4548                Split image sequence at the first 'NULL:' image.
4549              */
4550              source=(*images);
4551              while (source != (Image *) NULL)
4552              {
4553                source=GetNextImageInList(source);
4554                if ((source != (Image *) NULL) &&
4555                    (LocaleCompare(source->magick,"NULL") == 0))
4556                  break;
4557              }
4558              if (source != (Image *) NULL)
4559                {
4560                  if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4561                      (GetNextImageInList(source) == (Image *) NULL))
4562                    source=(Image *) NULL;
4563                  else
4564                    {
4565                      /*
4566                        Separate the two lists, junk the null: image.
4567                      */
4568                      source=SplitImageList(source->previous);
4569                      DeleteImageFromList(&source);
4570                    }
4571                }
4572              if (source == (Image *) NULL)
4573                {
4574                  (void) ThrowMagickException(exception,GetMagickModule(),
4575                    OptionError,"MissingNullSeparator","layers Composite");
4576                  status=MagickFalse;
4577                  break;
4578                }
4579              /*
4580                Adjust offset with gravity and virtual canvas.
4581              */
4582              SetGeometry(*images,&geometry);
4583              (void) ParseAbsoluteGeometry((*images)->geometry,&geometry);
4584              geometry.width=source->page.width != 0 ?
4585                source->page.width : source->columns;
4586              geometry.height=source->page.height != 0 ?
4587               source->page.height : source->rows;
4588              GravityAdjustGeometry((*images)->page.width != 0 ?
4589                (*images)->page.width : (*images)->columns,
4590                (*images)->page.height != 0 ? (*images)->page.height :
4591                (*images)->rows,(*images)->gravity,&geometry);
4592              compose=OverCompositeOp;
4593              argv[0]=GetImageOption(image_info,"compose");
4594              if (argv[0] != (const char *) NULL)
4595                compose=(CompositeOperator) ParseCommandOption(
4596                  MagickComposeOptions,MagickFalse,argv[0]);
4597              CompositeLayers(*images,compose,source,geometry.x,geometry.y,
4598                exception);
4599              source=DestroyImageList(source);
4600              break;
4601            }
4602          }
4603          if (layers == (Image *) NULL)
4604            break;
4605          InheritException(exception,&layers->exception);
4606          *images=DestroyImageList(*images);
4607          *images=layers;
4608          break;
4609        }
4610      break;
4611    }
4612    case 'm':
4613    {
4614      if (LocaleCompare("map",argv[0]+1) == 0)
4615        {
4616          (void) SyncImagesSettings(image_info,*images);
4617          if (*argv[0] == '+')
4618            {
4619              (void) RemapImages(quantize_info,*images,(Image *) NULL,
4620                exception);
4621              break;
4622            }
4623          break;
4624        }
4625      if (LocaleCompare("maximum",argv[0]+1) == 0)
4626        {
4627          Image
4628            *maximum_image;
4629
4630          /*
4631            Maximum image sequence (deprecated).
4632          */
4633          (void) SyncImagesSettings(image_info,*images);
4634          maximum_image=EvaluateImages(*images,MaxEvaluateOperator,exception);
4635          if (maximum_image == (Image *) NULL)
4636            {
4637              status=MagickFalse;
4638              break;
4639            }
4640          *images=DestroyImageList(*images);
4641          *images=maximum_image;
4642          break;
4643        }
4644      if (LocaleCompare("minimum",argv[0]+1) == 0)
4645        {
4646          Image
4647            *minimum_image;
4648
4649          /*
4650            Minimum image sequence (deprecated).
4651          */
4652          (void) SyncImagesSettings(image_info,*images);
4653          minimum_image=EvaluateImages(*images,MinEvaluateOperator,exception);
4654          if (minimum_image == (Image *) NULL)
4655            {
4656              status=MagickFalse;
4657              break;
4658            }
4659          *images=DestroyImageList(*images);
4660          *images=minimum_image;
4661          break;
4662        }
4663      if (LocaleCompare("morph",argv[0]+1) == 0)
4664        {
4665          Image
4666            *morph_image;
4667
4668          (void) SyncImagesSettings(image_info,*images);
4669          morph_image=MorphImages(*images,StringToUnsignedLong(argv[1]),
4670            exception);
4671          if (morph_image == (Image *) NULL)
4672            {
4673              status=MagickFalse;
4674              break;
4675            }
4676          *images=DestroyImageList(*images);
4677          *images=morph_image;
4678          break;
4679        }
4680      if (LocaleCompare("mosaic",argv[0]+1) == 0)
4681        {
4682          Image
4683            *mosaic_image;
4684
4685          (void) SyncImagesSettings(image_info,*images);
4686          mosaic_image=MergeImageLayers(*images,MosaicLayer,exception);
4687          if (mosaic_image == (Image *) NULL)
4688            {
4689              status=MagickFalse;
4690              break;
4691            }
4692          *images=DestroyImageList(*images);
4693          *images=mosaic_image;
4694          break;
4695        }
4696      break;
4697    }
4698    case 'p':
4699    {
4700      if (LocaleCompare("print",argv[0]+1) == 0)
4701        {
4702          char
4703            *string;
4704
4705          (void) SyncImagesSettings(image_info,*images);
4706          string=InterpretImageProperties(image_info,*images,argv[1],
4707            exception);
4708          if (string == (char *) NULL)
4709            break;
4710          (void) FormatLocaleFile(stdout,"%s",string);
4711          string=DestroyString(string);
4712        }
4713      if (LocaleCompare("process",argv[0]+1) == 0)
4714        {
4715          char
4716            **arguments;
4717
4718          int
4719            j,
4720            number_arguments;
4721
4722          (void) SyncImagesSettings(image_info,*images);
4723          arguments=StringToArgv(argv[1],&number_arguments);
4724          if (arguments == (char **) NULL)
4725            break;
4726          if ((argc > 1) && (strchr(arguments[1],'=') != (char *) NULL))
4727            {
4728              char
4729                breaker,
4730                quote,
4731                *token;
4732
4733              const char
4734                *arguments;
4735
4736              int
4737                next,
4738                status;
4739
4740              size_t
4741                length;
4742
4743              TokenInfo
4744                *token_info;
4745
4746              /*
4747                Support old style syntax, filter="-option arg".
4748              */
4749              length=strlen(argv[1]);
4750              token=(char *) NULL;
4751              if (~length >= (MaxTextExtent-1))
4752                token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4753                  sizeof(*token));
4754              if (token == (char *) NULL)
4755                break;
4756              next=0;
4757              arguments=argv[1];
4758              token_info=AcquireTokenInfo();
4759              status=Tokenizer(token_info,0,token,length,arguments,"","=",
4760                "\"",'\0',&breaker,&next,&quote);
4761              token_info=DestroyTokenInfo(token_info);
4762              if (status == 0)
4763                {
4764                  const char
4765                    *argv;
4766
4767                  argv=(&(arguments[next]));
4768                  (void) InvokeDynamicImageFilter(token,&(*images),1,&argv,
4769                    exception);
4770                }
4771              token=DestroyString(token);
4772              break;
4773            }
4774          (void) SubstituteString(&arguments[1],"-","");
4775          (void) InvokeDynamicImageFilter(arguments[1],&(*images),
4776            number_arguments-2,(const char **) arguments+2,exception);
4777          for (j=0; j < number_arguments; j++)
4778            arguments[j]=DestroyString(arguments[j]);
4779          arguments=(char **) RelinquishMagickMemory(arguments);
4780          break;
4781        }
4782      break;
4783    }
4784    case 'r':
4785    {
4786      if (LocaleCompare("reverse",argv[0]+1) == 0)
4787        {
4788          ReverseImageList(images);
4789          InheritException(exception,&(*images)->exception);
4790          break;
4791        }
4792      break;
4793    }
4794    case 's':
4795    {
4796      if (LocaleCompare("smush",argv[0]+1) == 0)
4797        {
4798          Image
4799            *smush_image;
4800
4801          ssize_t
4802            offset;
4803
4804          (void) SyncImagesSettings(image_info,*images);
4805          offset=(ssize_t) StringToLong(argv[1]);
4806          smush_image=SmushImages(*images,*argv[0] == '-' ? MagickTrue :
4807            MagickFalse,offset,exception);
4808          if (smush_image == (Image *) NULL)
4809            {
4810              status=MagickFalse;
4811              break;
4812            }
4813          *images=DestroyImageList(*images);
4814          *images=smush_image;
4815          break;
4816        }
4817      if (LocaleCompare("swap",argv[0]+1) == 0)
4818        {
4819          Image
4820            *p,
4821            *q,
4822            *swap;
4823
4824          ssize_t
4825            swap_index;
4826
4827          index=(-1);
4828          swap_index=(-2);
4829          if (*argv[0] != '+')
4830            {
4831              GeometryInfo
4832                geometry_info;
4833
4834              MagickStatusType
4835                flags;
4836
4837              swap_index=(-1);
4838              flags=ParseGeometry(argv[1],&geometry_info);
4839              index=(ssize_t) geometry_info.rho;
4840              if ((flags & SigmaValue) != 0)
4841                swap_index=(ssize_t) geometry_info.sigma;
4842            }
4843          p=GetImageFromList(*images,index);
4844          q=GetImageFromList(*images,swap_index);
4845          if ((p == (Image *) NULL) || (q == (Image *) NULL))
4846            {
4847              (void) ThrowMagickException(exception,GetMagickModule(),
4848                OptionError,"NoSuchImage","`%s'",(*images)->filename);
4849              status=MagickFalse;
4850              break;
4851            }
4852          if (p == q)
4853            break;
4854          swap=CloneImage(p,0,0,MagickTrue,exception);
4855          ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4856          ReplaceImageInList(&q,swap);
4857          *images=GetFirstImageInList(q);
4858          break;
4859        }
4860      break;
4861    }
4862    case 'w':
4863    {
4864      if (LocaleCompare("write",argv[0]+1) == 0)
4865        {
4866          char
4867            key[MaxTextExtent];
4868
4869          Image
4870            *write_images;
4871
4872          ImageInfo
4873            *write_info;
4874
4875          (void) SyncImagesSettings(image_info,*images);
4876          (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",argv[1]);
4877          (void) DeleteImageRegistry(key);
4878          write_images=(*images);
4879          if (*argv[0] == '+')
4880            write_images=CloneImageList(*images,exception);
4881          write_info=CloneImageInfo(image_info);
4882          status&=WriteImages(write_info,write_images,argv[1],exception);
4883          write_info=DestroyImageInfo(write_info);
4884          if (*argv[0] == '+')
4885            write_images=DestroyImageList(write_images);
4886          break;
4887        }
4888      break;
4889    }
4890    default:
4891      break;
4892  }
4893  quantize_info=DestroyQuantizeInfo(quantize_info);
4894
4895  status=(MagickStatusType) ((*image)->exception.severity ==
4896    UndefinedException ? 1 : 0);
4897  return(status != 0 ? MagickTrue : MagickFalse);
4898}
4899#endif
4900