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