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