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