2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
13 % CLI Magick Option Methods %
20 % Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
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
44 % Anthony Thyssen, September 2011
50 #include "MagickWand/studio.h"
51 #include "MagickWand/MagickWand.h"
52 #include "MagickWand/magick-wand-private.h"
53 #include "MagickWand/mogrify.h"
54 #include "MagickWand/wand.h"
55 #include "MagickWand/wandcli.h"
56 #include "MagickWand/wandcli-private.h"
57 #include "MagickCore/image-private.h"
58 #include "MagickCore/monitor-private.h"
59 #include "MagickWand/operation.h"
60 #include "MagickCore/thread-private.h"
61 #include "MagickCore/string-private.h"
62 #include "MagickCore/pixel-private.h"
68 MogrifyBackgroundColor[] = "#fff", /* white */
69 MogrifyBorderColor[] = "#dfdfdf", /* sRGB gray */
70 MogrifyMatteColor[] = "#bdbdbd"; /* slightly darker gray */
75 #define USE_WAND_METHODS 1
76 #define MAX_STACK_DEPTH 32
77 #define UNDEFINED_COMPRESSION_QUALITY 0UL
79 /* FUTURE: why is this default so specific? */
80 #define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
82 /* For Debugging Geometry Input */
83 #define ReportGeometry(flags,info) \
84 (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
85 flags, info.rho, info.sigma, info.xi, info.psi )
88 ** Function to report on the progress of image operations
90 static MagickBooleanType MonitorProgress(const char *text,
91 const MagickOffsetType offset,const MagickSizeType extent,
92 void *wand_unused(cli_wandent_data))
95 message[MagickPathExtent],
96 tag[MagickPathExtent];
106 (void) CopyMagickMemory(tag,text,MagickPathExtent);
108 if (p != (char *) NULL)
110 (void) FormatLocaleString(message,MagickPathExtent,"Monitor/%s",tag);
111 locale_message=GetLocaleMessage(message);
112 if (locale_message == message)
114 if (p == (char *) NULL)
115 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
116 locale_message,(long) offset,(unsigned long) extent,(long)
117 (100L*offset/(extent-1)));
119 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
120 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
121 (100L*offset/(extent-1)));
122 if (offset == (MagickOffsetType) (extent-1))
123 (void) FormatLocaleFile(stderr,"\n");
124 (void) fflush(stderr);
129 ** GetImageCache() will read an image into a image cache if not already
130 ** present then return the image that is in the cache under that filename.
132 static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
133 ExceptionInfo *exception)
136 key[MagickPathExtent];
147 (void) FormatLocaleString(key,MagickPathExtent,"cache:%s",path);
148 sans_exception=AcquireExceptionInfo();
149 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
150 sans_exception=DestroyExceptionInfo(sans_exception);
151 if (image != (Image *) NULL)
153 read_info=CloneImageInfo(image_info);
154 if (path != (const char *) NULL)
155 (void) CopyMagickString(read_info->filename,path,MagickPathExtent);
156 image=ReadImage(read_info,exception);
157 read_info=DestroyImageInfo(read_info);
158 if (image != (Image *) NULL)
159 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
164 SparseColorOption() parse the complex -sparse-color argument into an
165 an array of floating point values than call SparseColorImage().
166 Argument is a complex mix of floating-point pixel coodinates, and color
167 specifications (or direct floating point numbers). The number of floats
168 needed to represent a color varies depending on the current channel
171 This really should be in MagickCore, so that other API's can make use of it.
173 static Image *SparseColorOption(const Image *image,
174 const SparseColorMethod method,const char *arguments,ExceptionInfo *exception)
177 token[MagickPathExtent];
201 assert(image != (Image *) NULL);
202 assert(image->signature == MagickCoreSignature);
203 if (IfMagickTrue(image->debug))
204 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
205 assert(exception != (ExceptionInfo *) NULL);
206 assert(exception->signature == MagickCoreSignature);
208 Limit channels according to image
209 add up number of values needed per color.
212 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
214 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
216 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
218 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
219 (image->colorspace == CMYKColorspace))
221 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
222 image->alpha_trait != UndefinedPixelTrait)
226 Read string, to determine number of arguments needed,
232 GetMagickToken(p,&p,token);
233 if ( token[0] == ',' ) continue;
234 if ( isalpha((int) token[0]) || token[0] == '#' )
235 x += number_colors; /* color argument found */
237 x++; /* floating point argument */
239 /* control points and color values */
240 if ((x % (2+number_colors)) != 0)
242 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
243 "InvalidArgument","'%s': %s", "sparse-color",
244 "Invalid number of Arguments");
245 return( (Image *) NULL);
250 /* Allocate and fill in the floating point arguments */
251 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
252 sizeof(*sparse_arguments));
253 if (sparse_arguments == (double *) NULL) {
254 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
255 "MemoryAllocationFailed","%s","SparseColorOption");
256 return( (Image *) NULL);
258 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
259 sizeof(*sparse_arguments));
262 while( *p != '\0' && x < number_arguments ) {
264 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
265 if ( token[0] == '\0' ) break;
266 if ( isalpha((int) token[0]) || token[0] == '#' ) {
267 (void) ThrowMagickException(exception,GetMagickModule(),
268 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
269 "Color found, instead of X-coord");
273 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
275 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
276 if ( token[0] == '\0' ) break;
277 if ( isalpha((int) token[0]) || token[0] == '#' ) {
278 (void) ThrowMagickException(exception,GetMagickModule(),
279 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
280 "Color found, instead of Y-coord");
284 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
285 /* color name or function given in string argument */
286 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
287 if ( token[0] == '\0' ) break;
288 if ( isalpha((int) token[0]) || token[0] == '#' ) {
289 /* Color string given */
290 (void) QueryColorCompliance(token,AllCompliance,&color,
292 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
293 sparse_arguments[x++] = QuantumScale*color.red;
294 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
295 sparse_arguments[x++] = QuantumScale*color.green;
296 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
297 sparse_arguments[x++] = QuantumScale*color.blue;
298 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
299 (image->colorspace == CMYKColorspace))
300 sparse_arguments[x++] = QuantumScale*color.black;
301 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
302 image->alpha_trait != UndefinedPixelTrait)
303 sparse_arguments[x++] = QuantumScale*color.alpha;
306 /* Colors given as a set of floating point values - experimental */
307 /* NB: token contains the first floating point value to use! */
308 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
310 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
311 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
313 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
314 token[0] = ','; /* used this token - get another */
316 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
318 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
319 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
321 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
322 token[0] = ','; /* used this token - get another */
324 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
326 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
327 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
329 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
330 token[0] = ','; /* used this token - get another */
332 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
333 (image->colorspace == CMYKColorspace))
335 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
336 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
338 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
339 token[0] = ','; /* used this token - get another */
341 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
342 image->alpha_trait != UndefinedPixelTrait)
344 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
345 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
347 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
348 token[0] = ','; /* used this token - get another */
352 if (error != MagickFalse)
354 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
355 return((Image *) NULL);
357 if (number_arguments != x)
359 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
360 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
361 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
362 return((Image *) NULL);
364 /* Call the Sparse Color Interpolation function with the parsed arguments */
365 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
367 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
368 return( sparse_image );
372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376 % C L I S e t t i n g O p t i o n I n f o %
380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
382 % CLISettingOptionInfo() applies a single settings option into a CLI wand
383 % holding the image_info, draw_info, quantize_info structures that will be
384 % used when processing the images.
386 % These options do no require images to be present in the CLI wand for them
387 % to be able to be set, in which case they will generally be applied to image
388 % that are read in later
390 % Options handled by this function are listed in CommandOptions[] of
391 % "option.c" that is one of "SettingOptionFlags" option flags.
393 % The format of the CLISettingOptionInfo method is:
395 % void CLISettingOptionInfo(MagickCLI *cli_wand,
396 % const char *option, const char *arg1, const char *arg2)
398 % A description of each parameter follows:
400 % o cli_wand: structure holding settings to be applied
402 % o option: The option string to be set
404 % o arg1, arg2: optional argument strings to the operation
405 % arg2 is currently only used by "-limit"
408 WandPrivate void CLISettingOptionInfo(MagickCLI *cli_wand,
409 const char *option,const char *arg1n, const char *arg2n)
412 parse; /* option argument parsing (string to value table lookup) */
414 const char /* percent escaped versions of the args */
418 #define _image_info (cli_wand->wand.image_info)
419 #define _image (cli_wand->wand.images)
420 #define _exception (cli_wand->wand.exception)
421 #define _draw_info (cli_wand->draw_info)
422 #define _quantize_info (cli_wand->quantize_info)
423 #define IfSetOption (*option=='-')
424 #define ArgBoolean IfSetOption ? MagickTrue : MagickFalse
425 #define ArgBooleanNot IfSetOption ? MagickFalse : MagickTrue
426 #define ArgBooleanString (IfSetOption?"true":"false")
427 #define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
429 assert(cli_wand != (MagickCLI *) NULL);
430 assert(cli_wand->signature == MagickWandSignature);
431 assert(cli_wand->wand.signature == MagickWandSignature);
433 if (IfMagickTrue(cli_wand->wand.debug))
434 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
435 "- Setting Option: %s \"%s\" \"%s\"", option,arg1n,arg2n);
441 #define _process_flags (cli_wand->process_flags)
442 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
443 /* Interpret Percent Escapes in Arguments - using first image */
444 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
445 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
446 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
447 /* Interpret Percent escapes in argument 1 */
448 if (arg1n != (char *) NULL) {
449 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
450 if (arg1 == (char *) NULL) {
451 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
452 arg1=arg1n; /* use the given argument as is */
455 if (arg2n != (char *) NULL) {
456 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
457 if (arg2 == (char *) NULL) {
458 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
459 arg2=arg2n; /* use the given argument as is */
463 #undef _process_flags
471 if (LocaleCompare("adjoin",option+1) == 0)
473 _image_info->adjoin = ArgBoolean;
476 if (LocaleCompare("affine",option+1) == 0)
478 CLIWandWarnReplaced("-draw 'affine ...'");
480 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
482 GetAffineMatrix(&_draw_info->affine);
485 if (LocaleCompare("antialias",option+1) == 0)
487 _image_info->antialias =
488 _draw_info->stroke_antialias =
489 _draw_info->text_antialias = ArgBoolean;
492 if (LocaleCompare("attenuate",option+1) == 0)
494 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
495 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
496 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
499 if (LocaleCompare("authenticate",option+1) == 0)
501 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
504 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
508 if (LocaleCompare("background",option+1) == 0)
510 /* FUTURE: both _image_info attribute & ImageOption in use!
511 _image_info only used directly for generating new images.
512 SyncImageSettings() used to set per-image attribute.
514 FUTURE: if _image_info->background_color is not set then
515 we should fall back to per-image background_color
517 At this time -background will 'wipe out' the per-image
520 Better error handling of QueryColorCompliance() needed.
522 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
523 (void) QueryColorCompliance(ArgOption(MogrifyBackgroundColor),AllCompliance,
524 &_image_info->background_color,_exception);
527 if (LocaleCompare("bias",option+1) == 0)
529 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
530 as it is actually rarely used except in direct convolve operations
531 Usage outside a direct convolve operation is actally non-sensible!
533 SyncImageSettings() used to set per-image attribute.
535 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
536 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
537 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
540 if (LocaleCompare("black-point-compensation",option+1) == 0)
542 /* Used as a image chromaticity setting
543 SyncImageSettings() used to set per-image attribute.
545 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
548 if (LocaleCompare("blue-primary",option+1) == 0)
550 /* Image chromaticity X,Y NB: Y=X if Y not defined
551 Used by many coders including PNG
552 SyncImageSettings() used to set per-image attribute.
554 arg1=ArgOption("0.0");
555 if (IfMagickFalse(IsGeometry(arg1)))
556 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
557 (void) SetImageOption(_image_info,option+1,arg1);
560 if (LocaleCompare("bordercolor",option+1) == 0)
562 /* FUTURE: both _image_info attribute & ImageOption in use!
563 SyncImageSettings() used to set per-image attribute.
564 Better error checking of QueryColorCompliance().
568 (void) SetImageOption(_image_info,option+1,arg1);
569 (void) QueryColorCompliance(arg1,AllCompliance,
570 &_image_info->border_color,_exception);
571 (void) QueryColorCompliance(arg1,AllCompliance,
572 &_draw_info->border_color,_exception);
575 (void) DeleteImageOption(_image_info,option+1);
576 (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
577 &_image_info->border_color,_exception);
578 (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
579 &_draw_info->border_color,_exception);
582 if (LocaleCompare("box",option+1) == 0)
584 CLIWandWarnReplaced("-undercolor");
585 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
588 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
592 if (LocaleCompare("cache",option+1) == 0)
597 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
598 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
599 limit=MagickResourceInfinity;
600 if (LocaleCompare("unlimited",arg1) != 0)
601 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
602 (void) SetMagickResourceLimit(MemoryResource,limit);
603 (void) SetMagickResourceLimit(MapResource,2*limit);
606 if (LocaleCompare("caption",option+1) == 0)
608 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
611 if (LocaleCompare("colorspace",option+1) == 0)
613 /* Setting used for new images via AquireImage()
614 But also used as a SimpleImageOperator
615 Undefined colorspace means don't modify images on
616 read or as a operation */
617 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,
618 ArgOption("undefined"));
620 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
622 _image_info->colorspace=(ColorspaceType) parse;
625 if (LocaleCompare("comment",option+1) == 0)
627 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
630 if (LocaleCompare("compose",option+1) == 0)
632 /* FUTURE: _image_info should be used,
633 SyncImageSettings() used to set per-image attribute. - REMOVE
635 This setting should NOT be used to set image 'compose'
636 "-layer" operators shoud use _image_info if defined otherwise
637 they should use a per-image compose setting.
639 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
640 ArgOption("undefined"));
642 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
644 _image_info->compose=(CompositeOperator) parse;
645 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
648 if (LocaleCompare("compress",option+1) == 0)
650 /* FUTURE: What should be used? _image_info or ImageOption ???
651 The former is more efficent, but Crisy prefers the latter!
652 SyncImageSettings() used to set per-image attribute.
654 The coders appears to use _image_info, not Image_Option
655 however the image attribute (for save) is set from the
658 Note that "undefined" is a different setting to "none".
660 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
661 ArgOption("undefined"));
663 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
665 _image_info->compression=(CompressionType) parse;
666 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
669 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
673 if (LocaleCompare("debug",option+1) == 0)
675 /* SyncImageSettings() used to set per-image attribute. */
676 arg1=ArgOption("none");
677 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
679 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
681 (void) SetLogEventMask(arg1);
682 _image_info->debug=IsEventLogging(); /* extract logging*/
683 cli_wand->wand.debug=IsEventLogging();
686 if (LocaleCompare("define",option+1) == 0)
688 if (LocaleNCompare(arg1,"registry:",9) == 0)
691 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
693 (void) DeleteImageRegistry(arg1+9);
696 /* DefineImageOption() equals SetImageOption() but with '=' */
698 (void) DefineImageOption(_image_info,arg1);
699 else if (DeleteImageOption(_image_info,arg1) == MagickFalse)
700 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
703 if (LocaleCompare("delay",option+1) == 0)
705 /* Only used for new images via AcquireImage()
706 FUTURE: Option should also be used for "-morph" (color morphing)
709 if (IfMagickFalse(IsGeometry(arg1)))
710 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
711 (void) SetImageOption(_image_info,option+1,arg1);
714 if (LocaleCompare("density",option+1) == 0)
716 /* FUTURE: strings used in _image_info attr and _draw_info!
717 Basically as density can be in a XxY form!
719 SyncImageSettings() used to set per-image attribute.
721 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
722 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
723 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
724 (void) CloneString(&_image_info->density,ArgOption(NULL));
725 (void) CloneString(&_draw_info->density,_image_info->density);
728 if (LocaleCompare("depth",option+1) == 0)
730 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
731 SyncImageSettings() used to set per-image attribute.
733 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
734 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
735 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
736 :MAGICKCORE_QUANTUM_DEPTH;
739 if (LocaleCompare("direction",option+1) == 0)
741 /* Image Option is only used to set _draw_info */
742 arg1=ArgOption("undefined");
743 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
745 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
747 _draw_info->direction=(DirectionType) parse;
748 (void) SetImageOption(_image_info,option+1,arg1);
751 if (LocaleCompare("display",option+1) == 0)
753 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
754 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
757 if (LocaleCompare("dispose",option+1) == 0)
759 /* only used in setting new images */
760 arg1=ArgOption("undefined");
761 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
763 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
765 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
768 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
770 /* FUTURE: this is only used by CompareImages() which is used
771 only by the "compare" CLI program at this time. */
772 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
773 if (IfMagickFalse(IsGeometry(arg1)))
774 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
775 (void) SetImageOption(_image_info,option+1,arg1);
778 if (LocaleCompare("dither",option+1) == 0)
780 /* _image_info attr (on/off), _quantize_info attr (on/off)
781 but also ImageInfo and _quantize_info method!
782 FUTURE: merge the duality of the dithering options
784 _image_info->dither = ArgBoolean;
785 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
786 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
787 MagickDitherOptions,MagickFalse,ArgOption("none"));
788 if (_quantize_info->dither_method == NoDitherMethod)
789 _image_info->dither = MagickFalse;
792 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
796 if (LocaleCompare("encoding",option+1) == 0)
798 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
799 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
802 if (LocaleCompare("endian",option+1) == 0)
804 /* Both _image_info attr and ImageInfo */
805 arg1 = ArgOption("undefined");
806 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
808 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
810 /* FUTURE: check alloc/free of endian string! - remove? */
811 _image_info->endian=(EndianType) (*arg1);
812 (void) SetImageOption(_image_info,option+1,arg1);
815 if (LocaleCompare("extract",option+1) == 0)
817 (void) CloneString(&_image_info->extract,ArgOption(NULL));
820 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
824 if (LocaleCompare("family",option+1) == 0)
826 (void) CloneString(&_draw_info->family,ArgOption(NULL));
829 if (LocaleCompare("features",option+1) == 0)
831 (void) SetImageOption(_image_info,"identify:features",
834 (void) SetImageArtifact(_image,"verbose","true");
837 if (LocaleCompare("fill",option+1) == 0)
839 /* Set "fill" OR "fill-pattern" in _draw_info
840 The original fill color is preserved if a fill-pattern is given.
841 That way it does not effect other operations that directly using
842 the fill color and, can be retored using "+tile".
853 arg1 = ArgOption("none"); /* +fill turns it off! */
854 (void) SetImageOption(_image_info,option+1,arg1);
855 if (_draw_info->fill_pattern != (Image *) NULL)
856 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
858 /* is it a color or a image? -- ignore exceptions */
859 sans=AcquireExceptionInfo();
860 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
861 sans=DestroyExceptionInfo(sans);
863 if (IfMagickFalse(status))
864 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
866 _draw_info->fill=color;
869 if (LocaleCompare("filter",option+1) == 0)
871 /* SyncImageSettings() used to set per-image attribute. */
872 arg1 = ArgOption("undefined");
873 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
875 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
877 (void) SetImageOption(_image_info,option+1,arg1);
880 if (LocaleCompare("font",option+1) == 0)
882 (void) CloneString(&_draw_info->font,ArgOption(NULL));
883 (void) CloneString(&_image_info->font,_draw_info->font);
886 if (LocaleCompare("format",option+1) == 0)
888 /* FUTURE: why the ping test, you could set ping after this! */
893 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
894 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
895 _image_info->ping=MagickFalse;
897 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
900 if (LocaleCompare("fuzz",option+1) == 0)
902 /* Option used to set image fuzz! unless blank canvas (from color)
903 Image attribute used for color compare operations
904 SyncImageSettings() used to set per-image attribute.
906 FUTURE: Can't find anything else using _image_info->fuzz directly!
907 convert structure attribute to 'option' string
910 if (IfMagickFalse(IsGeometry(arg1)))
911 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
912 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
914 (void) SetImageOption(_image_info,option+1,arg1);
917 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
921 if (LocaleCompare("gravity",option+1) == 0)
923 /* SyncImageSettings() used to set per-image attribute. */
924 arg1 = ArgOption("none");
925 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
927 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
929 _draw_info->gravity=(GravityType) parse;
930 (void) SetImageOption(_image_info,option+1,arg1);
933 if (LocaleCompare("green-primary",option+1) == 0)
935 /* Image chromaticity X,Y NB: Y=X if Y not defined
936 SyncImageSettings() used to set per-image attribute.
937 Used directly by many coders
939 arg1=ArgOption("0.0");
940 if (IfMagickFalse(IsGeometry(arg1)))
941 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
942 (void) SetImageOption(_image_info,option+1,arg1);
945 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
949 if (LocaleCompare("highlight-color",option+1) == 0)
951 /* FUTURE: this is only used by CompareImages() which is used
952 only by the "compare" CLI program at this time. */
953 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
956 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
960 if (LocaleCompare("intensity",option+1) == 0)
962 arg1 = ArgOption("undefined");
963 parse = ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,
966 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityType",
968 (void) SetImageOption(_image_info,option+1,arg1);
971 if (LocaleCompare("intent",option+1) == 0)
973 /* Only used by coders: MIFF, MPC, BMP, PNG
974 and for image profile call to AcquireTransformThreadSet()
975 SyncImageSettings() used to set per-image attribute.
977 arg1 = ArgOption("undefined");
978 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
980 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
982 (void) SetImageOption(_image_info,option+1,arg1);
985 if (LocaleCompare("interlace",option+1) == 0)
987 /* _image_info is directly used by coders (so why an image setting?)
988 SyncImageSettings() used to set per-image attribute.
990 arg1 = ArgOption("undefined");
991 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
993 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
995 _image_info->interlace=(InterlaceType) parse;
996 (void) SetImageOption(_image_info,option+1,arg1);
999 if (LocaleCompare("interline-spacing",option+1) == 0)
1001 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1002 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1003 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1004 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
1008 if (LocaleCompare("interpolate",option+1) == 0)
1010 /* SyncImageSettings() used to set per-image attribute. */
1011 arg1 = ArgOption("undefined");
1012 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1014 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1016 (void) SetImageOption(_image_info,option+1,arg1);
1019 if (LocaleCompare("interword-spacing",option+1) == 0)
1021 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1022 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1023 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1024 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
1027 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1031 if (LocaleCompare("kerning",option+1) == 0)
1033 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1034 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1035 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1036 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
1039 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1043 if (LocaleCompare("label",option+1) == 0)
1045 /* only used for new images - not in SyncImageOptions() */
1046 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1049 if (LocaleCompare("limit",option+1) == 0)
1054 limit=MagickResourceInfinity;
1055 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1057 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1059 if (LocaleCompare("unlimited",arg2) != 0)
1060 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1061 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1064 if (LocaleCompare("log",option+1) == 0)
1067 if ((strchr(arg1,'%') == (char *) NULL))
1068 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1069 (void) SetLogFormat(arg1);
1073 if (LocaleCompare("lowlight-color",option+1) == 0)
1075 /* FUTURE: this is only used by CompareImages() which is used
1076 only by the "compare" CLI program at this time. */
1077 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1080 if (LocaleCompare("loop",option+1) == 0)
1082 /* SyncImageSettings() used to set per-image attribute. */
1083 arg1=ArgOption("0");
1084 if (IfMagickFalse(IsGeometry(arg1)))
1085 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1086 (void) SetImageOption(_image_info,option+1,arg1);
1089 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1093 if (LocaleCompare("mattecolor",option+1) == 0)
1095 /* SyncImageSettings() used to set per-image attribute. */
1096 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1097 (void) QueryColorCompliance(ArgOption(MogrifyMatteColor),AllCompliance,
1098 &_image_info->matte_color,_exception);
1101 if (LocaleCompare("metric",option+1) == 0)
1103 /* FUTURE: this is only used by CompareImages() which is used
1104 only by the "compare" CLI program at this time. */
1105 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1107 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1109 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1112 if (LocaleCompare("moments",option+1) == 0)
1114 (void) SetImageOption(_image_info,"identify:moments",
1117 (void) SetImageArtifact(_image,"verbose","true");
1120 if (LocaleCompare("monitor",option+1) == 0)
1122 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
1123 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
1126 if (LocaleCompare("monochrome",option+1) == 0)
1128 /* Setting (used by some input coders!) -- why?
1129 Warning: This is also Special '-type' SimpleOperator
1131 _image_info->monochrome= ArgBoolean;
1134 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1138 if (LocaleCompare("orient",option+1) == 0)
1140 /* Is not used when defining for new images.
1141 This makes it more of a 'operation' than a setting
1142 FUTURE: make set meta-data operator instead.
1143 SyncImageSettings() used to set per-image attribute.
1145 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1146 ArgOption("undefined"));
1148 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1150 _image_info->orientation=(OrientationType)parse;
1151 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1154 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1158 if (LocaleCompare("page",option+1) == 0)
1160 /* Only used for new images and image generators.
1161 SyncImageSettings() used to set per-image attribute. ?????
1162 That last is WRONG!!!!
1163 FUTURE: adjust named 'page' sizes according density
1167 page[MagickPathExtent];
1180 (void) DeleteImageOption(_image_info,option+1);
1181 (void) CloneString(&_image_info->page,(char *) NULL);
1184 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1185 image_option=GetImageOption(_image_info,"page");
1186 if (image_option != (const char *) NULL)
1187 flags=ParseAbsoluteGeometry(image_option,&geometry);
1188 canonical_page=GetPageGeometry(arg1);
1189 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1190 canonical_page=DestroyString(canonical_page);
1191 (void) FormatLocaleString(page,MagickPathExtent,"%lux%lu",
1192 (unsigned long) geometry.width,(unsigned long) geometry.height);
1193 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1194 (void) FormatLocaleString(page,MagickPathExtent,"%lux%lu%+ld%+ld",
1195 (unsigned long) geometry.width,(unsigned long) geometry.height,
1196 (long) geometry.x,(long) geometry.y);
1197 (void) SetImageOption(_image_info,option+1,page);
1198 (void) CloneString(&_image_info->page,page);
1201 if (LocaleCompare("ping",option+1) == 0)
1203 _image_info->ping = ArgBoolean;
1206 if (LocaleCompare("pointsize",option+1) == 0)
1209 if (IfMagickFalse(IsGeometry(arg1)))
1210 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1211 _image_info->pointsize =
1212 _draw_info->pointsize =
1213 StringToDouble(arg1,(char **) NULL);
1216 _image_info->pointsize=0.0; /* unset pointsize */
1217 _draw_info->pointsize=12.0;
1221 if (LocaleCompare("precision",option+1) == 0)
1223 arg1=ArgOption("-1");
1224 if (IfMagickFalse(IsGeometry(arg1)))
1225 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1226 (void) SetMagickPrecision(StringToInteger(arg1));
1229 /* FUTURE: Only the 'preview' coder appears to use this
1230 * DEPRECIATE the coder? Leaving only the 'preview' operator.
1231 if (LocaleCompare("preview",option+1) == 0)
1233 _image_info->preview_type=UndefinedPreview;
1235 _image_info->preview_type=(PreviewType) ParseCommandOption(
1236 MagickPreviewOptions,MagickFalse,arg1);
1240 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1244 if (LocaleCompare("quality",option+1) == 0)
1246 if (IfMagickFalse(IsGeometry(arg1)))
1247 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1248 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1249 : UNDEFINED_COMPRESSION_QUALITY;
1250 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1253 if (LocaleCompare("quantize",option+1) == 0)
1255 /* Just a set direct in _quantize_info */
1256 arg1=ArgOption("undefined");
1257 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1259 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1261 _quantize_info->colorspace=(ColorspaceType)parse;
1264 if (LocaleCompare("quiet",option+1) == 0)
1266 /* FUTURE: if two -quiet is performed you can not do +quiet!
1267 This needs to be checked over thoughly.
1269 static WarningHandler
1270 warning_handler = (WarningHandler) NULL;
1273 tmp = SetWarningHandler((WarningHandler) NULL);
1275 if ( tmp != (WarningHandler) NULL)
1276 warning_handler = tmp; /* remember the old handler */
1277 if (!IfSetOption) /* set the old handler */
1278 warning_handler=SetWarningHandler(warning_handler);
1281 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1285 if (LocaleCompare("red-primary",option+1) == 0)
1287 /* Image chromaticity X,Y NB: Y=X if Y not defined
1289 SyncImageSettings() used to set per-image attribute.
1291 arg1=ArgOption("0.0");
1292 if (IfMagickFalse(IsGeometry(arg1)))
1293 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1294 (void) SetImageOption(_image_info,option+1,arg1);
1297 if (LocaleCompare("regard-warnings",option+1) == 0)
1298 /* FUTURE: to be replaced by a 'fatal-level' type setting */
1300 if (LocaleCompare("render",option+1) == 0)
1302 /* _draw_info only setting */
1303 _draw_info->render= ArgBooleanNot;
1306 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1308 /* link image and setting stacks - option is itself saved on stack! */
1309 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1312 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1316 if (LocaleCompare("sampling-factor",option+1) == 0)
1318 /* FUTURE: should be converted to jpeg:sampling_factor */
1319 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1320 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1321 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
1324 if (LocaleCompare("scene",option+1) == 0)
1326 /* SyncImageSettings() used to set this as a per-image attribute.
1329 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1330 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1331 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1332 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
1335 if (LocaleCompare("seed",option+1) == 0)
1337 if (IfMagickFalse(IsGeometry(arg1)))
1338 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1340 IfSetOption ? (unsigned long) StringToUnsignedLong(arg1)
1341 : (unsigned long) time((time_t *) NULL) );
1344 if (LocaleCompare("size",option+1) == 0)
1346 /* FUTURE: string in _image_info -- convert to Option ???
1347 Look at the special handling for "size" in SetImageOption()
1349 (void) CloneString(&_image_info->size,ArgOption(NULL));
1352 if (LocaleCompare("stretch",option+1) == 0)
1354 arg1=ArgOption("undefined");
1355 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1357 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1359 _draw_info->stretch=(StretchType) parse;
1362 if (LocaleCompare("stroke",option+1) == 0)
1364 /* set stroke color OR stroke-pattern
1365 UPDATE: ensure stroke color is not destroyed is a pattern
1366 is given. Just in case the color is also used for other purposes.
1377 arg1 = ArgOption("none"); /* +fill turns it off! */
1378 (void) SetImageOption(_image_info,option+1,arg1);
1379 if (_draw_info->stroke_pattern != (Image *) NULL)
1380 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
1382 /* is it a color or a image? -- ignore exceptions */
1383 sans=AcquireExceptionInfo();
1384 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
1385 sans=DestroyExceptionInfo(sans);
1387 if (IfMagickFalse(status))
1388 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
1390 _draw_info->stroke=color;
1393 if (LocaleCompare("strokewidth",option+1) == 0)
1395 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1396 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1397 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1398 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1402 if (LocaleCompare("style",option+1) == 0)
1404 arg1=ArgOption("undefined");
1405 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1407 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1409 _draw_info->style=(StyleType) parse;
1413 if (LocaleCompare("subimage-search",option+1) == 0)
1415 /* FUTURE: this is only used by CompareImages() which is used
1416 only by the "compare" CLI program at this time. */
1417 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1421 if (LocaleCompare("synchronize",option+1) == 0)
1423 /* FUTURE: syncronize to storage - but what does that mean? */
1424 _image_info->synchronize = ArgBoolean;
1427 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1431 if (LocaleCompare("taint",option+1) == 0)
1433 /* SyncImageSettings() used to set per-image attribute. */
1434 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1437 if (LocaleCompare("texture",option+1) == 0)
1439 /* Note: arguments do not have percent escapes expanded */
1440 /* FUTURE: move _image_info string to option splay-tree
1441 Other than "montage" what uses "texture" ????
1443 (void) CloneString(&_image_info->texture,ArgOption(NULL));
1446 if (LocaleCompare("tile",option+1) == 0)
1448 /* Note: arguments do not have percent escapes expanded */
1449 _draw_info->fill_pattern=IfSetOption
1450 ?GetImageCache(_image_info,arg1,_exception)
1451 :DestroyImage(_draw_info->fill_pattern);
1454 if (LocaleCompare("tile-offset",option+1) == 0)
1456 /* SyncImageSettings() used to set per-image attribute. ??? */
1457 arg1=ArgOption("0");
1458 if (IfMagickFalse(IsGeometry(arg1)))
1459 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1460 (void) SetImageOption(_image_info,option+1,arg1);
1463 if (LocaleCompare("transparent-color",option+1) == 0)
1465 /* FUTURE: both _image_info attribute & ImageOption in use!
1466 _image_info only used for generating new images.
1467 SyncImageSettings() used to set per-image attribute.
1469 Note that +transparent-color, means fall-back to image
1470 attribute so ImageOption is deleted, not set to a default.
1472 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1473 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1474 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1475 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1476 &_image_info->transparent_color,_exception);
1479 if (LocaleCompare("treedepth",option+1) == 0)
1481 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1482 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1485 if (LocaleCompare("type",option+1) == 0)
1487 /* SyncImageSettings() used to set per-image attribute. */
1488 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1489 ArgOption("undefined"));
1491 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1493 _image_info->type=(ImageType) parse;
1494 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1497 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1501 if (LocaleCompare("undercolor",option+1) == 0)
1503 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1504 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1505 &_draw_info->undercolor,_exception);
1508 if (LocaleCompare("units",option+1) == 0)
1510 /* SyncImageSettings() used to set per-image attribute.
1511 Should this effect _draw_info X and Y resolution?
1512 FUTURE: this probably should be part of the density setting
1514 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1515 ArgOption("undefined"));
1517 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1519 _image_info->units=(ResolutionType) parse;
1520 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1523 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1527 if (LocaleCompare("verbose",option+1) == 0)
1529 /* FUTURE: Remember all options become image artifacts
1530 _image_info->verbose is only used by coders.
1532 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1533 _image_info->verbose= ArgBoolean;
1534 _image_info->ping=MagickFalse; /* verbose can't be a ping */
1537 if (LocaleCompare("view",option+1) == 0)
1539 /* FUTURE: Convert from _image_info to ImageOption
1540 Only used by coder FPX
1541 And it only tests existance, not its content!
1543 (void) CloneString(&_image_info->view,ArgOption(NULL));
1546 if (LocaleCompare("virtual-pixel",option+1) == 0)
1548 /* SyncImageSettings() used to set per-image attribute.
1549 This is VERY deep in the image caching structure.
1551 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1552 ArgOption("undefined"));
1554 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1556 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1559 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1563 if (LocaleCompare("weight",option+1) == 0)
1568 weight=ParseCommandOption(MagickWeightOptions,MagickFalse,arg1);
1570 weight=StringToUnsignedLong(arg1);
1571 _draw_info->weight=(size_t) weight;
1574 if (LocaleCompare("white-point",option+1) == 0)
1576 /* Used as a image chromaticity setting
1577 SyncImageSettings() used to set per-image attribute.
1579 arg1=ArgOption("0.0");
1580 if (IfMagickFalse(IsGeometry(arg1)))
1581 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1582 (void) SetImageOption(_image_info,option+1,arg1);
1585 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1588 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1591 /* clean up percent escape interpreted strings */
1592 if ((arg1 && arg1n) && (arg1 != arg1n ))
1593 arg1=DestroyString((char *) arg1);
1594 if ((arg2 && arg2n) && (arg2 != arg2n ))
1595 arg2=DestroyString((char *) arg2);
1600 #undef _quantize_info
1603 #undef ArgBooleanNot
1604 #undef ArgBooleanString
1611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1615 + C L I S i m p l e O p e r a t o r I m a g e s %
1619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1621 % CLISimpleOperatorImages() applys one simple image operation given to all
1622 % the images in the CLI wand, using any per-image or global settings that was
1623 % previously saved in the CLI wand.
1625 % It is assumed that any such settings are up-to-date.
1627 % The format of the WandSimpleOperatorImages method is:
1629 % MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,const char *option,
1630 % const char *arg1, const char *arg2,ExceptionInfo *exception)
1632 % A description of each parameter follows:
1634 % o cli_wand: structure holding settings and images to be operated on
1636 % o option: The option string for the operation
1638 % o arg1, arg2: optional argument strings to the operation
1643 CLISimpleOperatorImage() is an Internal subrountine to apply one simple
1644 image operation to the current image pointed to by the CLI wand.
1646 The image in the list may be modified in three different ways...
1647 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1648 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1649 * one image replace by a list of images (-separate and -crop only!)
1651 In each case the result replaces the single original image in the list, as
1652 well as the pointer to the modified image (last image added if replaced by a
1653 list of images) is returned.
1655 As the image pointed to may be replaced, the first image in the list may
1656 also change. GetFirstImageInList() should be used by caller if they wish
1657 return the Image pointer to the first image in list.
1659 static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
1660 const char *option, const char *arg1n, const char *arg2n,
1661 ExceptionInfo *exception)
1678 const char /* percent escaped versions of the args */
1682 #define _image_info (cli_wand->wand.image_info)
1683 #define _image (cli_wand->wand.images)
1684 #define _exception (cli_wand->wand.exception)
1685 #define _draw_info (cli_wand->draw_info)
1686 #define _quantize_info (cli_wand->quantize_info)
1687 #define _process_flags (cli_wand->process_flags)
1688 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
1689 #define IfNormalOp (*option=='-')
1690 #define IfPlusOp (*option!='-')
1691 #define IsNormalOp IfNormalOp ? MagickTrue : MagickFalse
1692 #define IsPlusOp IfNormalOp ? MagickFalse : MagickTrue
1694 assert(cli_wand != (MagickCLI *) NULL);
1695 assert(cli_wand->signature == MagickWandSignature);
1696 assert(cli_wand->wand.signature == MagickWandSignature);
1697 assert(_image != (Image *) NULL); /* an image must be present */
1698 if (IfMagickTrue(cli_wand->wand.debug))
1699 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
1704 /* Interpret Percent Escapes in Arguments - using first image */
1705 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1706 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1707 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1708 /* Interpret Percent escapes in argument 1 */
1709 if (arg1n != (char *) NULL) {
1710 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1711 if (arg1 == (char *) NULL) {
1712 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1713 arg1=arg1n; /* use the given argument as is */
1716 if (arg2n != (char *) NULL) {
1717 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1718 if (arg2 == (char *) NULL) {
1719 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1720 arg2=arg2n; /* use the given argument as is */
1724 #undef _process_flags
1728 (void) FormatLocaleFile(stderr,
1729 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1732 new_image = (Image *) NULL; /* the replacement image, if not null at end */
1733 SetGeometryInfo(&geometry_info);
1735 switch (*(option+1))
1739 if (LocaleCompare("adaptive-blur",option+1) == 0)
1741 flags=ParseGeometry(arg1,&geometry_info);
1742 if ((flags & (RhoValue|SigmaValue)) == 0)
1743 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1744 if ((flags & SigmaValue) == 0)
1745 geometry_info.sigma=1.0;
1746 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1747 geometry_info.sigma,_exception);
1750 if (LocaleCompare("adaptive-resize",option+1) == 0)
1752 /* FUTURE: Roll into a resize special operator */
1753 if (IfMagickFalse(IsGeometry(arg1)))
1754 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1755 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1756 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1760 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
1762 flags=ParseGeometry(arg1,&geometry_info);
1763 if ((flags & (RhoValue|SigmaValue)) == 0)
1764 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1765 if ((flags & SigmaValue) == 0)
1766 geometry_info.sigma=1.0;
1767 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1768 geometry_info.sigma,_exception);
1771 if (LocaleCompare("alpha",option+1) == 0)
1773 parse=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,arg1);
1775 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelOption",
1777 (void) SetImageAlphaChannel(_image,(AlphaChannelOption) parse,
1781 if (LocaleCompare("annotate",option+1) == 0)
1784 geometry[MagickPathExtent];
1786 SetGeometryInfo(&geometry_info);
1787 flags=ParseGeometry(arg1,&geometry_info);
1789 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1790 if ((flags & SigmaValue) == 0)
1791 geometry_info.sigma=geometry_info.rho;
1792 (void) CloneString(&_draw_info->text,arg2);
1793 (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
1794 geometry_info.xi,geometry_info.psi);
1795 (void) CloneString(&_draw_info->geometry,geometry);
1796 _draw_info->affine.sx=cos(DegreesToRadians(
1797 fmod(geometry_info.rho,360.0)));
1798 _draw_info->affine.rx=sin(DegreesToRadians(
1799 fmod(geometry_info.rho,360.0)));
1800 _draw_info->affine.ry=(-sin(DegreesToRadians(
1801 fmod(geometry_info.sigma,360.0))));
1802 _draw_info->affine.sy=cos(DegreesToRadians(
1803 fmod(geometry_info.sigma,360.0)));
1804 (void) AnnotateImage(_image,_draw_info,_exception);
1805 GetAffineMatrix(&_draw_info->affine);
1808 if (LocaleCompare("auto-gamma",option+1) == 0)
1810 (void) AutoGammaImage(_image,_exception);
1813 if (LocaleCompare("auto-level",option+1) == 0)
1815 (void) AutoLevelImage(_image,_exception);
1818 if (LocaleCompare("auto-orient",option+1) == 0)
1820 new_image=AutoOrientImage(_image,_image->orientation,_exception);
1823 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1827 if (LocaleCompare("black-threshold",option+1) == 0)
1829 if (IfMagickFalse(IsGeometry(arg1)))
1830 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1831 (void) BlackThresholdImage(_image,arg1,_exception);
1834 if (LocaleCompare("blue-shift",option+1) == 0)
1836 geometry_info.rho=1.5;
1838 flags=ParseGeometry(arg1,&geometry_info);
1839 if ((flags & RhoValue) == 0)
1840 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1842 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
1845 if (LocaleCompare("blur",option+1) == 0)
1847 flags=ParseGeometry(arg1,&geometry_info);
1848 if ((flags & (RhoValue|SigmaValue)) == 0)
1849 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1850 if ((flags & SigmaValue) == 0)
1851 geometry_info.sigma=1.0;
1852 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1856 if (LocaleCompare("border",option+1) == 0)
1864 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
1865 if ((flags & (WidthValue | HeightValue)) == 0)
1866 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1867 compose=OverCompositeOp;
1868 value=GetImageOption(_image_info,"compose");
1869 if (value != (const char *) NULL)
1870 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
1872 new_image=BorderImage(_image,&geometry,compose,_exception);
1875 if (LocaleCompare("brightness-contrast",option+1) == 0)
1887 flags=ParseGeometry(arg1,&geometry_info);
1888 if ((flags & RhoValue) == 0)
1889 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1890 brightness=geometry_info.rho;
1892 if ((flags & SigmaValue) != 0)
1893 contrast=geometry_info.sigma;
1894 (void) BrightnessContrastImage(_image,brightness,contrast,
1898 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1902 if (LocaleCompare("canny",option+1) == 0)
1904 flags=ParseGeometry(arg1,&geometry_info);
1905 if ((flags & (RhoValue|SigmaValue)) == 0)
1906 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1907 if ((flags & SigmaValue) == 0)
1908 geometry_info.sigma=1.0;
1909 if ((flags & XiValue) == 0)
1910 geometry_info.xi=10;
1911 if ((flags & PsiValue) == 0)
1912 geometry_info.psi=30;
1913 if ((flags & PercentValue) != 0)
1915 geometry_info.xi/=100.0;
1916 geometry_info.psi/=100.0;
1918 new_image=CannyEdgeImage(_image,geometry_info.rho,geometry_info.sigma,
1919 geometry_info.xi,geometry_info.psi,_exception);
1922 if (LocaleCompare("cdl",option+1) == 0)
1924 /* Note: arguments do not have percent escapes expanded */
1926 *color_correction_collection;
1929 Color correct with a color decision list.
1931 color_correction_collection=FileToString(arg1,~0UL,_exception);
1932 if (color_correction_collection == (char *) NULL)
1934 (void) ColorDecisionListImage(_image,color_correction_collection,
1938 if (LocaleCompare("channel",option+1) == 0)
1942 (void) SetPixelChannelMask(_image,DefaultChannels);
1945 parse=ParseChannelOption(arg1);
1947 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
1949 (void) SetPixelChannelMask(_image,(ChannelType) parse);
1952 if (LocaleCompare("charcoal",option+1) == 0)
1954 flags=ParseGeometry(arg1,&geometry_info);
1955 if ((flags & (RhoValue|SigmaValue)) == 0)
1956 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1957 if ((flags & SigmaValue) == 0)
1958 geometry_info.sigma=1.0;
1959 if ((flags & XiValue) == 0)
1960 geometry_info.xi=1.0;
1961 new_image=CharcoalImage(_image,geometry_info.rho,geometry_info.sigma,
1965 if (LocaleCompare("chop",option+1) == 0)
1967 if (IfMagickFalse(IsGeometry(arg1)))
1968 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1969 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1970 new_image=ChopImage(_image,&geometry,_exception);
1973 if (LocaleCompare("clamp",option+1) == 0)
1975 (void) ClampImage(_image,_exception);
1978 if (LocaleCompare("clip",option+1) == 0)
1981 (void) ClipImage(_image,_exception);
1982 else /* "+mask" remove the write mask */
1983 (void) SetImageMask(_image,ReadPixelMask,(Image *) NULL,_exception);
1986 if (LocaleCompare("clip-mask",option+1) == 0)
1988 /* Note: arguments do not have percent escapes expanded */
2005 /* use "+clip-mask" Remove the write mask for -clip-path */
2006 (void) SetImageMask(_image,ReadPixelMask,(Image *) NULL,_exception);
2009 mask_image=GetImageCache(_image_info,arg1,_exception);
2010 if (mask_image == (Image *) NULL)
2012 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
2014 /* Create a write mask from cli_wand mask image */
2015 /* FUTURE: use Alpha operations instead and create a Grey Image */
2016 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
2017 for (y=0; y < (ssize_t) mask_image->rows; y++)
2019 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
2021 if (q == (Quantum *) NULL)
2023 for (x=0; x < (ssize_t) mask_image->columns; x++)
2025 if (mask_image->alpha_trait == UndefinedPixelTrait)
2026 SetPixelAlpha(mask_image,(Quantum)
2027 GetPixelIntensity(mask_image,q),q);
2028 SetPixelGray(mask_image,GetPixelAlpha(mask_image,q),q);
2029 q+=GetPixelChannels(mask_image);
2031 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
2034 /* clean up and set the write mask */
2035 mask_view=DestroyCacheView(mask_view);
2036 mask_image->alpha_trait=BlendPixelTrait;
2037 (void) SetImageColorspace(_image,GRAYColorspace,_exception);
2038 (void) SetImageMask(_image,ReadPixelMask,mask_image,_exception);
2039 mask_image=DestroyImage(mask_image);
2042 if (LocaleCompare("clip-path",option+1) == 0)
2044 (void) ClipImagePath(_image,arg1,IsNormalOp,_exception);
2045 /* Note: Use "+clip-mask" remove the write mask added */
2048 if (LocaleCompare("colorize",option+1) == 0)
2050 if (IfMagickFalse(IsGeometry(arg1)))
2051 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2052 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
2055 if (LocaleCompare("color-matrix",option+1) == 0)
2060 kernel=AcquireKernelInfo(arg1,exception);
2061 if (kernel == (KernelInfo *) NULL)
2062 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2063 new_image=ColorMatrixImage(_image,kernel,_exception);
2064 kernel=DestroyKernelInfo(kernel);
2067 if (LocaleCompare("colors",option+1) == 0)
2069 /* Reduce the number of colors in the image.
2070 FUTURE: also provide 'plus version with image 'color counts'
2072 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2073 if (_quantize_info->number_colors == 0)
2074 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2075 if ((_image->storage_class == DirectClass) ||
2076 _image->colors > _quantize_info->number_colors)
2077 (void) QuantizeImage(_quantize_info,_image,_exception);
2079 (void) CompressImageColormap(_image,_exception);
2082 if (LocaleCompare("colorspace",option+1) == 0)
2084 /* WARNING: this is both a image_info setting (already done)
2085 and a operator to change image colorspace.
2087 FUTURE: default colorspace should be sRGB!
2088 Unless some type of 'linear colorspace' mode is set.
2090 Note that +colorspace sets "undefined" or no effect on
2091 new images, but forces images already in memory back to RGB!
2092 That seems to be a little strange!
2094 (void) TransformImageColorspace(_image,
2095 IfNormalOp ? _image_info->colorspace : sRGBColorspace,
2099 if (LocaleCompare("connected-components",option+1) == 0)
2101 if (IfMagickFalse(IsGeometry(arg1)))
2102 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2103 new_image=ConnectedComponentsImage(_image,(size_t)
2104 StringToInteger(arg1),_exception);
2107 if (LocaleCompare("contrast",option+1) == 0)
2109 CLIWandWarnReplaced(IfNormalOp?"-level":"+level");
2110 (void) ContrastImage(_image,IsNormalOp,_exception);
2113 if (LocaleCompare("contrast-stretch",option+1) == 0)
2122 flags=ParseGeometry(arg1,&geometry_info);
2123 if ((flags & RhoValue) == 0)
2124 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2125 black_point=geometry_info.rho;
2126 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2128 if ((flags & PercentValue) != 0) {
2129 black_point*=(double) _image->columns*_image->rows/100.0;
2130 white_point*=(double) _image->columns*_image->rows/100.0;
2132 white_point=(double) _image->columns*_image->rows-white_point;
2133 (void) ContrastStretchImage(_image,black_point,white_point,
2137 if (LocaleCompare("convolve",option+1) == 0)
2148 kernel_info=AcquireKernelInfo(arg1,exception);
2149 if (kernel_info == (KernelInfo *) NULL)
2150 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2152 for (j=0; j < (ssize_t) (kernel_info->width*kernel_info->height); j++)
2153 gamma+=kernel_info->values[j];
2154 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
2155 for (j=0; j < (ssize_t) (kernel_info->width*kernel_info->height); j++)
2156 kernel_info->values[j]*=gamma;
2157 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2159 kernel_info=DestroyKernelInfo(kernel_info);
2162 if (LocaleCompare("crop",option+1) == 0)
2164 /* WARNING: This can generate multiple images! */
2165 if (IfMagickFalse(IsGeometry(arg1)))
2166 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2167 new_image=CropImageToTiles(_image,arg1,_exception);
2170 if (LocaleCompare("cycle",option+1) == 0)
2172 if (IfMagickFalse(IsGeometry(arg1)))
2173 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2174 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2178 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2182 if (LocaleCompare("decipher",option+1) == 0)
2184 /* Note: arguments do not have percent escapes expanded */
2188 passkey=FileToStringInfo(arg1,~0UL,_exception);
2189 if (passkey == (StringInfo *) NULL)
2190 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2192 (void) PasskeyDecipherImage(_image,passkey,_exception);
2193 passkey=DestroyStringInfo(passkey);
2196 if (LocaleCompare("depth",option+1) == 0)
2198 /* The _image_info->depth setting has already been set
2199 We just need to apply it to all images in current sequence
2201 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2202 That is it really is an operation, not a setting! Arrgghhh
2204 FUTURE: this should not be an operator!!!
2206 (void) SetImageDepth(_image,_image_info->depth,_exception);
2209 if (LocaleCompare("deskew",option+1) == 0)
2215 if (IfMagickFalse(IsGeometry(arg1)))
2216 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2217 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
2220 threshold=40.0*QuantumRange/100.0;
2221 new_image=DeskewImage(_image,threshold,_exception);
2224 if (LocaleCompare("despeckle",option+1) == 0)
2226 new_image=DespeckleImage(_image,_exception);
2229 if (LocaleCompare("distort",option+1) == 0)
2237 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2239 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2241 if ((DistortImageMethod) parse == ResizeDistortion)
2245 /* Special Case - Argument is actually a resize geometry!
2246 ** Convert that to an appropriate distortion argument array.
2247 ** FUTURE: make a separate special resize operator
2248 Roll into a resize special operator */
2249 if (IfMagickFalse(IsGeometry(arg2)))
2250 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2252 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
2253 resize_args[0]=(double) geometry.width;
2254 resize_args[1]=(double) geometry.height;
2255 new_image=DistortImage(_image,(DistortImageMethod) parse,
2256 (size_t)2,resize_args,MagickTrue,_exception);
2259 /* convert argument string into an array of doubles */
2260 args = StringToArrayOfDoubles(arg2,&count,_exception);
2261 if (args == (double *) NULL )
2262 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2264 new_image=DistortImage(_image,(DistortImageMethod) parse,(size_t)
2265 count,args,IsPlusOp,_exception);
2266 args=(double *) RelinquishMagickMemory(args);
2269 if (LocaleCompare("draw",option+1) == 0)
2271 (void) CloneString(&_draw_info->primitive,arg1);
2272 (void) DrawImage(_image,_draw_info,_exception);
2273 (void) CloneString(&_draw_info->primitive,(char *) NULL);
2276 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2280 if (LocaleCompare("edge",option+1) == 0)
2282 flags=ParseGeometry(arg1,&geometry_info);
2283 if ((flags & (RhoValue|SigmaValue)) == 0)
2284 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2285 new_image=EdgeImage(_image,geometry_info.rho,_exception);
2288 if (LocaleCompare("emboss",option+1) == 0)
2290 flags=ParseGeometry(arg1,&geometry_info);
2291 if ((flags & (RhoValue|SigmaValue)) == 0)
2292 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2293 if ((flags & SigmaValue) == 0)
2294 geometry_info.sigma=1.0;
2295 new_image=EmbossImage(_image,geometry_info.rho,
2296 geometry_info.sigma,_exception);
2299 if (LocaleCompare("encipher",option+1) == 0)
2301 /* Note: arguments do not have percent escapes expanded */
2305 passkey=FileToStringInfo(arg1,~0UL,_exception);
2306 if (passkey != (StringInfo *) NULL)
2308 (void) PasskeyEncipherImage(_image,passkey,_exception);
2309 passkey=DestroyStringInfo(passkey);
2313 if (LocaleCompare("enhance",option+1) == 0)
2315 new_image=EnhanceImage(_image,_exception);
2318 if (LocaleCompare("equalize",option+1) == 0)
2320 (void) EqualizeImage(_image,_exception);
2323 if (LocaleCompare("evaluate",option+1) == 0)
2328 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2330 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2332 if (IfMagickFalse(IsGeometry(arg2)))
2333 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
2334 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
2335 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2339 if (LocaleCompare("extent",option+1) == 0)
2341 if (IfMagickFalse(IsGeometry(arg1)))
2342 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2343 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
2344 if (geometry.width == 0)
2345 geometry.width=_image->columns;
2346 if (geometry.height == 0)
2347 geometry.height=_image->rows;
2348 new_image=ExtentImage(_image,&geometry,_exception);
2351 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2355 if (LocaleCompare("flip",option+1) == 0)
2357 new_image=FlipImage(_image,_exception);
2360 if (LocaleCompare("flop",option+1) == 0)
2362 new_image=FlopImage(_image,_exception);
2365 if (LocaleCompare("floodfill",option+1) == 0)
2370 if (IfMagickFalse(IsGeometry(arg1)))
2371 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2372 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2373 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2374 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2375 geometry.y,IsPlusOp,_exception);
2378 if (LocaleCompare("frame",option+1) == 0)
2389 value=GetImageOption(_image_info,"compose");
2390 compose=OverCompositeOp; /* use Over not _image->compose */
2391 if (value != (const char *) NULL)
2392 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
2394 if (IfMagickFalse(IsGeometry(arg1)))
2395 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2396 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
2397 frame_info.width=geometry.width;
2398 frame_info.height=geometry.height;
2399 frame_info.outer_bevel=geometry.x;
2400 frame_info.inner_bevel=geometry.y;
2401 frame_info.x=(ssize_t) frame_info.width;
2402 frame_info.y=(ssize_t) frame_info.height;
2403 frame_info.width=_image->columns+2*frame_info.width;
2404 frame_info.height=_image->rows+2*frame_info.height;
2405 new_image=FrameImage(_image,&frame_info,compose,_exception);
2408 if (LocaleCompare("function",option+1) == 0)
2416 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2418 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2420 /* convert argument string into an array of doubles */
2421 args = StringToArrayOfDoubles(arg2,&count,_exception);
2422 if (args == (double *) NULL )
2423 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2425 (void) FunctionImage(_image,(MagickFunction)parse,(size_t) count,args,
2427 args=(double *) RelinquishMagickMemory(args);
2430 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2434 if (LocaleCompare("gamma",option+1) == 0)
2439 if (IfMagickFalse(IsGeometry(arg1)))
2440 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2441 constant=StringToDouble(arg1,(char **) NULL);
2443 /* Using Gamma, via a cache */
2445 constant=PerceptibleReciprocal(constant);
2446 (void) GammaImage(_image,constant,_exception);
2448 /* Using Evaluate POW, direct update of values - more accurite */
2450 constant=PerceptibleReciprocal(constant);
2451 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
2452 _image->gamma*=StringToDouble(arg1,(char **) NULL);
2454 /* Set gamma setting -- Old meaning of "+gamma"
2455 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2459 if (LocaleCompare("gaussian-blur",option+1) == 0)
2461 flags=ParseGeometry(arg1,&geometry_info);
2462 if ((flags & (RhoValue|SigmaValue)) == 0)
2463 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2464 if ((flags & SigmaValue) == 0)
2465 geometry_info.sigma=1.0;
2466 new_image=GaussianBlurImage(_image,geometry_info.rho,
2467 geometry_info.sigma,_exception);
2470 if (LocaleCompare("gaussian",option+1) == 0)
2472 CLIWandWarnReplaced("-gaussian-blur");
2473 (void) CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL,exception);
2475 if (LocaleCompare("geometry",option+1) == 0)
2478 Record Image offset for composition. (A Setting)
2479 Resize last _image. (ListOperator) -- DEPRECIATE
2480 FUTURE: Why if no 'offset' does this resize ALL images?
2481 Also why is the setting recorded in the IMAGE non-sense!
2484 { /* remove the previous composition geometry offset! */
2485 if (_image->geometry != (char *) NULL)
2486 _image->geometry=DestroyString(_image->geometry);
2489 if (IfMagickFalse(IsGeometry(arg1)))
2490 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2491 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
2492 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2493 (void) CloneString(&_image->geometry,arg1);
2495 new_image=ResizeImage(_image,geometry.width,geometry.height,
2496 _image->filter,_exception);
2499 if (LocaleCompare("grayscale",option+1) == 0)
2501 parse=ParseCommandOption(MagickPixelIntensityOptions,
2504 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
2506 (void) GrayscaleImage(_image,(PixelIntensityMethod) parse,_exception);
2509 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2513 if (LocaleCompare("hough-lines",option+1) == 0)
2515 flags=ParseGeometry(arg1,&geometry_info);
2516 if ((flags & (RhoValue|SigmaValue)) == 0)
2517 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2518 if ((flags & SigmaValue) == 0)
2519 geometry_info.sigma=geometry_info.rho;
2520 if ((flags & XiValue) == 0)
2521 geometry_info.xi=40;
2522 new_image=HoughLineImage(_image,(size_t) geometry_info.rho,
2523 (size_t) geometry_info.sigma,(size_t) geometry_info.xi,_exception);
2526 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2530 if (LocaleCompare("identify",option+1) == 0)
2536 format=GetImageOption(_image_info,"format");
2537 if (format == (char *) NULL)
2539 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2543 text=InterpretImageProperties(_image_info,_image,format,_exception);
2544 if (text == (char *) NULL)
2545 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
2547 (void) fputs(text,stdout);
2548 text=DestroyString((char *)text);
2551 if (LocaleCompare("implode",option+1) == 0)
2553 flags=ParseGeometry(arg1,&geometry_info);
2554 if ((flags & RhoValue) == 0)
2555 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2556 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2560 if (LocaleCompare("interpolative-resize",option+1) == 0)
2562 /* FUTURE: New to IMv7
2563 Roll into a resize special operator */
2564 if (IfMagickFalse(IsGeometry(arg1)))
2565 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2566 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2567 new_image=InterpolativeResizeImage(_image,geometry.width,
2568 geometry.height,_image->interpolate,_exception);
2571 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2575 if (LocaleCompare("kuwahara",option+1) == 0)
2578 Edge preserving blur.
2580 flags=ParseGeometry(arg1,&geometry_info);
2581 if ((flags & (RhoValue|SigmaValue)) == 0)
2582 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2583 if ((flags & SigmaValue) == 0)
2584 geometry_info.sigma=geometry_info.rho-0.5;
2585 new_image=KuwaharaImage(_image,geometry_info.rho,geometry_info.sigma,
2589 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2593 if (LocaleCompare("lat",option+1) == 0)
2595 flags=ParseGeometry(arg1,&geometry_info);
2596 if ((flags & (RhoValue|SigmaValue)) == 0)
2597 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2598 if ((flags & SigmaValue) == 0)
2599 geometry_info.sigma=1.0;
2600 if ((flags & PercentValue) != 0)
2601 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2602 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
2603 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2607 if (LocaleCompare("level",option+1) == 0)
2617 flags=ParseGeometry(arg1,&geometry_info);
2618 if ((flags & RhoValue) == 0)
2619 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2620 black_point=geometry_info.rho;
2621 white_point=(double) QuantumRange;
2622 if ((flags & SigmaValue) != 0)
2623 white_point=geometry_info.sigma;
2625 if ((flags & XiValue) != 0)
2626 gamma=geometry_info.xi;
2627 if ((flags & PercentValue) != 0)
2629 black_point*=(double) (QuantumRange/100.0);
2630 white_point*=(double) (QuantumRange/100.0);
2632 if ((flags & SigmaValue) == 0)
2633 white_point=(double) QuantumRange-black_point;
2634 if (IfPlusOp || ((flags & AspectValue) != 0))
2635 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
2637 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
2640 if (LocaleCompare("level-colors",option+1) == 0)
2643 token[MagickPathExtent];
2652 p=(const char *) arg1;
2653 GetMagickToken(p,&p,token); /* get black point color */
2654 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2655 (void) QueryColorCompliance(token,AllCompliance,
2656 &black_point,_exception);
2658 (void) QueryColorCompliance("#000000",AllCompliance,
2659 &black_point,_exception);
2660 if (isalpha((int) token[0]) || (token[0] == '#'))
2661 GetMagickToken(p,&p,token);
2663 white_point=black_point; /* set everything to that color */
2666 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2667 GetMagickToken(p,&p,token); /* Get white point color. */
2668 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2669 (void) QueryColorCompliance(token,AllCompliance,
2670 &white_point,_exception);
2672 (void) QueryColorCompliance("#ffffff",AllCompliance,
2673 &white_point,_exception);
2675 (void) LevelImageColors(_image,&black_point,&white_point,
2676 IsPlusOp,_exception);
2679 if (LocaleCompare("linear-stretch",option+1) == 0)
2688 flags=ParseGeometry(arg1,&geometry_info);
2689 if ((flags & RhoValue) == 0)
2690 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2691 black_point=geometry_info.rho;
2692 white_point=(double) _image->columns*_image->rows;
2693 if ((flags & SigmaValue) != 0)
2694 white_point=geometry_info.sigma;
2695 if ((flags & PercentValue) != 0)
2697 black_point*=(double) _image->columns*_image->rows/100.0;
2698 white_point*=(double) _image->columns*_image->rows/100.0;
2700 if ((flags & SigmaValue) == 0)
2701 white_point=(double) _image->columns*_image->rows-
2703 (void) LinearStretchImage(_image,black_point,white_point,_exception);
2706 if (LocaleCompare("liquid-rescale",option+1) == 0)
2708 /* FUTURE: Roll into a resize special operator */
2709 if (IfMagickFalse(IsGeometry(arg1)))
2710 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2711 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
2712 if ((flags & XValue) == 0)
2714 if ((flags & YValue) == 0)
2716 new_image=LiquidRescaleImage(_image,geometry.width,
2717 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
2720 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2724 if (LocaleCompare("magnify",option+1) == 0)
2726 new_image=MagnifyImage(_image,_exception);
2729 if (LocaleCompare("map",option+1) == 0)
2731 CLIWandWarnReplaced("-remap");
2732 (void) CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL,exception);
2735 if (LocaleCompare("mask",option+1) == 0)
2737 CLIWandWarnReplaced("-read-mask");
2738 (void) CLISimpleOperatorImage(cli_wand,"-read-mask",NULL,NULL,
2742 if (LocaleCompare("matte",option+1) == 0)
2744 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
2745 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2746 DeactivateAlphaChannel, _exception);
2749 if (LocaleCompare("mean-shift",option+1) == 0)
2751 flags=ParseGeometry(arg1,&geometry_info);
2752 if ((flags & (RhoValue|SigmaValue)) == 0)
2753 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2754 if ((flags & SigmaValue) == 0)
2755 geometry_info.sigma=1.0;
2756 if ((flags & XiValue) == 0)
2757 geometry_info.xi=0.10*QuantumRange;
2758 if ((flags & PercentValue) != 0)
2759 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2760 new_image=MeanShiftImage(_image,(size_t) geometry_info.rho,
2761 (size_t) geometry_info.sigma,geometry_info.xi,_exception);
2764 if (LocaleCompare("median",option+1) == 0)
2766 CLIWandWarnReplaced("-statistic Median");
2767 (void) CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1,exception);
2770 if (LocaleCompare("mode",option+1) == 0)
2772 /* FUTURE: note this is also a special "montage" option */
2773 CLIWandWarnReplaced("-statistic Mode");
2774 (void) CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1,exception);
2777 if (LocaleCompare("modulate",option+1) == 0)
2779 if (IfMagickFalse(IsGeometry(arg1)))
2780 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2781 (void) ModulateImage(_image,arg1,_exception);
2784 if (LocaleCompare("monitor",option+1) == 0)
2786 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
2787 (MagickProgressMonitor) NULL,(void *) NULL);
2790 if (LocaleCompare("monochrome",option+1) == 0)
2792 (void) SetImageType(_image,BilevelType,_exception);
2795 if (LocaleCompare("morphology",option+1) == 0)
2798 token[MagickPathExtent];
2810 GetMagickToken(p,&p,token);
2811 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2813 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",option,
2816 GetMagickToken(p,&p,token);
2817 if ((*p == ':') || (*p == ','))
2818 GetMagickToken(p,&p,token);
2820 iterations=(ssize_t) StringToLong(p);
2821 kernel=AcquireKernelInfo(arg2,exception);
2822 if (kernel == (KernelInfo *) NULL)
2823 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",option,arg2);
2824 new_image=MorphologyImage(_image,(MorphologyMethod)parse,iterations,
2826 kernel=DestroyKernelInfo(kernel);
2829 if (LocaleCompare("motion-blur",option+1) == 0)
2831 flags=ParseGeometry(arg1,&geometry_info);
2832 if ((flags & (RhoValue|SigmaValue)) == 0)
2833 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2834 if ((flags & SigmaValue) == 0)
2835 geometry_info.sigma=1.0;
2836 new_image=MotionBlurImage(_image,geometry_info.rho,geometry_info.sigma,
2837 geometry_info.xi,_exception);
2840 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2844 if (LocaleCompare("negate",option+1) == 0)
2846 (void) NegateImage(_image, IsPlusOp, _exception);
2849 if (LocaleCompare("noise",option+1) == 0)
2859 CLIWandWarnReplaced("-statistic NonPeak");
2860 (void) CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1,exception);
2863 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2865 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2868 value=GetImageOption(_image_info,"attenuate");
2869 if (value != (const char *) NULL)
2870 attenuate=StringToDouble(value,(char **) NULL);
2871 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2875 if (LocaleCompare("normalize",option+1) == 0)
2877 (void) NormalizeImage(_image,_exception);
2880 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2884 if (LocaleCompare("opaque",option+1) == 0)
2889 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2890 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,IsPlusOp,
2894 if (LocaleCompare("ordered-dither",option+1) == 0)
2896 (void) OrderedPosterizeImage(_image,arg1,_exception);
2899 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2903 if (LocaleCompare("paint",option+1) == 0)
2905 flags=ParseGeometry(arg1,&geometry_info);
2906 if ((flags & (RhoValue|SigmaValue)) == 0)
2907 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2908 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2912 if (LocaleCompare("perceptible",option+1) == 0)
2914 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2918 if (LocaleCompare("polaroid",option+1) == 0)
2930 random_info=AcquireRandomInfo();
2931 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2932 random_info=DestroyRandomInfo(random_info);
2935 flags=ParseGeometry(arg1,&geometry_info);
2936 if ((flags & RhoValue) == 0)
2937 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2938 angle=geometry_info.rho;
2940 caption=GetImageProperty(_image,"caption",_exception);
2941 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2942 _image->interpolate,_exception);
2945 if (LocaleCompare("posterize",option+1) == 0)
2947 flags=ParseGeometry(arg1,&geometry_info);
2948 if ((flags & RhoValue) == 0)
2949 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2950 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
2951 _quantize_info->dither_method,_exception);
2954 if (LocaleCompare("preview",option+1) == 0)
2956 /* FUTURE: should be a 'Genesis' option?
2957 Option however is also in WandSettingOptionInfo()
2960 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2962 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2964 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
2967 if (LocaleCompare("profile",option+1) == 0)
2969 /* Note: arguments do not have percent escapes expanded */
2983 { /* Remove a profile from the _image. */
2984 (void) ProfileImage(_image,arg1,(const unsigned char *)
2988 /* Associate a profile with the _image. */
2989 profile_info=CloneImageInfo(_image_info);
2990 profile=GetImageProfile(_image,"iptc");
2991 if (profile != (StringInfo *) NULL)
2992 profile_info->profile=(void *) CloneStringInfo(profile);
2993 profile_image=GetImageCache(profile_info,arg1,_exception);
2994 profile_info=DestroyImageInfo(profile_info);
2995 if (profile_image == (Image *) NULL)
3000 profile_info=CloneImageInfo(_image_info);
3001 (void) CopyMagickString(profile_info->filename,arg1,
3003 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
3004 if (profile != (StringInfo *) NULL)
3006 (void) ProfileImage(_image,profile_info->magick,
3007 GetStringInfoDatum(profile),(size_t)
3008 GetStringInfoLength(profile),_exception);
3009 profile=DestroyStringInfo(profile);
3011 profile_info=DestroyImageInfo(profile_info);
3014 ResetImageProfileIterator(profile_image);
3015 name=GetNextImageProfile(profile_image);
3016 while (name != (const char *) NULL)
3018 profile=GetImageProfile(profile_image,name);
3019 if (profile != (StringInfo *) NULL)
3020 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3021 (size_t) GetStringInfoLength(profile),_exception);
3022 name=GetNextImageProfile(profile_image);
3024 profile_image=DestroyImage(profile_image);
3027 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3031 if (LocaleCompare("rotational-blur",option+1) == 0)
3033 flags=ParseGeometry(arg1,&geometry_info);
3034 if ((flags & RhoValue) == 0)
3035 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3036 new_image=RotationalBlurImage(_image,geometry_info.rho,_exception);
3039 if (LocaleCompare("raise",option+1) == 0)
3041 if (IfMagickFalse(IsGeometry(arg1)))
3042 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3043 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3044 (void) RaiseImage(_image,&geometry,IsNormalOp,_exception);
3047 if (LocaleCompare("random-threshold",option+1) == 0)
3049 if (IfMagickFalse(IsGeometry(arg1)))
3050 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3051 (void) RandomThresholdImage(_image,arg1,_exception);
3054 if (LocaleCompare("read-mask",option+1) == 0)
3056 /* Note: arguments do not have percent escapes expanded */
3061 { /* Remove a mask. */
3062 (void) SetImageMask(_image,ReadPixelMask,(Image *) NULL,
3066 /* Set the image mask. */
3067 mask=GetImageCache(_image_info,arg1,_exception);
3068 if (mask == (Image *) NULL)
3070 (void) SetImageMask(_image,ReadPixelMask,mask,_exception);
3071 mask=DestroyImage(mask);
3074 if (LocaleCompare("recolor",option+1) == 0)
3076 CLIWandWarnReplaced("-color-matrix");
3077 (void) CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL,exception);
3079 if (LocaleCompare("remap",option+1) == 0)
3081 /* Note: arguments do not have percent escapes expanded */
3085 remap_image=GetImageCache(_image_info,arg1,_exception);
3086 if (remap_image == (Image *) NULL)
3088 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
3089 remap_image=DestroyImage(remap_image);
3092 if (LocaleCompare("repage",option+1) == 0)
3096 if (IfMagickFalse(IsGeometry(arg1)))
3097 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3099 (void) ResetImagePage(_image,arg1);
3102 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
3105 if (LocaleCompare("resample",option+1) == 0)
3107 /* FUTURE: Roll into a resize special operation */
3108 flags=ParseGeometry(arg1,&geometry_info);
3109 if ((flags & (RhoValue|SigmaValue)) == 0)
3110 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3111 if ((flags & SigmaValue) == 0)
3112 geometry_info.sigma=geometry_info.rho;
3113 new_image=ResampleImage(_image,geometry_info.rho,
3114 geometry_info.sigma,_image->filter,_exception);
3117 if (LocaleCompare("resize",option+1) == 0)
3119 if (IfMagickFalse(IsGeometry(arg1)))
3120 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3121 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3122 new_image=ResizeImage(_image,geometry.width,geometry.height,
3123 _image->filter,_exception);
3126 if (LocaleCompare("roll",option+1) == 0)
3128 if (IfMagickFalse(IsGeometry(arg1)))
3129 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3130 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3131 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
3134 if (LocaleCompare("rotate",option+1) == 0)
3136 flags=ParseGeometry(arg1,&geometry_info);
3137 if ((flags & RhoValue) == 0)
3138 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3139 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
3141 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3143 new_image=RotateImage(_image,geometry_info.rho,_exception);
3146 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3150 if (LocaleCompare("sample",option+1) == 0)
3152 /* FUTURE: Roll into a resize special operator */
3153 if (IfMagickFalse(IsGeometry(arg1)))
3154 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3155 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3156 new_image=SampleImage(_image,geometry.width,geometry.height,
3160 if (LocaleCompare("scale",option+1) == 0)
3162 /* FUTURE: Roll into a resize special operator */
3163 if (IfMagickFalse(IsGeometry(arg1)))
3164 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3165 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3166 new_image=ScaleImage(_image,geometry.width,geometry.height,
3170 if (LocaleCompare("segment",option+1) == 0)
3172 flags=ParseGeometry(arg1,&geometry_info);
3173 if ((flags & (RhoValue|SigmaValue)) == 0)
3174 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3175 if ((flags & SigmaValue) == 0)
3176 geometry_info.sigma=1.0;
3177 (void) SegmentImage(_image,_image->colorspace,
3178 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3182 if (LocaleCompare("selective-blur",option+1) == 0)
3184 flags=ParseGeometry(arg1,&geometry_info);
3185 if ((flags & (RhoValue|SigmaValue)) == 0)
3186 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3187 if ((flags & SigmaValue) == 0)
3188 geometry_info.sigma=1.0;
3189 if ((flags & PercentValue) != 0)
3190 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3191 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3192 geometry_info.sigma,geometry_info.xi,_exception);
3195 if (LocaleCompare("separate",option+1) == 0)
3197 /* WARNING: This can generate multiple images! */
3198 /* FUTURE - this may be replaced by a "-channel" method */
3199 new_image=SeparateImages(_image,_exception);
3202 if (LocaleCompare("sepia-tone",option+1) == 0)
3204 if (IfMagickFalse(IsGeometry(arg1)))
3205 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3206 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3207 (double) QuantumRange+1.0),_exception);
3210 if (LocaleCompare("shade",option+1) == 0)
3212 flags=ParseGeometry(arg1,&geometry_info);
3213 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3214 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3215 new_image=ShadeImage(_image,IsNormalOp,geometry_info.rho,
3216 geometry_info.sigma,_exception);
3219 if (LocaleCompare("shadow",option+1) == 0)
3221 flags=ParseGeometry(arg1,&geometry_info);
3222 if ((flags & (RhoValue|SigmaValue)) == 0)
3223 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3224 if ((flags & SigmaValue) == 0)
3225 geometry_info.sigma=1.0;
3226 if ((flags & XiValue) == 0)
3227 geometry_info.xi=4.0;
3228 if ((flags & PsiValue) == 0)
3229 geometry_info.psi=4.0;
3230 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3231 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3232 ceil(geometry_info.psi-0.5),_exception);
3235 if (LocaleCompare("sharpen",option+1) == 0)
3237 flags=ParseGeometry(arg1,&geometry_info);
3238 if ((flags & (RhoValue|SigmaValue)) == 0)
3239 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3240 if ((flags & SigmaValue) == 0)
3241 geometry_info.sigma=1.0;
3242 if ((flags & XiValue) == 0)
3243 geometry_info.xi=0.0;
3244 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3248 if (LocaleCompare("shave",option+1) == 0)
3250 if (IfMagickFalse(IsGeometry(arg1)))
3251 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3252 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3253 new_image=ShaveImage(_image,&geometry,_exception);
3256 if (LocaleCompare("shear",option+1) == 0)
3258 flags=ParseGeometry(arg1,&geometry_info);
3259 if ((flags & RhoValue) == 0)
3260 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3261 if ((flags & SigmaValue) == 0)
3262 geometry_info.sigma=geometry_info.rho;
3263 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3267 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
3269 flags=ParseGeometry(arg1,&geometry_info);
3270 if ((flags & RhoValue) == 0)
3271 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3272 if ((flags & SigmaValue) == 0)
3273 geometry_info.sigma=(double) QuantumRange/2.0;
3274 if ((flags & PercentValue) != 0)
3275 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3277 (void) SigmoidalContrastImage(_image,IsNormalOp,geometry_info.rho,
3278 geometry_info.sigma,_exception);
3281 if (LocaleCompare("sketch",option+1) == 0)
3283 flags=ParseGeometry(arg1,&geometry_info);
3284 if ((flags & (RhoValue|SigmaValue)) == 0)
3285 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3286 if ((flags & SigmaValue) == 0)
3287 geometry_info.sigma=1.0;
3288 new_image=SketchImage(_image,geometry_info.rho,
3289 geometry_info.sigma,geometry_info.xi,_exception);
3292 if (LocaleCompare("solarize",option+1) == 0)
3294 if (IfMagickFalse(IsGeometry(arg1)))
3295 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3296 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3297 QuantumRange+1.0),_exception);
3300 if (LocaleCompare("sparse-color",option+1) == 0)
3302 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3304 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3306 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3310 if (LocaleCompare("splice",option+1) == 0)
3312 if (IfMagickFalse(IsGeometry(arg1)))
3313 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3314 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
3315 new_image=SpliceImage(_image,&geometry,_exception);
3318 if (LocaleCompare("spread",option+1) == 0)
3320 flags=ParseGeometry(arg1,&geometry_info);
3321 if ((flags & RhoValue) == 0)
3322 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3323 new_image=SpreadImage(_image,geometry_info.rho,_exception);
3326 if (LocaleCompare("statistic",option+1) == 0)
3328 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3330 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
3332 flags=ParseGeometry(arg2,&geometry_info);
3333 if ((flags & RhoValue) == 0)
3334 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3335 if ((flags & SigmaValue) == 0)
3336 geometry_info.sigma=geometry_info.rho;
3337 new_image=StatisticImage(_image,(StatisticType)parse,
3338 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3342 if (LocaleCompare("strip",option+1) == 0)
3344 (void) StripImage(_image,_exception);
3347 if (LocaleCompare("swirl",option+1) == 0)
3349 flags=ParseGeometry(arg1,&geometry_info);
3350 if ((flags & RhoValue) == 0)
3351 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3352 new_image=SwirlImage(_image,geometry_info.rho,
3353 _image->interpolate,_exception);
3356 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3360 if (LocaleCompare("threshold",option+1) == 0)
3365 threshold=(double) QuantumRange/2;
3367 if (IfMagickFalse(IsGeometry(arg1)))
3368 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3369 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
3371 (void) BilevelImage(_image,threshold,_exception);
3374 if (LocaleCompare("thumbnail",option+1) == 0)
3376 if (IfMagickFalse(IsGeometry(arg1)))
3377 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3378 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3379 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3383 if (LocaleCompare("tint",option+1) == 0)
3385 if (IfMagickFalse(IsGeometry(arg1)))
3386 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3387 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
3390 if (LocaleCompare("transform",option+1) == 0)
3392 CLIWandWarnReplaced("+distort AffineProjection");
3393 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
3396 if (LocaleCompare("transparent",option+1) == 0)
3401 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3402 (void) TransparentPaintImage(_image,&target,(Quantum)
3403 TransparentAlpha,IsPlusOp,_exception);
3406 if (LocaleCompare("transpose",option+1) == 0)
3408 new_image=TransposeImage(_image,_exception);
3411 if (LocaleCompare("transverse",option+1) == 0)
3413 new_image=TransverseImage(_image,_exception);
3416 if (LocaleCompare("trim",option+1) == 0)
3418 new_image=TrimImage(_image,_exception);
3421 if (LocaleCompare("type",option+1) == 0)
3423 /* Note that "type" setting should have already been defined */
3424 (void) SetImageType(_image,_image_info->type,_exception);
3427 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3431 if (LocaleCompare("unique",option+1) == 0)
3433 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3434 Option is not documented, bt appears to be for "identify".
3435 We may need a identify specific verbose!
3438 (void) DeleteImageArtifact(_image,"identify:unique-colors");
3441 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3442 (void) SetImageArtifact(_image,"verbose","true");
3445 if (LocaleCompare("unique-colors",option+1) == 0)
3447 new_image=UniqueImageColors(_image,_exception);
3450 if (LocaleCompare("unsharp",option+1) == 0)
3452 flags=ParseGeometry(arg1,&geometry_info);
3453 if ((flags & (RhoValue|SigmaValue)) == 0)
3454 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3455 if ((flags & SigmaValue) == 0)
3456 geometry_info.sigma=1.0;
3457 if ((flags & XiValue) == 0)
3458 geometry_info.xi=1.0;
3459 if ((flags & PsiValue) == 0)
3460 geometry_info.psi=0.05;
3461 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3462 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
3465 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3469 if (LocaleCompare("verbose",option+1) == 0)
3471 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
3472 three places! ImageArtifact ImageOption _image_info->verbose
3473 Some how new images also get this artifact!
3475 (void) SetImageArtifact(_image,option+1,
3476 IfNormalOp ? "true" : "false" );
3479 if (LocaleCompare("vignette",option+1) == 0)
3481 flags=ParseGeometry(arg1,&geometry_info);
3482 if ((flags & (RhoValue|SigmaValue)) == 0)
3483 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3484 if ((flags & SigmaValue) == 0)
3485 geometry_info.sigma=1.0;
3486 if ((flags & XiValue) == 0)
3487 geometry_info.xi=0.1*_image->columns;
3488 if ((flags & PsiValue) == 0)
3489 geometry_info.psi=0.1*_image->rows;
3490 if ((flags & PercentValue) != 0)
3492 geometry_info.xi*=(double) _image->columns/100.0;
3493 geometry_info.psi*=(double) _image->rows/100.0;
3495 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3496 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3497 ceil(geometry_info.psi-0.5),_exception);
3500 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3504 if (LocaleCompare("wave",option+1) == 0)
3506 flags=ParseGeometry(arg1,&geometry_info);
3507 if ((flags & (RhoValue|SigmaValue)) == 0)
3508 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3509 if ((flags & SigmaValue) == 0)
3510 geometry_info.sigma=1.0;
3511 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3512 _image->interpolate,_exception);
3515 if (LocaleCompare("white-threshold",option+1) == 0)
3517 if (IfMagickFalse(IsGeometry(arg1)))
3518 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3519 (void) WhiteThresholdImage(_image,arg1,_exception);
3522 if (LocaleCompare("write-mask",option+1) == 0)
3524 /* Note: arguments do not have percent escapes expanded */
3529 { /* Remove a mask. */
3530 (void) SetImageMask(_image,WritePixelMask,(Image *) NULL,
3534 /* Set the image mask. */
3535 mask=GetImageCache(_image_info,arg1,_exception);
3536 if (mask == (Image *) NULL)
3538 (void) SetImageMask(_image,WritePixelMask,mask,_exception);
3539 mask=DestroyImage(mask);
3542 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3545 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3547 /* clean up percent escape interpreted strings */
3549 arg1=DestroyString((char *)arg1);
3551 arg2=DestroyString((char *)arg2);
3553 /* Replace current image with any image that was generated
3554 and set image point to last image (so image->next is correct) */
3555 if (new_image != (Image *) NULL)
3556 ReplaceImageInListReturnLast(&_image,new_image);
3561 #undef _quantize_info
3570 WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
3571 const char *option,const char *arg1,const char *arg2,ExceptionInfo *exception)
3573 #if !USE_WAND_METHODS
3579 assert(cli_wand != (MagickCLI *) NULL);
3580 assert(cli_wand->signature == MagickWandSignature);
3581 assert(cli_wand->wand.signature == MagickWandSignature);
3582 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3584 if (IfMagickTrue(cli_wand->wand.debug))
3585 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3586 "- Simple Operator: %s \"%s\" \"%s\"", option,arg1,arg2);
3588 #if !USE_WAND_METHODS
3589 /* FUTURE add appropriate tracing */
3591 n=GetImageListLength(cli_wand->wand.images);
3592 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3595 CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
3596 if ( cli_wand->wand.images->next == (Image *) NULL )
3598 cli_wand->wand.images=cli_wand->wand.images->next;
3601 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3603 MagickResetIterator(&cli_wand->wand);
3604 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
3605 (void) CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
3606 MagickResetIterator(&cli_wand->wand);
3612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3616 + C L I L i s t O p e r a t o r I m a g e s %
3620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3622 % CLIListOperatorImages() applies a single operation that is apply to the
3623 % entire image list as a whole. The result is often a complete replacment
3624 % of the image list with a completely new list, or with just a single image
3627 % The format of the MogrifyImage method is:
3629 % MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3630 % const char *option,const char *arg1,const char *arg2)
3632 % A description of each parameter follows:
3634 % o cli_wand: structure holding settings to be applied
3636 % o option: The option string for the operation
3638 % o arg1, arg2: optional argument strings to the operation
3639 % arg2 is currently not used
3642 WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3643 const char *option,const char *arg1n,const char *arg2n)
3645 const char /* percent escaped versions of the args */
3658 #define _image_info (cli_wand->wand.image_info)
3659 #define _images (cli_wand->wand.images)
3660 #define _exception (cli_wand->wand.exception)
3661 #define _draw_info (cli_wand->draw_info)
3662 #define _quantize_info (cli_wand->quantize_info)
3663 #define _process_flags (cli_wand->process_flags)
3664 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
3665 #define IfNormalOp (*option=='-')
3666 #define IfPlusOp (*option!='-')
3667 #define IsNormalOp IfNormalOp ? MagickTrue : MagickFalse
3669 assert(cli_wand != (MagickCLI *) NULL);
3670 assert(cli_wand->signature == MagickWandSignature);
3671 assert(cli_wand->wand.signature == MagickWandSignature);
3672 assert(_images != (Image *) NULL); /* _images must be present */
3674 if (IfMagickTrue(cli_wand->wand.debug))
3675 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3676 "- List Operator: %s \"%s\" \"%s\"", option,
3677 arg1n == (const char *) NULL ? "null" : arg1n,
3678 arg2n == (const char *) NULL ? "null" : arg2n);
3683 /* Interpret Percent Escapes in Arguments - using first image */
3684 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3685 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3686 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3687 /* Interpret Percent escapes in argument 1 */
3688 if (arg1n != (char *) NULL) {
3689 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3690 if (arg1 == (char *) NULL) {
3691 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3692 arg1=arg1n; /* use the given argument as is */
3695 if (arg2n != (char *) NULL) {
3696 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3697 if (arg2 == (char *) NULL) {
3698 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3699 arg2=arg2n; /* use the given argument as is */
3703 #undef _process_flags
3707 new_images=NewImageList();
3709 switch (*(option+1))
3713 if (LocaleCompare("append",option+1) == 0)
3715 new_images=AppendImages(_images,IsNormalOp,_exception);
3718 if (LocaleCompare("average",option+1) == 0)
3720 CLIWandWarnReplaced("-evaluate-sequence Mean");
3721 (void) CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
3724 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3728 if (LocaleCompare("channel-fx",option+1) == 0)
3730 new_images=ChannelFxImage(_images,arg1,_exception);
3733 if (LocaleCompare("clut",option+1) == 0)
3738 /* FUTURE - make this a compose option, and thus can be used
3739 with layers compose or even compose last image over all other
3742 new_images=RemoveFirstImageFromList(&_images);
3743 clut_image=RemoveLastImageFromList(&_images);
3744 /* FUTURE - produce Exception, rather than silent fail */
3745 if (clut_image == (Image *) NULL)
3747 (void) ClutImage(new_images,clut_image,new_images->interpolate,
3749 clut_image=DestroyImage(clut_image);
3752 if (LocaleCompare("coalesce",option+1) == 0)
3754 new_images=CoalesceImages(_images,_exception);
3757 if (LocaleCompare("combine",option+1) == 0)
3759 parse=(ssize_t) _images->colorspace;
3761 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
3763 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
3765 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
3768 if (LocaleCompare("compare",option+1) == 0)
3781 Mathematically and visually annotate the difference between an
3782 image and its reconstruction.
3784 image=RemoveFirstImageFromList(&_images);
3785 reconstruct_image=RemoveFirstImageFromList(&_images);
3786 /* FUTURE - produce Exception, rather than silent fail */
3787 if (reconstruct_image == (Image *) NULL)
3789 metric=UndefinedErrorMetric;
3790 option=GetImageOption(_image_info,"metric");
3791 if (option != (const char *) NULL)
3792 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
3793 MagickFalse,option);
3794 new_images=CompareImages(image,reconstruct_image,metric,&distortion,
3797 reconstruct_image=DestroyImage(reconstruct_image);
3798 image=DestroyImage(image);
3801 if (LocaleCompare("complex",option+1) == 0)
3803 parse=ParseCommandOption(MagickComplexOptions,MagickFalse,arg1);
3805 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3807 new_images=ComplexImages(_images,(ComplexOperator) parse,_exception);
3810 if (LocaleCompare("composite",option+1) == 0)
3828 /* Compose value from "-compose" option only */
3829 value=GetImageOption(_image_info,"compose");
3830 if (value == (const char *) NULL)
3831 compose=OverCompositeOp; /* use Over not source_image->compose */
3833 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3836 /* Get "clip-to-self" expert setting (false is normal) */
3837 value=GetImageOption(_image_info,"compose:clip-to-self");
3838 if (value == (const char *) NULL)
3839 clip_to_self=MagickTrue;
3841 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3842 "compose:clip-to-self")); /* if this is true */
3843 value=GetImageOption(_image_info,"compose:outside-overlay");
3844 if (value != (const char *) NULL) { /* or this false */
3845 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
3846 clip_to_self=IsStringFalse(value);
3849 new_images=RemoveFirstImageFromList(&_images);
3850 source_image=RemoveFirstImageFromList(&_images);
3851 if (source_image == (Image *) NULL)
3852 break; /* FUTURE - produce Exception, rather than silent fail */
3854 /* FUTURE - this should not be here! - should be part of -geometry */
3855 (void) TransformImage(&source_image,(char *) NULL,
3856 source_image->geometry,_exception);
3857 SetGeometry(source_image,&geometry);
3858 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3859 GravityAdjustGeometry(new_images->columns,new_images->rows,
3860 new_images->gravity, &geometry);
3861 mask_image=RemoveFirstImageFromList(&_images);
3862 if (mask_image == (Image *) NULL)
3863 status&=CompositeImage(new_images,source_image,compose,clip_to_self,
3864 geometry.x,geometry.y,_exception);
3867 if ((compose == DisplaceCompositeOp) ||
3868 (compose == DistortCompositeOp))
3870 status&=CompositeImage(source_image,mask_image,
3871 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3872 status&=CompositeImage(new_images,source_image,compose,
3873 clip_to_self,geometry.x,geometry.y,_exception);
3880 clone_image=CloneImage(new_images,0,0,MagickTrue,_exception);
3881 if (clone_image == (Image *) NULL)
3883 status&=CompositeImage(new_images,source_image,compose,
3884 clip_to_self,geometry.x,geometry.y,_exception);
3885 status&=CompositeImage(new_images,mask_image,
3886 CopyAlphaCompositeOp,MagickTrue,0,0,_exception);
3887 status&=CompositeImage(clone_image,new_images,OverCompositeOp,
3888 clip_to_self,geometry.x,geometry.y,_exception);
3889 new_images=DestroyImage(new_images);
3890 new_images=clone_image;
3892 mask_image=DestroyImage(mask_image);
3894 source_image=DestroyImage(source_image);
3897 if (LocaleCompare("copy",option+1) == 0)
3911 if (IfMagickFalse(IsGeometry(arg1)))
3912 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3913 if (IfMagickFalse(IsGeometry(arg2)))
3914 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3915 (void) ParsePageGeometry(_images,arg2,&geometry,_exception);
3916 offset.x=geometry.x;
3917 offset.y=geometry.y;
3918 source_image=_images;
3919 if (source_image->next != (Image *) NULL)
3920 source_image=source_image->next;
3921 (void) ParsePageGeometry(source_image,arg1,&geometry,_exception);
3922 (void) CopyImagePixels(_images,source_image,&geometry,&offset,
3926 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3930 if (LocaleCompare("deconstruct",option+1) == 0)
3932 CLIWandWarnReplaced("-layer CompareAny");
3933 (void) CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
3936 if (LocaleCompare("delete",option+1) == 0)
3939 DeleteImages(&_images,arg1,_exception);
3941 DeleteImages(&_images,"-1",_exception);
3944 if (LocaleCompare("duplicate",option+1) == 0)
3954 if (IfMagickFalse(IsGeometry(arg1)))
3955 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3957 number_duplicates=(size_t) StringToLong(arg1);
3959 if (p == (const char *) NULL)
3960 new_images=DuplicateImages(_images,number_duplicates,"-1",
3963 new_images=DuplicateImages(_images,number_duplicates,p,
3967 new_images=DuplicateImages(_images,1,"-1",_exception);
3968 AppendImageToList(&_images, new_images);
3969 new_images=(Image *) NULL;
3972 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3976 if (LocaleCompare("evaluate-sequence",option+1) == 0)
3978 parse=ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3980 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3982 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3986 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3990 if (LocaleCompare("fft",option+1) == 0)
3992 new_images=ForwardFourierTransformImage(_images,IsNormalOp,
3996 if (LocaleCompare("flatten",option+1) == 0)
3998 /* REDIRECTED to use -layers flatten instead */
3999 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
4002 if (LocaleCompare("fx",option+1) == 0)
4004 new_images=FxImage(_images,arg1,_exception);
4007 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4011 if (LocaleCompare("hald-clut",option+1) == 0)
4013 /* FUTURE - make this a compose option (and thus layers compose )
4014 or perhaps compose last image over all other _images.
4019 new_images=RemoveFirstImageFromList(&_images);
4020 hald_image=RemoveLastImageFromList(&_images);
4021 if (hald_image == (Image *) NULL)
4023 (void) HaldClutImage(new_images,hald_image,_exception);
4024 hald_image=DestroyImage(hald_image);
4027 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4031 if (LocaleCompare("ift",option+1) == 0)
4037 magnitude_image=RemoveFirstImageFromList(&_images);
4038 phase_image=RemoveFirstImageFromList(&_images);
4039 /* FUTURE - produce Exception, rather than silent fail */
4040 if (phase_image == (Image *) NULL)
4042 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
4043 IsNormalOp,_exception);
4044 magnitude_image=DestroyImage(magnitude_image);
4045 phase_image=DestroyImage(phase_image);
4048 if (LocaleCompare("insert",option+1) == 0)
4057 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
4058 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4060 insert_image=RemoveLastImageFromList(&_images);
4062 index=(ssize_t) StringToLong(arg1);
4063 index_image=insert_image;
4065 PrependImageToList(&_images,insert_image);
4066 else if (index == (ssize_t) GetImageListLength(_images))
4067 AppendImageToList(&_images,insert_image);
4070 index_image=GetImageFromList(_images,index-1);
4071 if (index_image == (Image *) NULL)
4072 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
4073 InsertImageInList(&index_image,insert_image);
4075 _images=GetFirstImageInList(index_image);
4078 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4082 if (LocaleCompare("layers",option+1) == 0)
4084 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4086 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4088 switch ((LayerMethod) parse)
4092 new_images=CoalesceImages(_images,_exception);
4095 case CompareAnyLayer:
4096 case CompareClearLayer:
4097 case CompareOverlayLayer:
4100 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
4107 case TrimBoundsLayer:
4109 new_images=MergeImageLayers(_images,(LayerMethod) parse,
4115 new_images=DisposeImages(_images,_exception);
4118 case OptimizeImageLayer:
4120 new_images=OptimizeImageLayers(_images,_exception);
4123 case OptimizePlusLayer:
4125 new_images=OptimizePlusImageLayers(_images,_exception);
4128 case OptimizeTransLayer:
4130 OptimizeImageTransparency(_images,_exception);
4133 case RemoveDupsLayer:
4135 RemoveDuplicateLayers(&_images,_exception);
4138 case RemoveZeroLayer:
4140 RemoveZeroDelayLayers(&_images,_exception);
4144 { /* General Purpose, GIF Animation Optimizer. */
4145 new_images=CoalesceImages(_images,_exception);
4146 if (new_images == (Image *) NULL)
4148 _images=DestroyImageList(_images);
4149 _images=OptimizeImageLayers(new_images,_exception);
4150 if (_images == (Image *) NULL)
4152 new_images=DestroyImageList(new_images);
4153 OptimizeImageTransparency(_images,_exception);
4154 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4158 case CompositeLayer:
4172 value=GetImageOption(_image_info,"compose");
4173 compose=OverCompositeOp; /* Default to Over */
4174 if (value != (const char *) NULL)
4175 compose=(CompositeOperator) ParseCommandOption(
4176 MagickComposeOptions,MagickFalse,value);
4178 /* Split image sequence at the first 'NULL:' image. */
4180 while (source != (Image *) NULL)
4182 source=GetNextImageInList(source);
4183 if ((source != (Image *) NULL) &&
4184 (LocaleCompare(source->magick,"NULL") == 0))
4187 if (source != (Image *) NULL)
4189 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4190 (GetNextImageInList(source) == (Image *) NULL))
4191 source=(Image *) NULL;
4193 { /* Separate the two lists, junk the null: image. */
4194 source=SplitImageList(source->previous);
4195 DeleteImageFromList(&source);
4198 if (source == (Image *) NULL)
4200 (void) ThrowMagickException(_exception,GetMagickModule(),
4201 OptionError,"MissingNullSeparator","layers Composite");
4204 /* Adjust offset with gravity and virtual canvas. */
4205 SetGeometry(_images,&geometry);
4206 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
4207 geometry.width=source->page.width != 0 ?
4208 source->page.width : source->columns;
4209 geometry.height=source->page.height != 0 ?
4210 source->page.height : source->rows;
4211 GravityAdjustGeometry(_images->page.width != 0 ?
4212 _images->page.width : _images->columns,
4213 _images->page.height != 0 ? _images->page.height :
4214 _images->rows,_images->gravity,&geometry);
4216 /* Compose the two image sequences together */
4217 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4219 source=DestroyImageList(source);
4225 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4229 if (LocaleCompare("map",option+1) == 0)
4231 CLIWandWarnReplaced("+remap");
4232 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4235 if (LocaleCompare("metric",option+1) == 0)
4237 if (LocaleCompare("morph",option+1) == 0)
4242 if (IfMagickFalse(IsGeometry(arg1)))
4243 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4244 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4246 if (morph_image == (Image *) NULL)
4248 _images=DestroyImageList(_images);
4249 _images=morph_image;
4252 if (LocaleCompare("mosaic",option+1) == 0)
4254 /* REDIRECTED to use -layers mosaic instead */
4255 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
4258 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4262 if (LocaleCompare("poly",option+1) == 0)
4270 /* convert argument string into an array of doubles */
4271 args = StringToArrayOfDoubles(arg1,&count,_exception);
4272 if (args == (double *) NULL )
4273 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg1);
4274 new_images=PolynomialImage(_images,(size_t) (count >> 1),args,
4276 args=(double *) RelinquishMagickMemory(args);
4279 if (LocaleCompare("process",option+1) == 0)
4281 /* FUTURE: better parsing using ScriptToken() from string ??? */
4289 arguments=StringToArgv(arg1,&number_arguments);
4290 if (arguments == (char **) NULL)
4292 if (strchr(arguments[1],'=') != (char *) NULL)
4313 Support old style syntax, filter="-option arg1".
4315 assert(arg1 != (const char *) NULL);
4316 length=strlen(arg1);
4317 token=(char *) NULL;
4318 if (~length >= (MagickPathExtent-1))
4319 token=(char *) AcquireQuantumMemory(length+MagickPathExtent,
4321 if (token == (char *) NULL)
4325 token_info=AcquireTokenInfo();
4326 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4327 "\"",'\0',&breaker,&next,"e);
4328 token_info=DestroyTokenInfo(token_info);
4334 argv=(&(arguments[next]));
4335 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4338 token=DestroyString(token);
4341 (void) SubstituteString(&arguments[1],"-","");
4342 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4343 number_arguments-2,(const char **) arguments+2,_exception);
4344 for (j=0; j < number_arguments; j++)
4345 arguments[j]=DestroyString(arguments[j]);
4346 arguments=(char **) RelinquishMagickMemory(arguments);
4349 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4353 if (LocaleCompare("remap",option+1) == 0)
4355 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4358 if (LocaleCompare("reverse",option+1) == 0)
4360 ReverseImageList(&_images);
4363 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4367 if (LocaleCompare("smush",option+1) == 0)
4369 /* FUTURE: this option needs more work to make better */
4373 if (IfMagickFalse(IsGeometry(arg1)))
4374 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4375 offset=(ssize_t) StringToLong(arg1);
4376 new_images=SmushImages(_images,IsNormalOp,offset,_exception);
4379 if (LocaleCompare("subimage",option+1) == 0)
4397 base_image=GetImageFromList(_images,0);
4398 compare_image=GetImageFromList(_images,1);
4400 /* Comparision Metric */
4401 metric=UndefinedErrorMetric;
4402 value=GetImageOption(_image_info,"metric");
4403 if (value != (const char *) NULL)
4404 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4407 new_images=SimilarityImage(base_image,compare_image,metric,0.0,
4408 &offset,&similarity,_exception);
4410 if (new_images != (Image *) NULL)
4413 result[MagickPathExtent];
4415 (void) FormatLocaleString(result,MagickPathExtent,"%lf",
4417 (void) SetImageProperty(new_images,"subimage:similarity",result,
4419 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",(long)
4421 (void) SetImageProperty(new_images,"subimage:x",result,
4423 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",(long)
4425 (void) SetImageProperty(new_images,"subimage:y",result,
4427 (void) FormatLocaleString(result,MagickPathExtent,
4428 "%lux%lu%+ld%+ld",(unsigned long) offset.width,(unsigned long)
4429 offset.height,(long) offset.x,(long) offset.y);
4430 (void) SetImageProperty(new_images,"subimage:offset",result,
4435 if (LocaleCompare("swap",option+1) == 0)
4456 flags=ParseGeometry(arg1,&geometry_info);
4457 if ((flags & RhoValue) == 0)
4458 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4459 index=(ssize_t) geometry_info.rho;
4460 if ((flags & SigmaValue) != 0)
4461 swap_index=(ssize_t) geometry_info.sigma;
4463 p=GetImageFromList(_images,index);
4464 q=GetImageFromList(_images,swap_index);
4465 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4467 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4469 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4472 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
4473 swap=CloneImage(p,0,0,MagickTrue,_exception);
4474 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4475 ReplaceImageInList(&q,swap);
4476 _images=GetFirstImageInList(q);
4479 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4482 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4485 /* clean up percent escape interpreted strings */
4487 arg1=DestroyString((char *)arg1);
4489 arg2=DestroyString((char *)arg2);
4491 /* if new image list generated, replace existing image list */
4492 if (new_images == (Image *) NULL)
4493 return(status == 0 ? MagickFalse : MagickTrue);
4494 _images=DestroyImageList(_images);
4495 _images=GetFirstImageInList(new_images);
4496 return(status == 0 ? MagickFalse : MagickTrue);
4502 #undef _quantize_info
4509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4513 + C L I N o I m a g e O p e r a t i o n s %
4517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4519 % CLINoImageOperator() Applies operations that may not actually need images
4522 % The classic operators of this type is "-read", which actually creates
4523 % images even when no images are present. Or image stack operators, which
4524 % can be applied (push or pop) to an empty image list.
4526 % Note that these operators may involve other special 'option' prefix
4527 % characters other than '-' or '+', namely parenthesis and braces.
4529 % The format of the CLINoImageOption method is:
4531 % void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4532 % const char *arg1, const char *arg2)
4534 % A description of each parameter follows:
4536 % o cli_wand: the main CLI Wand to use. (sometimes not required)
4538 % o option: The special option (with any switch char) to process
4540 % o arg1 & arg2: Argument for option, if required
4541 % Currently arg2 is not used.
4544 WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
4545 const char *option,const char *arg1n,const char *arg2n)
4547 const char /* percent escaped versions of the args */
4551 #define _image_info (cli_wand->wand.image_info)
4552 #define _images (cli_wand->wand.images)
4553 #define _exception (cli_wand->wand.exception)
4554 #define _process_flags (cli_wand->process_flags)
4555 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
4556 #define IfNormalOp (*option=='-')
4557 #define IfPlusOp (*option!='-')
4559 assert(cli_wand != (MagickCLI *) NULL);
4560 assert(cli_wand->signature == MagickWandSignature);
4561 assert(cli_wand->wand.signature == MagickWandSignature);
4563 if (IfMagickTrue(cli_wand->wand.debug))
4564 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
4565 "- NoImage Operator: %s \"%s\" \"%s\"", option,
4566 arg1n != (char *) NULL ? arg1n : "",
4567 arg2n != (char *) NULL ? arg2n : "");
4572 /* Interpret Percent Escapes in Arguments - using first image */
4573 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4574 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4575 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4576 /* Interpret Percent escapes in argument 1 */
4577 if (arg1n != (char *) NULL) {
4578 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4579 if (arg1 == (char *) NULL) {
4580 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4581 arg1=arg1n; /* use the given argument as is */
4584 if (arg2n != (char *) NULL) {
4585 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4586 if (arg2 == (char *) NULL) {
4587 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4588 arg2=arg2n; /* use the given argument as is */
4592 #undef _process_flags
4595 do { /* break to exit code */
4597 No-op options (ignore these)
4599 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
4601 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4603 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4605 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
4607 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4612 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4613 ( LocaleCompare("--",option) == 0 ) ) {
4614 /* Do Glob filename Expansion for 'arg1' then read all images.
4616 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4617 * (but attaching to the filenames in the generated argument list) any
4618 * [...] read modifiers that may be present.
4620 * For example: It will expand '*.gif[20x20]' into a list such as
4621 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4623 * NOTE: In IMv6 this was done globally across all images. This
4624 * meant you could include IM options in '@filename' lists, but you
4625 * could not include comments. Doing it only for image read makes
4626 * it far more secure.
4628 * Note: arguments do not have percent escapes expanded for security
4636 argv = (char **) &arg1;
4638 /* Expand 'glob' expressions in the given filename.
4639 Expansion handles any 'coder:' prefix, or read modifiers attached
4640 to the filename, including them in the resulting expanded list.
4642 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4643 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4644 option,GetExceptionMessage(errno));
4646 /* loop over expanded filename list, and read then all in */
4647 for (i=0; i < (ssize_t) argc; i++) {
4650 if (IfMagickTrue(_image_info->ping))
4651 new_images=PingImages(_image_info,argv[i],_exception);
4653 new_images=ReadImages(_image_info,argv[i],_exception);
4654 AppendImageToList(&_images, new_images);
4656 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4661 Note: Writing a empty image list is valid in specific cases
4663 if (LocaleCompare("write",option+1) == 0) {
4664 /* Note: arguments do not have percent escapes expanded */
4666 key[MagickPathExtent];
4674 /* Need images, unless a "null:" output coder is used */
4675 if ( _images == (Image *) NULL ) {
4676 if ( LocaleCompare(arg1,"null:") == 0 )
4678 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4681 (void) FormatLocaleString(key,MagickPathExtent,"cache:%s",arg1);
4682 (void) DeleteImageRegistry(key);
4683 write_images=_images;
4685 write_images=CloneImageList(_images,_exception);
4686 write_info=CloneImageInfo(_image_info);
4687 (void) WriteImages(write_info,write_images,arg1,_exception);
4688 write_info=DestroyImageInfo(write_info);
4690 write_images=DestroyImageList(write_images);
4694 Parenthesis and Brace operations
4696 if (LocaleCompare("(",option) == 0) {
4697 /* stack 'push' images */
4705 node=cli_wand->image_list_stack;
4706 for ( ; node != (Stack *) NULL; node=node->next)
4708 if ( size >= MAX_STACK_DEPTH )
4709 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4710 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4711 if (node == (Stack *) NULL)
4712 CLIWandExceptionBreak(ResourceLimitFatalError,
4713 "MemoryAllocationFailed",option);
4714 node->data = (void *)cli_wand->wand.images;
4715 node->next = cli_wand->image_list_stack;
4716 cli_wand->image_list_stack = node;
4717 cli_wand->wand.images = NewImageList();
4719 /* handle respect-parenthesis */
4720 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4721 "respect-parenthesis"))))
4722 option="{"; /* fall-thru so as to push image settings too */
4725 /* fall thru to operation */
4727 if (LocaleCompare("{",option) == 0) {
4728 /* stack 'push' of image_info settings */
4736 node=cli_wand->image_info_stack;
4737 for ( ; node != (Stack *) NULL; node=node->next)
4739 if ( size >= MAX_STACK_DEPTH )
4740 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4741 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4742 if (node == (Stack *) NULL)
4743 CLIWandExceptionBreak(ResourceLimitFatalError,
4744 "MemoryAllocationFailed",option);
4746 node->data = (void *)cli_wand->wand.image_info;
4747 node->next = cli_wand->image_info_stack;
4749 cli_wand->image_info_stack = node;
4750 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4751 if (cli_wand->wand.image_info == (ImageInfo *) NULL) {
4752 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4754 cli_wand->wand.image_info = (ImageInfo *)node->data;
4755 node = (Stack *)RelinquishMagickMemory(node);
4761 if (LocaleCompare(")",option) == 0) {
4762 /* pop images from stack */
4766 node = (Stack *)cli_wand->image_list_stack;
4767 if ( node == (Stack *) NULL)
4768 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4769 cli_wand->image_list_stack = node->next;
4771 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4772 cli_wand->wand.images= (Image *)node->data;
4773 node = (Stack *)RelinquishMagickMemory(node);
4775 /* handle respect-parenthesis - of the previous 'pushed' settings */
4776 node = cli_wand->image_info_stack;
4777 if ( node != (Stack *) NULL)
4779 if (IfMagickTrue(IsStringTrue(GetImageOption(
4780 cli_wand->wand.image_info,"respect-parenthesis"))))
4781 option="}"; /* fall-thru so as to pop image settings too */
4787 /* fall thru to next if */
4789 if (LocaleCompare("}",option) == 0) {
4790 /* pop image_info settings from stack */
4794 node = (Stack *)cli_wand->image_info_stack;
4795 if ( node == (Stack *) NULL)
4796 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4797 cli_wand->image_info_stack = node->next;
4799 (void) DestroyImageInfo(cli_wand->wand.image_info);
4800 cli_wand->wand.image_info = (ImageInfo *)node->data;
4801 node = (Stack *)RelinquishMagickMemory(node);
4803 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4804 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4805 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4809 if (LocaleCompare("print",option+1) == 0)
4811 (void) FormatLocaleFile(stdout,"%s",arg1);
4814 if (LocaleCompare("set",option+1) == 0)
4816 /* Settings are applied to each image in memory in turn (if any).
4817 While a option: only need to be applied once globally.
4819 NOTE: rguments have not been automatically percent expaneded
4822 /* escape the 'key' once only, using first image. */
4823 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4824 if (arg1 == (char *) NULL)
4825 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4828 if (LocaleNCompare(arg1,"registry:",9) == 0)
4832 (void) DeleteImageRegistry(arg1+9);
4833 arg1=DestroyString((char *)arg1);
4836 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4837 if (arg2 == (char *) NULL) {
4838 arg1=DestroyString((char *)arg1);
4839 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4842 (void) SetImageRegistry(StringRegistryType,arg1+9,arg2,_exception);
4843 arg1=DestroyString((char *)arg1);
4844 arg2=DestroyString((char *)arg2);
4847 if (LocaleNCompare(arg1,"option:",7) == 0)
4849 /* delete equivelent artifact from all images (if any) */
4850 if (_images != (Image *) NULL)
4852 MagickResetIterator(&cli_wand->wand);
4853 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4854 (void) DeleteImageArtifact(_images,arg1+7);
4855 MagickResetIterator(&cli_wand->wand);
4857 /* now set/delete the global option as needed */
4858 /* FUTURE: make escapes in a global 'option:' delayed */
4862 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4863 if (arg2 == (char *) NULL)
4864 CLIWandExceptionBreak(OptionWarning,
4865 "InterpretPropertyFailure",option);
4867 (void) SetImageOption(_image_info,arg1+7,arg2);
4868 arg1=DestroyString((char *)arg1);
4869 arg2=DestroyString((char *)arg2);
4872 /* Set Artifacts/Properties/Attributes all images (required) */
4873 if ( _images == (Image *) NULL )
4874 CLIWandExceptArgBreak(OptionWarning,"NoImageForProperty",option,arg1);
4876 MagickResetIterator(&cli_wand->wand);
4877 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4882 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4883 if (arg2 == (char *) NULL)
4884 CLIWandExceptionBreak(OptionWarning,
4885 "InterpretPropertyFailure",option);
4887 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4888 (void) SetImageArtifact(_images,arg1+9,arg2);
4889 else if (LocaleNCompare(arg1,"property:",9) == 0)
4890 (void) SetImageProperty(_images,arg1+9,arg2,_exception);
4892 (void) SetImageProperty(_images,arg1,arg2,_exception);
4893 arg2=DestroyString((char *)arg2);
4895 MagickResetIterator(&cli_wand->wand);
4896 arg1=DestroyString((char *)arg1);
4899 if (LocaleCompare("clone",option+1) == 0) {
4904 arg1=AcquireString("-1");
4905 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4906 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
4907 if ( cli_wand->image_list_stack == (Stack *) NULL)
4908 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4909 new_images = (Image *)cli_wand->image_list_stack->data;
4910 if (new_images == (Image *) NULL)
4911 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4912 new_images=CloneImages(new_images,arg1,_exception);
4913 if (new_images == (Image *) NULL)
4914 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4915 AppendImageToList(&_images,new_images);
4919 Informational Operations.
4921 Note that these do not require either a cli-wand or images!
4922 Though currently a cli-wand much be provided regardless.
4924 if (LocaleCompare("version",option+1) == 0)
4926 ListMagickVersion(stdout);
4929 if (LocaleCompare("list",option+1) == 0) {
4931 FUTURE: This 'switch' should really be part of MagickCore
4936 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4938 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4943 case MagickCoderOptions:
4945 (void) ListCoderInfo((FILE *) NULL,_exception);
4948 case MagickColorOptions:
4950 (void) ListColorInfo((FILE *) NULL,_exception);
4953 case MagickConfigureOptions:
4955 (void) ListConfigureInfo((FILE *) NULL,_exception);
4958 case MagickDelegateOptions:
4960 (void) ListDelegateInfo((FILE *) NULL,_exception);
4963 case MagickFontOptions:
4965 (void) ListTypeInfo((FILE *) NULL,_exception);
4968 case MagickFormatOptions:
4969 (void) ListMagickInfo((FILE *) NULL,_exception);
4971 case MagickLocaleOptions:
4972 (void) ListLocaleInfo((FILE *) NULL,_exception);
4974 case MagickLogOptions:
4975 (void) ListLogInfo((FILE *) NULL,_exception);
4977 case MagickMagicOptions:
4978 (void) ListMagicInfo((FILE *) NULL,_exception);
4980 case MagickMimeOptions:
4981 (void) ListMimeInfo((FILE *) NULL,_exception);
4983 case MagickModuleOptions:
4984 (void) ListModuleInfo((FILE *) NULL,_exception);
4986 case MagickPolicyOptions:
4987 (void) ListPolicyInfo((FILE *) NULL,_exception);
4989 case MagickResourceOptions:
4990 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4992 case MagickThresholdOptions:
4993 (void) ListThresholdMaps((FILE *) NULL,_exception);
4996 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
5003 CLIWandException(OptionError,"UnrecognizedOption",option);
5005 DisableMSCWarning(4127)
5006 } while (0); /* break to exit code. */
5009 /* clean up percent escape interpreted strings */
5011 arg1=DestroyString((char *)arg1);
5013 arg2=DestroyString((char *)arg2);
5023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5027 + C L I O p t i o n %
5031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5033 % CLIOption() Processes the given option using the given CLI Magick Wand.
5034 % The option arguments can be variable in number, though at this time no more
5035 % that two is actually used by any option (this may change). Excess options
5036 % are simply ignored.
5038 % If the cli_wand->command pointer is non-null, then it is assumed that the
5039 % option has already been search for up from the CommandOptions[] table in
5040 % "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
5041 % routine will do the lookup instead. The pointer is reset afterward.
5043 % This action allows the caller to lookup and pre-handle any 'special'
5044 % options, (such as implicit reads) before calling this general option
5045 % handler to deal with 'standard' command line options.
5047 % The format of the CLIOption method is:
5049 % void CLIOption(MagickCLI *cli_wand,const char *option, ...)
5051 % A description of each parameter follows:
5053 % o cli_wand: the main CLI Wand to use.
5055 % o option: The special option (with any switch char) to process
5057 % o args: any required arguments for an option (variable number)
5061 % CLIoption(cli_wand,"-read","rose:");
5062 % CLIoption(cli_wand,"-virtual-pixel","transparent");
5063 % CLIoption(cli_wand,"-distort","SRT:","30");
5064 % CLIoption(cli_wand,"-write","rotated_rose.png");
5067 WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
5069 const char /* extracted option args from args */
5076 assert(cli_wand != (MagickCLI *) NULL);
5077 assert(cli_wand->signature == MagickWandSignature);
5078 assert(cli_wand->wand.signature == MagickWandSignature);
5080 do { /* Break Code Block for error handling */
5082 /* get information about option */
5083 if ( cli_wand->command == (const OptionInfo *) NULL )
5084 cli_wand->command = GetCommandOptionInfo(option);
5086 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
5087 option, cli_wand->command->mnemonic );
5089 option_type=(CommandOptionFlags) cli_wand->command->flags;
5091 if ( option_type == UndefinedOptionFlag )
5092 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
5094 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
5096 /* deprecated options */
5097 if ( (option_type & DeprecateOptionFlag) != 0 )
5098 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
5100 /* options that this module does not handle */
5101 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
5102 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
5104 /* Get argument strings from VarArgs
5105 How can you determine if enough arguments was supplied?
5106 What happens if not enough arguments were supplied?
5109 count = (size_t) cli_wand->command->type;
5114 va_start(operands,option);
5118 arg1=(const char *) va_arg(operands, const char *);
5120 arg2=(const char *) va_arg(operands, const char *);
5124 (void) FormatLocaleFile(stderr,
5125 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
5126 option,(long) count,option_type,arg1,arg2);
5131 Call the appropriate option handler
5134 /* FUTURE: this is temporary - get 'settings' to handle distribution of
5135 settings to images attributes,proprieties,artifacts */
5136 if ( cli_wand->wand.images != (Image *) NULL )
5137 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
5138 cli_wand->wand.exception);
5140 if ( (option_type & SettingOptionFlags) != 0 ) {
5141 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
5142 // FUTURE: Sync Specific Settings into Image Properities (not global)
5145 /* Operators that do not need images - read, write, stack, clone */
5146 if ((option_type & NoImageOperatorFlag) != 0)
5147 CLINoImageOperator(cli_wand, option, arg1, arg2);
5149 /* FUTURE: The not a setting part below is a temporary hack due to
5150 * some options being both a Setting and a Simple operator.
5151 * Specifically -monitor, -depth, and -colorspace */
5152 if ( cli_wand->wand.images == (Image *) NULL )
5153 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
5154 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
5155 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
5157 /* Operators which loop of individual images, simply */
5158 if ( (option_type & SimpleOperatorFlag) != 0 &&
5159 cli_wand->wand.images != (Image *) NULL) /* temp hack */
5161 ExceptionInfo *exception=AcquireExceptionInfo();
5162 (void) CLISimpleOperatorImages(cli_wand, option, arg1, arg2,exception);
5163 exception=DestroyExceptionInfo(exception);
5166 /* Operators that work on the image list as a whole */
5167 if ( (option_type & ListOperatorFlag) != 0 )
5168 (void) CLIListOperatorImages(cli_wand, option, arg1, arg2);
5170 DisableMSCWarning(4127)
5171 } while (0); /* end Break code block */
5174 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */