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-2019 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 % https://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/operation.h"
55 #include "MagickWand/wand.h"
56 #include "MagickWand/wandcli.h"
57 #include "MagickWand/wandcli-private.h"
58 #include "MagickCore/composite-private.h"
59 #include "MagickCore/image-private.h"
60 #include "MagickCore/monitor-private.h"
61 #include "MagickCore/pixel-private.h"
62 #include "MagickCore/string-private.h"
63 #include "MagickCore/thread-private.h"
69 MogrifyAlphaColor[] = "#bdbdbd", /* slightly darker gray */
70 MogrifyBackgroundColor[] = "#fff", /* white */
71 MogrifyBorderColor[] = "#dfdfdf"; /* sRGB gray */
76 #define USE_WAND_METHODS 1
77 #define MAX_STACK_DEPTH 32
78 #define UNDEFINED_COMPRESSION_QUALITY 0UL
80 /* FUTURE: why is this default so specific? */
81 #define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
83 /* For Debugging Geometry Input */
84 #define ReportGeometry(flags,info) \
85 (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
86 flags, info.rho, info.sigma, info.xi, info.psi )
89 ** Function to report on the progress of image operations
91 static MagickBooleanType MonitorProgress(const char *text,
92 const MagickOffsetType offset,const MagickSizeType extent,
93 void *wand_unused(client_data))
96 message[MagickPathExtent],
97 tag[MagickPathExtent];
105 magick_unreferenced(client_data);
107 if ((extent <= 1) || (offset < 0) || (offset >= (MagickOffsetType) extent))
109 if ((offset != (MagickOffsetType) (extent-1)) && ((offset % 50) != 0))
111 (void) CopyMagickString(tag,text,MagickPathExtent);
113 if (p != (char *) NULL)
115 (void) FormatLocaleString(message,MagickPathExtent,"Monitor/%s",tag);
116 locale_message=GetLocaleMessage(message);
117 if (locale_message == message)
119 if (p == (char *) NULL)
120 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
121 locale_message,(long) offset,(unsigned long) extent,(long)
122 (100L*offset/(extent-1)));
124 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
125 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
126 (100L*offset/(extent-1)));
127 if (offset == (MagickOffsetType) (extent-1))
128 (void) FormatLocaleFile(stderr,"\n");
129 (void) fflush(stderr);
134 ** GetImageCache() will read an image into a image cache if not already
135 ** present then return the image that is in the cache under that filename.
137 static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
138 ExceptionInfo *exception)
141 key[MagickPathExtent];
152 (void) FormatLocaleString(key,MagickPathExtent,"cache:%s",path);
153 sans_exception=AcquireExceptionInfo();
154 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
155 sans_exception=DestroyExceptionInfo(sans_exception);
156 if (image != (Image *) NULL)
158 read_info=CloneImageInfo(image_info);
159 if (path != (const char *) NULL)
160 (void) CopyMagickString(read_info->filename,path,MagickPathExtent);
161 image=ReadImage(read_info,exception);
162 read_info=DestroyImageInfo(read_info);
163 if (image != (Image *) NULL)
164 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
169 SparseColorOption() parse the complex -sparse-color argument into an
170 an array of floating point values than call SparseColorImage().
171 Argument is a complex mix of floating-point pixel coodinates, and color
172 specifications (or direct floating point numbers). The number of floats
173 needed to represent a color varies depending on the current channel
176 This really should be in MagickCore, so that other API's can make use of it.
178 static Image *SparseColorOption(const Image *image,
179 const SparseColorMethod method,const char *arguments,ExceptionInfo *exception)
182 token[MagickPathExtent];
206 assert(image != (Image *) NULL);
207 assert(image->signature == MagickCoreSignature);
208 if (image->debug != MagickFalse)
209 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
210 assert(exception != (ExceptionInfo *) NULL);
211 assert(exception->signature == MagickCoreSignature);
213 Limit channels according to image
214 add up number of values needed per color.
217 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
219 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
221 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
223 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
224 (image->colorspace == CMYKColorspace))
226 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
227 image->alpha_trait != UndefinedPixelTrait)
231 Read string, to determine number of arguments needed,
237 GetNextToken(p,&p,MagickPathExtent,token);
238 if ( token[0] == ',' ) continue;
239 if ( isalpha((int) token[0]) || token[0] == '#' )
240 x += number_colors; /* color argument found */
242 x++; /* floating point argument */
244 /* control points and color values */
245 if ((x % (2+number_colors)) != 0)
247 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
248 "InvalidArgument","'%s': %s", "sparse-color",
249 "Invalid number of Arguments");
250 return( (Image *) NULL);
255 /* Allocate and fill in the floating point arguments */
256 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
257 sizeof(*sparse_arguments));
258 if (sparse_arguments == (double *) NULL) {
259 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
260 "MemoryAllocationFailed","%s","SparseColorOption");
261 return( (Image *) NULL);
263 (void) memset(sparse_arguments,0,number_arguments*
264 sizeof(*sparse_arguments));
267 while( *p != '\0' && x < number_arguments ) {
269 token[0]=','; while ( token[0] == ',' ) GetNextToken(p,&p,MagickPathExtent,token);
270 if ( token[0] == '\0' ) break;
271 if ( isalpha((int) token[0]) || token[0] == '#' ) {
272 (void) ThrowMagickException(exception,GetMagickModule(),
273 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
274 "Color found, instead of X-coord");
278 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
280 token[0]=','; while ( token[0] == ',' ) GetNextToken(p,&p,MagickPathExtent,token);
281 if ( token[0] == '\0' ) break;
282 if ( isalpha((int) token[0]) || token[0] == '#' ) {
283 (void) ThrowMagickException(exception,GetMagickModule(),
284 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
285 "Color found, instead of Y-coord");
289 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
290 /* color name or function given in string argument */
291 token[0]=','; while ( token[0] == ',' ) GetNextToken(p,&p,MagickPathExtent,token);
292 if ( token[0] == '\0' ) break;
293 if ( isalpha((int) token[0]) || token[0] == '#' ) {
294 /* Color string given */
295 (void) QueryColorCompliance(token,AllCompliance,&color,
297 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
298 sparse_arguments[x++] = QuantumScale*color.red;
299 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
300 sparse_arguments[x++] = QuantumScale*color.green;
301 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
302 sparse_arguments[x++] = QuantumScale*color.blue;
303 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
304 (image->colorspace == CMYKColorspace))
305 sparse_arguments[x++] = QuantumScale*color.black;
306 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
307 image->alpha_trait != UndefinedPixelTrait)
308 sparse_arguments[x++] = QuantumScale*color.alpha;
311 /* Colors given as a set of floating point values - experimental */
312 /* NB: token contains the first floating point value to use! */
313 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
315 while ( token[0] == ',' ) GetNextToken(p,&p,MagickPathExtent,token);
316 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
318 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
319 token[0] = ','; /* used this token - get another */
321 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
323 while ( token[0] == ',' ) GetNextToken(p,&p,MagickPathExtent,token);
324 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
326 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
327 token[0] = ','; /* used this token - get another */
329 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
331 while ( token[0] == ',' ) GetNextToken(p,&p,MagickPathExtent,token);
332 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
334 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
335 token[0] = ','; /* used this token - get another */
337 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
338 (image->colorspace == CMYKColorspace))
340 while ( token[0] == ',' ) GetNextToken(p,&p,MagickPathExtent,token);
341 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
343 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
344 token[0] = ','; /* used this token - get another */
346 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
347 image->alpha_trait != UndefinedPixelTrait)
349 while ( token[0] == ',' ) GetNextToken(p,&p,MagickPathExtent,token);
350 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
352 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
353 token[0] = ','; /* used this token - get another */
357 if (error != MagickFalse)
359 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
360 return((Image *) NULL);
362 if (number_arguments != x)
364 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
365 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
366 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
367 return((Image *) NULL);
369 /* Call the Sparse Color Interpolation function with the parsed arguments */
370 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
372 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
373 return( sparse_image );
377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381 % C L I S e t t i n g O p t i o n I n f o %
385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387 % CLISettingOptionInfo() applies a single settings option into a CLI wand
388 % holding the image_info, draw_info, quantize_info structures that will be
389 % used when processing the images.
391 % These options do no require images to be present in the CLI wand for them
392 % to be able to be set, in which case they will generally be applied to image
393 % that are read in later
395 % Options handled by this function are listed in CommandOptions[] of
396 % "option.c" that is one of "SettingOptionFlags" option flags.
398 % The format of the CLISettingOptionInfo method is:
400 % void CLISettingOptionInfo(MagickCLI *cli_wand,
401 % const char *option, const char *arg1, const char *arg2)
403 % A description of each parameter follows:
405 % o cli_wand: structure holding settings to be applied
407 % o option: The option string to be set
409 % o arg1, arg2: optional argument strings to the operation
410 % arg2 is currently only used by "-limit"
413 WandPrivate void CLISettingOptionInfo(MagickCLI *cli_wand,
414 const char *option,const char *arg1n, const char *arg2n)
417 parse; /* option argument parsing (string to value table lookup) */
419 const char /* percent escaped versions of the args */
423 #define _image_info (cli_wand->wand.image_info)
424 #define _image (cli_wand->wand.images)
425 #define _exception (cli_wand->wand.exception)
426 #define _draw_info (cli_wand->draw_info)
427 #define _quantize_info (cli_wand->quantize_info)
428 #define IfSetOption (*option=='-')
429 #define ArgBoolean IfSetOption ? MagickTrue : MagickFalse
430 #define ArgBooleanNot IfSetOption ? MagickFalse : MagickTrue
431 #define ArgBooleanString (IfSetOption?"true":"false")
432 #define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
434 assert(cli_wand != (MagickCLI *) NULL);
435 assert(cli_wand->signature == MagickWandSignature);
436 assert(cli_wand->wand.signature == MagickWandSignature);
438 if (cli_wand->wand.debug != MagickFalse)
439 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
440 "- Setting Option: %s \"%s\" \"%s\"", option,arg1n,arg2n);
446 #define _process_flags (cli_wand->process_flags)
447 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
448 /* Interpret Percent Escapes in Arguments - using first image */
449 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
450 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
451 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
452 /* Interpret Percent escapes in argument 1 */
453 if (arg1n != (char *) NULL) {
454 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
455 if (arg1 == (char *) NULL) {
456 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
457 arg1=arg1n; /* use the given argument as is */
460 if (arg2n != (char *) NULL) {
461 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
462 if (arg2 == (char *) NULL) {
463 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
464 arg2=arg2n; /* use the given argument as is */
468 #undef _process_flags
476 if (LocaleCompare("adjoin",option+1) == 0)
478 _image_info->adjoin = ArgBoolean;
481 if (LocaleCompare("affine",option+1) == 0)
483 CLIWandWarnReplaced("-draw 'affine ...'");
485 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
487 GetAffineMatrix(&_draw_info->affine);
490 if (LocaleCompare("antialias",option+1) == 0)
492 _image_info->antialias =
493 _draw_info->stroke_antialias =
494 _draw_info->text_antialias = ArgBoolean;
497 if (LocaleCompare("attenuate",option+1) == 0)
499 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
500 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
501 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
504 if (LocaleCompare("authenticate",option+1) == 0)
506 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
509 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
513 if (LocaleCompare("background",option+1) == 0)
515 /* FUTURE: both _image_info attribute & ImageOption in use!
516 _image_info only used directly for generating new images.
517 SyncImageSettings() used to set per-image attribute.
519 FUTURE: if _image_info->background_color is not set then
520 we should fall back to per-image background_color
522 At this time -background will 'wipe out' the per-image
525 Better error handling of QueryColorCompliance() needed.
527 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
528 (void) QueryColorCompliance(ArgOption(MogrifyBackgroundColor),AllCompliance,
529 &_image_info->background_color,_exception);
532 if (LocaleCompare("bias",option+1) == 0)
534 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
535 as it is actually rarely used except in direct convolve operations
536 Usage outside a direct convolve operation is actally non-sensible!
538 SyncImageSettings() used to set per-image attribute.
540 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
541 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
542 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
545 if (LocaleCompare("black-point-compensation",option+1) == 0)
547 /* Used as a image chromaticity setting
548 SyncImageSettings() used to set per-image attribute.
550 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
553 if (LocaleCompare("blue-primary",option+1) == 0)
555 /* Image chromaticity X,Y NB: Y=X if Y not defined
556 Used by many coders including PNG
557 SyncImageSettings() used to set per-image attribute.
559 arg1=ArgOption("0.0");
560 if (IsGeometry(arg1) == MagickFalse)
561 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
562 (void) SetImageOption(_image_info,option+1,arg1);
565 if (LocaleCompare("bordercolor",option+1) == 0)
567 /* FUTURE: both _image_info attribute & ImageOption in use!
568 SyncImageSettings() used to set per-image attribute.
569 Better error checking of QueryColorCompliance().
573 (void) SetImageOption(_image_info,option+1,arg1);
574 (void) QueryColorCompliance(arg1,AllCompliance,
575 &_image_info->border_color,_exception);
576 (void) QueryColorCompliance(arg1,AllCompliance,
577 &_draw_info->border_color,_exception);
580 (void) DeleteImageOption(_image_info,option+1);
581 (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
582 &_image_info->border_color,_exception);
583 (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
584 &_draw_info->border_color,_exception);
587 if (LocaleCompare("box",option+1) == 0)
589 CLIWandWarnReplaced("-undercolor");
590 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
593 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
597 if (LocaleCompare("cache",option+1) == 0)
602 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
603 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
604 limit=MagickResourceInfinity;
605 if (LocaleCompare("unlimited",arg1) != 0)
606 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
607 (void) SetMagickResourceLimit(MemoryResource,limit);
608 (void) SetMagickResourceLimit(MapResource,2*limit);
611 if (LocaleCompare("caption",option+1) == 0)
613 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
616 if (LocaleCompare("colorspace",option+1) == 0)
618 /* Setting used for new images via AquireImage()
619 But also used as a SimpleImageOperator
620 Undefined colorspace means don't modify images on
621 read or as a operation */
622 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,
623 ArgOption("undefined"));
625 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
627 _image_info->colorspace=(ColorspaceType) parse;
630 if (LocaleCompare("comment",option+1) == 0)
632 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
635 if (LocaleCompare("compose",option+1) == 0)
637 /* FUTURE: _image_info should be used,
638 SyncImageSettings() used to set per-image attribute. - REMOVE
640 This setting should NOT be used to set image 'compose'
641 "-layer" operators shoud use _image_info if defined otherwise
642 they should use a per-image compose setting.
644 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
645 ArgOption("undefined"));
647 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
649 _image_info->compose=(CompositeOperator) parse;
650 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
653 if (LocaleCompare("compress",option+1) == 0)
655 /* FUTURE: What should be used? _image_info or ImageOption ???
656 The former is more efficent, but Crisy prefers the latter!
657 SyncImageSettings() used to set per-image attribute.
659 The coders appears to use _image_info, not Image_Option
660 however the image attribute (for save) is set from the
663 Note that "undefined" is a different setting to "none".
665 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
666 ArgOption("undefined"));
668 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
670 _image_info->compression=(CompressionType) parse;
671 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
674 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
678 if (LocaleCompare("debug",option+1) == 0)
680 /* SyncImageSettings() used to set per-image attribute. */
681 arg1=ArgOption("none");
682 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
684 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
686 (void) SetLogEventMask(arg1);
687 _image_info->debug=IsEventLogging(); /* extract logging*/
688 cli_wand->wand.debug=IsEventLogging();
691 if (LocaleCompare("define",option+1) == 0)
693 if (LocaleNCompare(arg1,"registry:",9) == 0)
696 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
698 (void) DeleteImageRegistry(arg1+9);
701 /* DefineImageOption() equals SetImageOption() but with '=' */
703 (void) DefineImageOption(_image_info,arg1);
704 else if (DeleteImageOption(_image_info,arg1) == MagickFalse)
705 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
708 if (LocaleCompare("delay",option+1) == 0)
710 /* Only used for new images via AcquireImage()
711 FUTURE: Option should also be used for "-morph" (color morphing)
714 if (IsGeometry(arg1) == MagickFalse)
715 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
716 (void) SetImageOption(_image_info,option+1,arg1);
719 if (LocaleCompare("density",option+1) == 0)
721 /* FUTURE: strings used in _image_info attr and _draw_info!
722 Basically as density can be in a XxY form!
724 SyncImageSettings() used to set per-image attribute.
726 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
727 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
728 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
729 (void) CloneString(&_image_info->density,ArgOption(NULL));
730 (void) CloneString(&_draw_info->density,_image_info->density);
733 if (LocaleCompare("depth",option+1) == 0)
735 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
736 SyncImageSettings() used to set per-image attribute.
738 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
739 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
740 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
741 :MAGICKCORE_QUANTUM_DEPTH;
744 if (LocaleCompare("direction",option+1) == 0)
746 /* Image Option is only used to set _draw_info */
747 arg1=ArgOption("undefined");
748 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
750 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
752 _draw_info->direction=(DirectionType) parse;
753 (void) SetImageOption(_image_info,option+1,arg1);
756 if (LocaleCompare("display",option+1) == 0)
758 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
759 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
762 if (LocaleCompare("dispose",option+1) == 0)
764 /* only used in setting new images */
765 arg1=ArgOption("undefined");
766 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
768 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
770 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
773 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
775 /* FUTURE: this is only used by CompareImages() which is used
776 only by the "compare" CLI program at this time. */
777 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
778 if (IsGeometry(arg1) == MagickFalse)
779 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
780 (void) SetImageOption(_image_info,option+1,arg1);
783 if (LocaleCompare("dither",option+1) == 0)
785 /* _image_info attr (on/off), _quantize_info attr (on/off)
786 but also ImageInfo and _quantize_info method!
787 FUTURE: merge the duality of the dithering options
789 _image_info->dither = ArgBoolean;
790 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
791 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
792 MagickDitherOptions,MagickFalse,ArgOption("none"));
793 if (_quantize_info->dither_method == NoDitherMethod)
794 _image_info->dither = MagickFalse;
797 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
801 if (LocaleCompare("encoding",option+1) == 0)
803 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
804 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
807 if (LocaleCompare("endian",option+1) == 0)
809 /* Both _image_info attr and ImageInfo */
810 arg1 = ArgOption("undefined");
811 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
813 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
815 /* FUTURE: check alloc/free of endian string! - remove? */
816 _image_info->endian=(EndianType) (*arg1);
817 (void) SetImageOption(_image_info,option+1,arg1);
820 if (LocaleCompare("extract",option+1) == 0)
822 (void) CloneString(&_image_info->extract,ArgOption(NULL));
825 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
829 if (LocaleCompare("family",option+1) == 0)
831 (void) CloneString(&_draw_info->family,ArgOption(NULL));
834 if (LocaleCompare("features",option+1) == 0)
836 (void) SetImageOption(_image_info,"identify:features",
839 (void) SetImageArtifact(_image,"verbose","true");
842 if (LocaleCompare("fill",option+1) == 0)
844 /* Set "fill" OR "fill-pattern" in _draw_info
845 The original fill color is preserved if a fill-pattern is given.
846 That way it does not effect other operations that directly using
847 the fill color and, can be retored using "+tile".
858 arg1 = ArgOption("none"); /* +fill turns it off! */
859 (void) SetImageOption(_image_info,option+1,arg1);
860 if (_draw_info->fill_pattern != (Image *) NULL)
861 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
863 /* is it a color or a image? -- ignore exceptions */
864 sans=AcquireExceptionInfo();
865 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
866 sans=DestroyExceptionInfo(sans);
868 if (status == MagickFalse)
869 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
871 _draw_info->fill=color;
874 if (LocaleCompare("filter",option+1) == 0)
876 /* SyncImageSettings() used to set per-image attribute. */
877 arg1 = ArgOption("undefined");
878 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
880 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
882 (void) SetImageOption(_image_info,option+1,arg1);
885 if (LocaleCompare("font",option+1) == 0)
887 (void) CloneString(&_draw_info->font,ArgOption(NULL));
888 (void) CloneString(&_image_info->font,_draw_info->font);
891 if (LocaleCompare("format",option+1) == 0)
893 /* FUTURE: why the ping test, you could set ping after this! */
898 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
899 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
900 _image_info->ping=MagickFalse;
902 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
905 if (LocaleCompare("fuzz",option+1) == 0)
907 /* Option used to set image fuzz! unless blank canvas (from color)
908 Image attribute used for color compare operations
909 SyncImageSettings() used to set per-image attribute.
911 FUTURE: Can't find anything else using _image_info->fuzz directly!
912 convert structure attribute to 'option' string
915 if (IsGeometry(arg1) == MagickFalse)
916 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
917 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
919 (void) SetImageOption(_image_info,option+1,arg1);
922 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
926 if (LocaleCompare("gravity",option+1) == 0)
928 /* SyncImageSettings() used to set per-image attribute. */
929 arg1 = ArgOption("none");
930 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
932 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
934 _draw_info->gravity=(GravityType) parse;
935 (void) SetImageOption(_image_info,option+1,arg1);
938 if (LocaleCompare("green-primary",option+1) == 0)
940 /* Image chromaticity X,Y NB: Y=X if Y not defined
941 SyncImageSettings() used to set per-image attribute.
942 Used directly by many coders
944 arg1=ArgOption("0.0");
945 if (IsGeometry(arg1) == MagickFalse)
946 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
947 (void) SetImageOption(_image_info,option+1,arg1);
950 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
954 if (LocaleCompare("highlight-color",option+1) == 0)
956 /* FUTURE: this is only used by CompareImages() which is used
957 only by the "compare" CLI program at this time. */
958 (void) SetImageOption(_image_info,"compare:highlight-color",
962 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
966 if (LocaleCompare("intensity",option+1) == 0)
968 arg1 = ArgOption("undefined");
969 parse = ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,
972 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityType",
974 (void) SetImageOption(_image_info,option+1,arg1);
977 if (LocaleCompare("intent",option+1) == 0)
979 /* Only used by coders: MIFF, MPC, BMP, PNG
980 and for image profile call to AcquireTransformThreadSet()
981 SyncImageSettings() used to set per-image attribute.
983 arg1 = ArgOption("undefined");
984 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
986 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
988 (void) SetImageOption(_image_info,option+1,arg1);
991 if (LocaleCompare("interlace",option+1) == 0)
993 /* _image_info is directly used by coders (so why an image setting?)
994 SyncImageSettings() used to set per-image attribute.
996 arg1 = ArgOption("undefined");
997 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
999 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
1001 _image_info->interlace=(InterlaceType) parse;
1002 (void) SetImageOption(_image_info,option+1,arg1);
1005 if (LocaleCompare("interline-spacing",option+1) == 0)
1007 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
1008 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1009 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1010 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
1014 if (LocaleCompare("interpolate",option+1) == 0)
1016 /* SyncImageSettings() used to set per-image attribute. */
1017 arg1 = ArgOption("undefined");
1018 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1020 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1022 (void) SetImageOption(_image_info,option+1,arg1);
1025 if (LocaleCompare("interword-spacing",option+1) == 0)
1027 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
1028 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1029 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1030 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
1033 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1037 if (LocaleCompare("kerning",option+1) == 0)
1039 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
1040 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1041 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1042 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
1045 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1049 if (LocaleCompare("label",option+1) == 0)
1051 /* only used for new images - not in SyncImageOptions() */
1052 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1055 if (LocaleCompare("limit",option+1) == 0)
1060 limit=MagickResourceInfinity;
1061 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1063 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1065 if (LocaleCompare("unlimited",arg2) != 0)
1066 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1067 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1070 if (LocaleCompare("log",option+1) == 0)
1073 if ((strchr(arg1,'%') == (char *) NULL))
1074 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1075 (void) SetLogFormat(arg1);
1079 if (LocaleCompare("lowlight-color",option+1) == 0)
1081 /* FUTURE: this is only used by CompareImages() which is used
1082 only by the "compare" CLI program at this time. */
1083 (void) SetImageOption(_image_info,"compare:lowlight-color",
1087 if (LocaleCompare("loop",option+1) == 0)
1089 /* SyncImageSettings() used to set per-image attribute. */
1090 arg1=ArgOption("0");
1091 if (IsGeometry(arg1) == MagickFalse)
1092 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1093 (void) SetImageOption(_image_info,option+1,arg1);
1096 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1100 if (LocaleCompare("mattecolor",option+1) == 0)
1102 /* SyncImageSettings() used to set per-image attribute. */
1103 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1104 (void) QueryColorCompliance(ArgOption(MogrifyAlphaColor),
1105 AllCompliance,&_image_info->matte_color,_exception);
1108 if (LocaleCompare("metric",option+1) == 0)
1110 /* FUTURE: this is only used by CompareImages() which is used
1111 only by the "compare" CLI program at this time. */
1112 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1114 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1116 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1119 if (LocaleCompare("moments",option+1) == 0)
1121 (void) SetImageOption(_image_info,"identify:moments",
1124 (void) SetImageArtifact(_image,"verbose","true");
1127 if (LocaleCompare("monitor",option+1) == 0)
1129 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
1130 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
1133 if (LocaleCompare("monochrome",option+1) == 0)
1135 /* Setting (used by some input coders!) -- why?
1136 Warning: This is also Special '-type' SimpleOperator
1138 _image_info->monochrome= ArgBoolean;
1141 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1145 if (LocaleCompare("orient",option+1) == 0)
1147 /* Is not used when defining for new images.
1148 This makes it more of a 'operation' than a setting
1149 FUTURE: make set meta-data operator instead.
1150 SyncImageSettings() used to set per-image attribute.
1152 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1153 ArgOption("undefined"));
1155 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1157 _image_info->orientation=(OrientationType)parse;
1158 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1161 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1165 if (LocaleCompare("page",option+1) == 0)
1167 /* Only used for new images and image generators.
1168 SyncImageSettings() used to set per-image attribute. ?????
1169 That last is WRONG!!!!
1170 FUTURE: adjust named 'page' sizes according density
1174 page[MagickPathExtent];
1187 (void) DeleteImageOption(_image_info,option+1);
1188 (void) CloneString(&_image_info->page,(char *) NULL);
1191 (void) memset(&geometry,0,sizeof(geometry));
1192 image_option=GetImageOption(_image_info,"page");
1193 if (image_option != (const char *) NULL)
1194 flags=ParseAbsoluteGeometry(image_option,&geometry);
1195 canonical_page=GetPageGeometry(arg1);
1196 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1197 canonical_page=DestroyString(canonical_page);
1198 (void) FormatLocaleString(page,MagickPathExtent,"%lux%lu",
1199 (unsigned long) geometry.width,(unsigned long) geometry.height);
1200 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1201 (void) FormatLocaleString(page,MagickPathExtent,"%lux%lu%+ld%+ld",
1202 (unsigned long) geometry.width,(unsigned long) geometry.height,
1203 (long) geometry.x,(long) geometry.y);
1204 (void) SetImageOption(_image_info,option+1,page);
1205 (void) CloneString(&_image_info->page,page);
1208 if (LocaleCompare("ping",option+1) == 0)
1210 _image_info->ping = ArgBoolean;
1213 if (LocaleCompare("pointsize",option+1) == 0)
1216 if (IsGeometry(arg1) == MagickFalse)
1217 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1218 _image_info->pointsize =
1219 _draw_info->pointsize =
1220 StringToDouble(arg1,(char **) NULL);
1223 _image_info->pointsize=0.0; /* unset pointsize */
1224 _draw_info->pointsize=12.0;
1228 if (LocaleCompare("precision",option+1) == 0)
1230 arg1=ArgOption("-1");
1231 if (IsGeometry(arg1) == MagickFalse)
1232 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1233 (void) SetMagickPrecision(StringToInteger(arg1));
1236 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1240 if (LocaleCompare("quality",option+1) == 0)
1242 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
1243 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1244 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1245 : UNDEFINED_COMPRESSION_QUALITY;
1246 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
1249 if (LocaleCompare("quantize",option+1) == 0)
1251 /* Just a set direct in _quantize_info */
1252 arg1=ArgOption("undefined");
1253 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1255 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1257 _quantize_info->colorspace=(ColorspaceType)parse;
1260 if (LocaleCompare("quiet",option+1) == 0)
1262 /* FUTURE: if two -quiet is performed you can not do +quiet!
1263 This needs to be checked over thoughly.
1265 static WarningHandler
1266 warning_handler = (WarningHandler) NULL;
1269 tmp = SetWarningHandler((WarningHandler) NULL);
1271 if ( tmp != (WarningHandler) NULL)
1272 warning_handler = tmp; /* remember the old handler */
1273 if (!IfSetOption) /* set the old handler */
1274 warning_handler=SetWarningHandler(warning_handler);
1277 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1281 if (LocaleCompare("red-primary",option+1) == 0)
1283 /* Image chromaticity X,Y NB: Y=X if Y not defined
1285 SyncImageSettings() used to set per-image attribute.
1287 arg1=ArgOption("0.0");
1288 if (IsGeometry(arg1) == MagickFalse)
1289 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1290 (void) SetImageOption(_image_info,option+1,arg1);
1293 if (LocaleCompare("regard-warnings",option+1) == 0)
1294 /* FUTURE: to be replaced by a 'fatal-level' type setting */
1296 if (LocaleCompare("render",option+1) == 0)
1298 /* _draw_info only setting */
1299 _draw_info->render= ArgBooleanNot;
1302 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1304 /* link image and setting stacks - option is itself saved on stack! */
1305 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1308 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1312 if (LocaleCompare("sampling-factor",option+1) == 0)
1314 /* FUTURE: should be converted to jpeg:sampling_factor */
1315 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
1316 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1317 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
1320 if (LocaleCompare("scene",option+1) == 0)
1322 /* SyncImageSettings() used to set this as a per-image attribute.
1325 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
1326 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1327 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1328 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
1331 if (LocaleCompare("seed",option+1) == 0)
1333 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
1334 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1336 IfSetOption ? (unsigned long) StringToUnsignedLong(arg1)
1337 : (unsigned long) time((time_t *) NULL) );
1340 if (LocaleCompare("size",option+1) == 0)
1342 /* FUTURE: string in _image_info -- convert to Option ???
1343 Look at the special handling for "size" in SetImageOption()
1345 (void) CloneString(&_image_info->size,ArgOption(NULL));
1348 if (LocaleCompare("stretch",option+1) == 0)
1350 arg1=ArgOption("undefined");
1351 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1353 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1355 _draw_info->stretch=(StretchType) parse;
1358 if (LocaleCompare("stroke",option+1) == 0)
1360 /* set stroke color OR stroke-pattern
1361 UPDATE: ensure stroke color is not destroyed is a pattern
1362 is given. Just in case the color is also used for other purposes.
1373 arg1 = ArgOption("none"); /* +fill turns it off! */
1374 (void) SetImageOption(_image_info,option+1,arg1);
1375 if (_draw_info->stroke_pattern != (Image *) NULL)
1376 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
1378 /* is it a color or a image? -- ignore exceptions */
1379 sans=AcquireExceptionInfo();
1380 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
1381 sans=DestroyExceptionInfo(sans);
1383 if (status == MagickFalse)
1384 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
1386 _draw_info->stroke=color;
1389 if (LocaleCompare("strokewidth",option+1) == 0)
1391 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
1392 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1393 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1394 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1398 if (LocaleCompare("style",option+1) == 0)
1400 arg1=ArgOption("undefined");
1401 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1403 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1405 _draw_info->style=(StyleType) parse;
1409 if (LocaleCompare("subimage-search",option+1) == 0)
1411 /* FUTURE: this is only used by CompareImages() which is used
1412 only by the "compare" CLI program at this time. */
1413 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1417 if (LocaleCompare("synchronize",option+1) == 0)
1419 /* FUTURE: syncronize to storage - but what does that mean? */
1420 _image_info->synchronize = ArgBoolean;
1423 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1427 if (LocaleCompare("taint",option+1) == 0)
1429 /* SyncImageSettings() used to set per-image attribute. */
1430 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1433 if (LocaleCompare("texture",option+1) == 0)
1435 /* Note: arguments do not have percent escapes expanded */
1436 /* FUTURE: move _image_info string to option splay-tree
1437 Other than "montage" what uses "texture" ????
1439 (void) CloneString(&_image_info->texture,ArgOption(NULL));
1442 if (LocaleCompare("tile",option+1) == 0)
1444 /* Note: arguments do not have percent escapes expanded */
1445 _draw_info->fill_pattern=IfSetOption
1446 ?GetImageCache(_image_info,arg1,_exception)
1447 :DestroyImage(_draw_info->fill_pattern);
1450 if (LocaleCompare("tile-offset",option+1) == 0)
1452 /* SyncImageSettings() used to set per-image attribute. ??? */
1453 arg1=ArgOption("0");
1454 if (IsGeometry(arg1) == MagickFalse)
1455 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1456 (void) SetImageOption(_image_info,option+1,arg1);
1459 if (LocaleCompare("transparent-color",option+1) == 0)
1461 /* FUTURE: both _image_info attribute & ImageOption in use!
1462 _image_info only used for generating new images.
1463 SyncImageSettings() used to set per-image attribute.
1465 Note that +transparent-color, means fall-back to image
1466 attribute so ImageOption is deleted, not set to a default.
1468 if (IfSetOption && (IsGeometry(arg1) == MagickFalse))
1469 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1470 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1471 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1472 &_image_info->transparent_color,_exception);
1475 if (LocaleCompare("treedepth",option+1) == 0)
1477 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1478 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1481 if (LocaleCompare("type",option+1) == 0)
1483 /* SyncImageSettings() used to set per-image attribute. */
1484 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1485 ArgOption("undefined"));
1487 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1489 _image_info->type=(ImageType) parse;
1490 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1493 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1497 if (LocaleCompare("undercolor",option+1) == 0)
1499 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1500 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1501 &_draw_info->undercolor,_exception);
1504 if (LocaleCompare("units",option+1) == 0)
1506 /* SyncImageSettings() used to set per-image attribute.
1507 Should this effect _draw_info X and Y resolution?
1508 FUTURE: this probably should be part of the density setting
1510 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1511 ArgOption("undefined"));
1513 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1515 _image_info->units=(ResolutionType) parse;
1516 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1519 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1523 if (LocaleCompare("verbose",option+1) == 0)
1525 /* FUTURE: Remember all options become image artifacts
1526 _image_info->verbose is only used by coders.
1528 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1529 _image_info->verbose= ArgBoolean;
1530 _image_info->ping=MagickFalse; /* verbose can't be a ping */
1533 if (LocaleCompare("virtual-pixel",option+1) == 0)
1535 /* SyncImageSettings() used to set per-image attribute.
1536 This is VERY deep in the image caching structure.
1538 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1539 ArgOption("undefined"));
1541 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1543 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1546 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1550 if (LocaleCompare("weight",option+1) == 0)
1555 weight=ParseCommandOption(MagickWeightOptions,MagickFalse,arg1);
1557 weight=(ssize_t) StringToUnsignedLong(arg1);
1558 _draw_info->weight=(size_t) weight;
1561 if (LocaleCompare("white-point",option+1) == 0)
1563 /* Used as a image chromaticity setting
1564 SyncImageSettings() used to set per-image attribute.
1566 arg1=ArgOption("0.0");
1567 if (IsGeometry(arg1) == MagickFalse)
1568 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1569 (void) SetImageOption(_image_info,option+1,arg1);
1572 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1575 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1578 /* clean up percent escape interpreted strings */
1579 if ((arg1 && arg1n) && (arg1 != arg1n ))
1580 arg1=DestroyString((char *) arg1);
1581 if ((arg2 && arg2n) && (arg2 != arg2n ))
1582 arg2=DestroyString((char *) arg2);
1587 #undef _quantize_info
1590 #undef ArgBooleanNot
1591 #undef ArgBooleanString
1598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1602 + C L I S i m p l e O p e r a t o r I m a g e s %
1606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1608 % CLISimpleOperatorImages() applys one simple image operation given to all
1609 % the images in the CLI wand, using any per-image or global settings that was
1610 % previously saved in the CLI wand.
1612 % It is assumed that any such settings are up-to-date.
1614 % The format of the WandSimpleOperatorImages method is:
1616 % MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,const char *option,
1617 % const char *arg1, const char *arg2,ExceptionInfo *exception)
1619 % A description of each parameter follows:
1621 % o cli_wand: structure holding settings and images to be operated on
1623 % o option: The option string for the operation
1625 % o arg1, arg2: optional argument strings to the operation
1630 CLISimpleOperatorImage() is an Internal subrountine to apply one simple
1631 image operation to the current image pointed to by the CLI wand.
1633 The image in the list may be modified in three different ways...
1634 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1635 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1636 * one image replace by a list of images (-separate and -crop only!)
1638 In each case the result replaces the single original image in the list, as
1639 well as the pointer to the modified image (last image added if replaced by a
1640 list of images) is returned.
1642 As the image pointed to may be replaced, the first image in the list may
1643 also change. GetFirstImageInList() should be used by caller if they wish
1644 return the Image pointer to the first image in list.
1646 static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
1647 const char *option, const char *arg1n, const char *arg2n,
1648 ExceptionInfo *exception)
1665 const char /* percent escaped versions of the args */
1669 #define _image_info (cli_wand->wand.image_info)
1670 #define _image (cli_wand->wand.images)
1671 #define _exception (cli_wand->wand.exception)
1672 #define _draw_info (cli_wand->draw_info)
1673 #define _quantize_info (cli_wand->quantize_info)
1674 #define _process_flags (cli_wand->process_flags)
1675 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
1676 #define IfNormalOp (*option=='-')
1677 #define IfPlusOp (*option!='-')
1678 #define IsNormalOp IfNormalOp ? MagickTrue : MagickFalse
1679 #define IsPlusOp IfNormalOp ? MagickFalse : MagickTrue
1681 assert(cli_wand != (MagickCLI *) NULL);
1682 assert(cli_wand->signature == MagickWandSignature);
1683 assert(cli_wand->wand.signature == MagickWandSignature);
1684 assert(_image != (Image *) NULL); /* an image must be present */
1685 if (cli_wand->wand.debug != MagickFalse)
1686 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
1691 /* Interpret Percent Escapes in Arguments - using first image */
1692 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1693 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1694 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1695 /* Interpret Percent escapes in argument 1 */
1696 if (arg1n != (char *) NULL) {
1697 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1698 if (arg1 == (char *) NULL) {
1699 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1700 arg1=arg1n; /* use the given argument as is */
1703 if (arg2n != (char *) NULL) {
1704 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1705 if (arg2 == (char *) NULL) {
1706 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1707 arg2=arg2n; /* use the given argument as is */
1711 #undef _process_flags
1715 (void) FormatLocaleFile(stderr,
1716 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1719 new_image = (Image *) NULL; /* the replacement image, if not null at end */
1720 SetGeometryInfo(&geometry_info);
1722 switch (*(option+1))
1726 if (LocaleCompare("adaptive-blur",option+1) == 0)
1728 flags=ParseGeometry(arg1,&geometry_info);
1729 if ((flags & (RhoValue|SigmaValue)) == 0)
1730 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1731 if ((flags & SigmaValue) == 0)
1732 geometry_info.sigma=1.0;
1733 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1734 geometry_info.sigma,_exception);
1737 if (LocaleCompare("adaptive-resize",option+1) == 0)
1739 /* FUTURE: Roll into a resize special operator */
1740 if (IsGeometry(arg1) == MagickFalse)
1741 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1742 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1743 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1747 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
1749 flags=ParseGeometry(arg1,&geometry_info);
1750 if ((flags & (RhoValue|SigmaValue)) == 0)
1751 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1752 if ((flags & SigmaValue) == 0)
1753 geometry_info.sigma=1.0;
1754 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1755 geometry_info.sigma,_exception);
1758 if (LocaleCompare("alpha",option+1) == 0)
1760 parse=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,arg1);
1762 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelOption",
1764 (void) SetImageAlphaChannel(_image,(AlphaChannelOption) parse,
1768 if (LocaleCompare("annotate",option+1) == 0)
1771 geometry[MagickPathExtent];
1773 SetGeometryInfo(&geometry_info);
1774 flags=ParseGeometry(arg1,&geometry_info);
1776 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1777 if ((flags & SigmaValue) == 0)
1778 geometry_info.sigma=geometry_info.rho;
1779 (void) CloneString(&_draw_info->text,arg2);
1780 (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
1781 geometry_info.xi,geometry_info.psi);
1782 (void) CloneString(&_draw_info->geometry,geometry);
1783 _draw_info->affine.sx=cos(DegreesToRadians(
1784 fmod(geometry_info.rho,360.0)));
1785 _draw_info->affine.rx=sin(DegreesToRadians(
1786 fmod(geometry_info.rho,360.0)));
1787 _draw_info->affine.ry=(-sin(DegreesToRadians(
1788 fmod(geometry_info.sigma,360.0))));
1789 _draw_info->affine.sy=cos(DegreesToRadians(
1790 fmod(geometry_info.sigma,360.0)));
1791 (void) AnnotateImage(_image,_draw_info,_exception);
1792 GetAffineMatrix(&_draw_info->affine);
1795 if (LocaleCompare("auto-gamma",option+1) == 0)
1797 (void) AutoGammaImage(_image,_exception);
1800 if (LocaleCompare("auto-level",option+1) == 0)
1802 (void) AutoLevelImage(_image,_exception);
1805 if (LocaleCompare("auto-orient",option+1) == 0)
1807 new_image=AutoOrientImage(_image,_image->orientation,_exception);
1810 if (LocaleCompare("auto-threshold",option+1) == 0)
1815 method=(AutoThresholdMethod) ParseCommandOption(
1816 MagickAutoThresholdOptions,MagickFalse,arg1);
1817 (void) AutoThresholdImage(_image,method,_exception);
1820 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1824 if (LocaleCompare("black-threshold",option+1) == 0)
1826 if (IsGeometry(arg1) == MagickFalse)
1827 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1828 (void) BlackThresholdImage(_image,arg1,_exception);
1831 if (LocaleCompare("blue-shift",option+1) == 0)
1833 geometry_info.rho=1.5;
1835 flags=ParseGeometry(arg1,&geometry_info);
1836 if ((flags & RhoValue) == 0)
1837 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1839 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
1842 if (LocaleCompare("blur",option+1) == 0)
1844 flags=ParseGeometry(arg1,&geometry_info);
1845 if ((flags & (RhoValue|SigmaValue)) == 0)
1846 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1847 if ((flags & SigmaValue) == 0)
1848 geometry_info.sigma=1.0;
1849 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1853 if (LocaleCompare("border",option+1) == 0)
1861 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
1862 if ((flags & (WidthValue | HeightValue)) == 0)
1863 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1864 compose=OverCompositeOp;
1865 value=GetImageOption(_image_info,"compose");
1866 if (value != (const char *) NULL)
1867 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
1869 new_image=BorderImage(_image,&geometry,compose,_exception);
1872 if (LocaleCompare("brightness-contrast",option+1) == 0)
1884 flags=ParseGeometry(arg1,&geometry_info);
1885 if ((flags & RhoValue) == 0)
1886 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1887 brightness=geometry_info.rho;
1889 if ((flags & SigmaValue) != 0)
1890 contrast=geometry_info.sigma;
1891 (void) BrightnessContrastImage(_image,brightness,contrast,
1895 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1899 if (LocaleCompare("canny",option+1) == 0)
1901 flags=ParseGeometry(arg1,&geometry_info);
1902 if ((flags & (RhoValue|SigmaValue)) == 0)
1903 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1904 if ((flags & SigmaValue) == 0)
1905 geometry_info.sigma=1.0;
1906 if ((flags & XiValue) == 0)
1907 geometry_info.xi=10;
1908 if ((flags & PsiValue) == 0)
1909 geometry_info.psi=30;
1910 if ((flags & PercentValue) != 0)
1912 geometry_info.xi/=100.0;
1913 geometry_info.psi/=100.0;
1915 new_image=CannyEdgeImage(_image,geometry_info.rho,geometry_info.sigma,
1916 geometry_info.xi,geometry_info.psi,_exception);
1919 if (LocaleCompare("cdl",option+1) == 0)
1922 *color_correction_collection; /* Note: arguments do not have percent escapes expanded */
1925 Color correct with a color decision list.
1927 color_correction_collection=FileToString(arg1,~0UL,_exception);
1928 if (color_correction_collection == (char *) NULL)
1930 (void) ColorDecisionListImage(_image,color_correction_collection,
1934 if (LocaleCompare("channel",option+1) == 0)
1938 (void) SetPixelChannelMask(_image,DefaultChannels);
1941 parse=ParseChannelOption(arg1);
1943 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",option,
1945 (void) SetPixelChannelMask(_image,(ChannelType) parse);
1948 if (LocaleCompare("charcoal",option+1) == 0)
1950 flags=ParseGeometry(arg1,&geometry_info);
1951 if ((flags & (RhoValue|SigmaValue)) == 0)
1952 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1953 if ((flags & SigmaValue) == 0)
1954 geometry_info.sigma=1.0;
1955 if ((flags & XiValue) == 0)
1956 geometry_info.xi=1.0;
1957 new_image=CharcoalImage(_image,geometry_info.rho,geometry_info.sigma,
1961 if (LocaleCompare("chop",option+1) == 0)
1963 if (IsGeometry(arg1) == MagickFalse)
1964 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1965 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1966 new_image=ChopImage(_image,&geometry,_exception);
1969 if (LocaleCompare("clahe",option+1) == 0)
1971 if (IsGeometry(arg1) == MagickFalse)
1972 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1973 flags=ParseGeometry(arg1,&geometry_info);
1974 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
1975 (void) CLAHEImage(_image,geometry.width,geometry.height,
1976 (size_t) geometry.x,geometry_info.psi,_exception);
1979 if (LocaleCompare("clamp",option+1) == 0)
1981 (void) ClampImage(_image,_exception);
1984 if (LocaleCompare("clip",option+1) == 0)
1987 (void) ClipImage(_image,_exception);
1988 else /* "+mask" remove the write mask */
1989 (void) SetImageMask(_image,WritePixelMask,(Image *) NULL,
1993 if (LocaleCompare("clip-mask",option+1) == 0)
1999 /* use "+clip-mask" Remove the write mask for -clip-path */
2000 (void) SetImageMask(_image,WritePixelMask,(Image *) NULL,_exception);
2003 clip_mask=GetImageCache(_image_info,arg1,_exception);
2004 if (clip_mask == (Image *) NULL)
2006 (void) SetImageMask(_image,WritePixelMask,clip_mask,_exception);
2007 clip_mask=DestroyImage(clip_mask);
2010 if (LocaleCompare("clip-path",option+1) == 0)
2012 (void) ClipImagePath(_image,arg1,IsNormalOp,_exception);
2013 /* Note: Use "+clip-mask" remove the write mask added */
2016 if (LocaleCompare("colorize",option+1) == 0)
2018 if (IsGeometry(arg1) == MagickFalse)
2019 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2020 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
2023 if (LocaleCompare("color-matrix",option+1) == 0)
2028 kernel=AcquireKernelInfo(arg1,exception);
2029 if (kernel == (KernelInfo *) NULL)
2030 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2031 new_image=ColorMatrixImage(_image,kernel,_exception);
2032 kernel=DestroyKernelInfo(kernel);
2035 if (LocaleCompare("colors",option+1) == 0)
2037 /* Reduce the number of colors in the image.
2038 FUTURE: also provide 'plus version with image 'color counts'
2040 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2041 if (_quantize_info->number_colors == 0)
2042 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2043 if ((_image->storage_class == DirectClass) ||
2044 _image->colors > _quantize_info->number_colors)
2045 (void) QuantizeImage(_quantize_info,_image,_exception);
2047 (void) CompressImageColormap(_image,_exception);
2050 if (LocaleCompare("colorspace",option+1) == 0)
2052 /* WARNING: this is both a image_info setting (already done)
2053 and a operator to change image colorspace.
2055 FUTURE: default colorspace should be sRGB!
2056 Unless some type of 'linear colorspace' mode is set.
2058 Note that +colorspace sets "undefined" or no effect on
2059 new images, but forces images already in memory back to RGB!
2060 That seems to be a little strange!
2062 (void) TransformImageColorspace(_image,
2063 IfNormalOp ? _image_info->colorspace : sRGBColorspace,
2067 if (LocaleCompare("connected-components",option+1) == 0)
2069 if (IsGeometry(arg1) == MagickFalse)
2070 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2071 new_image=ConnectedComponentsImage(_image,(size_t)
2072 StringToInteger(arg1),(CCObjectInfo **) NULL,_exception);
2075 if (LocaleCompare("contrast",option+1) == 0)
2077 CLIWandWarnReplaced(IfNormalOp?"-level":"+level");
2078 (void) ContrastImage(_image,IsNormalOp,_exception);
2081 if (LocaleCompare("contrast-stretch",option+1) == 0)
2090 flags=ParseGeometry(arg1,&geometry_info);
2091 if ((flags & RhoValue) == 0)
2092 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2093 black_point=geometry_info.rho;
2094 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2096 if ((flags & PercentValue) != 0) {
2097 black_point*=(double) _image->columns*_image->rows/100.0;
2098 white_point*=(double) _image->columns*_image->rows/100.0;
2100 white_point=(double) _image->columns*_image->rows-white_point;
2101 (void) ContrastStretchImage(_image,black_point,white_point,
2105 if (LocaleCompare("convolve",option+1) == 0)
2116 kernel_info=AcquireKernelInfo(arg1,exception);
2117 if (kernel_info == (KernelInfo *) NULL)
2118 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2120 for (j=0; j < (ssize_t) (kernel_info->width*kernel_info->height); j++)
2121 gamma+=kernel_info->values[j];
2122 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
2123 for (j=0; j < (ssize_t) (kernel_info->width*kernel_info->height); j++)
2124 kernel_info->values[j]*=gamma;
2125 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2127 kernel_info=DestroyKernelInfo(kernel_info);
2130 if (LocaleCompare("crop",option+1) == 0)
2132 /* WARNING: This can generate multiple images! */
2133 if (IsGeometry(arg1) == MagickFalse)
2134 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2135 new_image=CropImageToTiles(_image,arg1,_exception);
2138 if (LocaleCompare("cycle",option+1) == 0)
2140 if (IsGeometry(arg1) == MagickFalse)
2141 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2142 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2146 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2150 if (LocaleCompare("decipher",option+1) == 0)
2152 /* Note: arguments do not have percent escapes expanded */
2156 passkey=FileToStringInfo(arg1,~0UL,_exception);
2157 if (passkey == (StringInfo *) NULL)
2158 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2160 (void) PasskeyDecipherImage(_image,passkey,_exception);
2161 passkey=DestroyStringInfo(passkey);
2164 if (LocaleCompare("depth",option+1) == 0)
2166 /* The _image_info->depth setting has already been set
2167 We just need to apply it to all images in current sequence
2169 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2170 That is it really is an operation, not a setting! Arrgghhh
2172 FUTURE: this should not be an operator!!!
2174 (void) SetImageDepth(_image,_image_info->depth,_exception);
2177 if (LocaleCompare("deskew",option+1) == 0)
2183 if (IsGeometry(arg1) == MagickFalse)
2184 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2185 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
2188 threshold=40.0*QuantumRange/100.0;
2189 new_image=DeskewImage(_image,threshold,_exception);
2192 if (LocaleCompare("despeckle",option+1) == 0)
2194 new_image=DespeckleImage(_image,_exception);
2197 if (LocaleCompare("distort",option+1) == 0)
2205 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2207 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2209 if ((DistortMethod) parse == ResizeDistortion)
2213 /* Special Case - Argument is actually a resize geometry!
2214 ** Convert that to an appropriate distortion argument array.
2215 ** FUTURE: make a separate special resize operator
2216 Roll into a resize special operator */
2217 if (IsGeometry(arg2) == MagickFalse)
2218 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2220 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
2221 resize_args[0]=(double) geometry.width;
2222 resize_args[1]=(double) geometry.height;
2223 new_image=DistortImage(_image,(DistortMethod) parse,
2224 (size_t)2,resize_args,MagickTrue,_exception);
2227 /* convert argument string into an array of doubles */
2228 args = StringToArrayOfDoubles(arg2,&count,_exception);
2229 if (args == (double *) NULL )
2230 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2232 new_image=DistortImage(_image,(DistortMethod) parse,(size_t)
2233 count,args,IsPlusOp,_exception);
2234 args=(double *) RelinquishMagickMemory(args);
2237 if (LocaleCompare("draw",option+1) == 0)
2239 (void) CloneString(&_draw_info->primitive,arg1);
2240 (void) DrawImage(_image,_draw_info,_exception);
2241 (void) CloneString(&_draw_info->primitive,(char *) NULL);
2244 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2248 if (LocaleCompare("edge",option+1) == 0)
2250 flags=ParseGeometry(arg1,&geometry_info);
2251 if ((flags & (RhoValue|SigmaValue)) == 0)
2252 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2253 new_image=EdgeImage(_image,geometry_info.rho,_exception);
2256 if (LocaleCompare("emboss",option+1) == 0)
2258 flags=ParseGeometry(arg1,&geometry_info);
2259 if ((flags & (RhoValue|SigmaValue)) == 0)
2260 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2261 if ((flags & SigmaValue) == 0)
2262 geometry_info.sigma=1.0;
2263 new_image=EmbossImage(_image,geometry_info.rho,
2264 geometry_info.sigma,_exception);
2267 if (LocaleCompare("encipher",option+1) == 0)
2269 /* Note: arguments do not have percent escapes expanded */
2273 passkey=FileToStringInfo(arg1,~0UL,_exception);
2274 if (passkey != (StringInfo *) NULL)
2276 (void) PasskeyEncipherImage(_image,passkey,_exception);
2277 passkey=DestroyStringInfo(passkey);
2281 if (LocaleCompare("enhance",option+1) == 0)
2283 new_image=EnhanceImage(_image,_exception);
2286 if (LocaleCompare("equalize",option+1) == 0)
2288 (void) EqualizeImage(_image,_exception);
2291 if (LocaleCompare("evaluate",option+1) == 0)
2296 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2298 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2300 if (IsGeometry(arg2) == MagickFalse)
2301 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
2302 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
2303 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2307 if (LocaleCompare("extent",option+1) == 0)
2309 if (IsGeometry(arg1) == MagickFalse)
2310 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2311 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
2312 if (geometry.width == 0)
2313 geometry.width=_image->columns;
2314 if (geometry.height == 0)
2315 geometry.height=_image->rows;
2316 new_image=ExtentImage(_image,&geometry,_exception);
2319 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2323 if (LocaleCompare("flip",option+1) == 0)
2325 new_image=FlipImage(_image,_exception);
2328 if (LocaleCompare("flop",option+1) == 0)
2330 new_image=FlopImage(_image,_exception);
2333 if (LocaleCompare("floodfill",option+1) == 0)
2338 if (IsGeometry(arg1) == MagickFalse)
2339 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2340 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2341 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2342 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2343 geometry.y,IsPlusOp,_exception);
2346 if (LocaleCompare("frame",option+1) == 0)
2357 value=GetImageOption(_image_info,"compose");
2358 compose=OverCompositeOp; /* use Over not _image->compose */
2359 if (value != (const char *) NULL)
2360 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
2362 if (IsGeometry(arg1) == MagickFalse)
2363 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2364 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
2365 frame_info.width=geometry.width;
2366 frame_info.height=geometry.height;
2367 frame_info.outer_bevel=geometry.x;
2368 frame_info.inner_bevel=geometry.y;
2369 frame_info.x=(ssize_t) frame_info.width;
2370 frame_info.y=(ssize_t) frame_info.height;
2371 frame_info.width=_image->columns+2*frame_info.width;
2372 frame_info.height=_image->rows+2*frame_info.height;
2373 new_image=FrameImage(_image,&frame_info,compose,_exception);
2376 if (LocaleCompare("function",option+1) == 0)
2384 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2386 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2388 /* convert argument string into an array of doubles */
2389 args = StringToArrayOfDoubles(arg2,&count,_exception);
2390 if (args == (double *) NULL )
2391 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2393 (void) FunctionImage(_image,(MagickFunction)parse,(size_t) count,args,
2395 args=(double *) RelinquishMagickMemory(args);
2398 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2402 if (LocaleCompare("gamma",option+1) == 0)
2407 if (IsGeometry(arg1) == MagickFalse)
2408 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2409 constant=StringToDouble(arg1,(char **) NULL);
2411 /* Using Gamma, via a cache */
2413 constant=PerceptibleReciprocal(constant);
2414 (void) GammaImage(_image,constant,_exception);
2416 /* Using Evaluate POW, direct update of values - more accurite */
2418 constant=PerceptibleReciprocal(constant);
2419 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
2420 _image->gamma*=StringToDouble(arg1,(char **) NULL);
2422 /* Set gamma setting -- Old meaning of "+gamma"
2423 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2427 if (LocaleCompare("gaussian-blur",option+1) == 0)
2429 flags=ParseGeometry(arg1,&geometry_info);
2430 if ((flags & (RhoValue|SigmaValue)) == 0)
2431 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2432 if ((flags & SigmaValue) == 0)
2433 geometry_info.sigma=1.0;
2434 new_image=GaussianBlurImage(_image,geometry_info.rho,
2435 geometry_info.sigma,_exception);
2438 if (LocaleCompare("gaussian",option+1) == 0)
2440 CLIWandWarnReplaced("-gaussian-blur");
2441 (void) CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL,exception);
2443 if (LocaleCompare("geometry",option+1) == 0)
2446 Record Image offset for composition. (A Setting)
2447 Resize last _image. (ListOperator) -- DEPRECIATE
2448 FUTURE: Why if no 'offset' does this resize ALL images?
2449 Also why is the setting recorded in the IMAGE non-sense!
2452 { /* remove the previous composition geometry offset! */
2453 if (_image->geometry != (char *) NULL)
2454 _image->geometry=DestroyString(_image->geometry);
2457 if (IsGeometry(arg1) == MagickFalse)
2458 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2459 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
2460 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2461 (void) CloneString(&_image->geometry,arg1);
2463 new_image=ResizeImage(_image,geometry.width,geometry.height,
2464 _image->filter,_exception);
2467 if (LocaleCompare("grayscale",option+1) == 0)
2469 parse=ParseCommandOption(MagickPixelIntensityOptions,
2472 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
2474 (void) GrayscaleImage(_image,(PixelIntensityMethod) parse,_exception);
2477 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2481 if (LocaleCompare("hough-lines",option+1) == 0)
2483 flags=ParseGeometry(arg1,&geometry_info);
2484 if ((flags & (RhoValue|SigmaValue)) == 0)
2485 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2486 if ((flags & SigmaValue) == 0)
2487 geometry_info.sigma=geometry_info.rho;
2488 if ((flags & XiValue) == 0)
2489 geometry_info.xi=40;
2490 new_image=HoughLineImage(_image,(size_t) geometry_info.rho,
2491 (size_t) geometry_info.sigma,(size_t) geometry_info.xi,_exception);
2494 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2498 if (LocaleCompare("identify",option+1) == 0)
2504 format=GetImageOption(_image_info,"format");
2505 if (format == (char *) NULL)
2507 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2511 text=InterpretImageProperties(_image_info,_image,format,_exception);
2512 if (text == (char *) NULL)
2513 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
2515 (void) fputs(text,stdout);
2516 text=DestroyString((char *)text);
2519 if (LocaleCompare("implode",option+1) == 0)
2521 flags=ParseGeometry(arg1,&geometry_info);
2522 if ((flags & RhoValue) == 0)
2523 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2524 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2528 if (LocaleCompare("interpolative-resize",option+1) == 0)
2530 /* FUTURE: New to IMv7
2531 Roll into a resize special operator */
2532 if (IsGeometry(arg1) == MagickFalse)
2533 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2534 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2535 new_image=InterpolativeResizeImage(_image,geometry.width,
2536 geometry.height,_image->interpolate,_exception);
2539 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2543 if (LocaleCompare("kuwahara",option+1) == 0)
2546 Edge preserving blur.
2548 flags=ParseGeometry(arg1,&geometry_info);
2549 if ((flags & (RhoValue|SigmaValue)) == 0)
2550 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2551 if ((flags & SigmaValue) == 0)
2552 geometry_info.sigma=geometry_info.rho-0.5;
2553 new_image=KuwaharaImage(_image,geometry_info.rho,geometry_info.sigma,
2557 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2561 if (LocaleCompare("lat",option+1) == 0)
2563 flags=ParseGeometry(arg1,&geometry_info);
2564 if ((flags & (RhoValue|SigmaValue)) == 0)
2565 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2566 if ((flags & SigmaValue) == 0)
2567 geometry_info.sigma=1.0;
2568 if ((flags & PercentValue) != 0)
2569 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2570 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
2571 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2575 if (LocaleCompare("level",option+1) == 0)
2585 flags=ParseGeometry(arg1,&geometry_info);
2586 if ((flags & RhoValue) == 0)
2587 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2588 black_point=geometry_info.rho;
2589 white_point=(double) QuantumRange;
2590 if ((flags & SigmaValue) != 0)
2591 white_point=geometry_info.sigma;
2593 if ((flags & XiValue) != 0)
2594 gamma=geometry_info.xi;
2595 if ((flags & PercentValue) != 0)
2597 black_point*=(double) (QuantumRange/100.0);
2598 white_point*=(double) (QuantumRange/100.0);
2600 if ((flags & SigmaValue) == 0)
2601 white_point=(double) QuantumRange-black_point;
2602 if (IfPlusOp || ((flags & AspectValue) != 0))
2603 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
2605 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
2608 if (LocaleCompare("level-colors",option+1) == 0)
2611 token[MagickPathExtent];
2620 p=(const char *) arg1;
2621 GetNextToken(p,&p,MagickPathExtent,token); /* get black point color */
2622 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2623 (void) QueryColorCompliance(token,AllCompliance,
2624 &black_point,_exception);
2626 (void) QueryColorCompliance("#000000",AllCompliance,
2627 &black_point,_exception);
2628 if (isalpha((int) token[0]) || (token[0] == '#'))
2629 GetNextToken(p,&p,MagickPathExtent,token);
2631 white_point=black_point; /* set everything to that color */
2634 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2635 GetNextToken(p,&p,MagickPathExtent,token); /* Get white point color. */
2636 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2637 (void) QueryColorCompliance(token,AllCompliance,
2638 &white_point,_exception);
2640 (void) QueryColorCompliance("#ffffff",AllCompliance,
2641 &white_point,_exception);
2643 (void) LevelImageColors(_image,&black_point,&white_point,
2644 IsPlusOp,_exception);
2647 if (LocaleCompare("linear-stretch",option+1) == 0)
2656 flags=ParseGeometry(arg1,&geometry_info);
2657 if ((flags & RhoValue) == 0)
2658 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2659 black_point=geometry_info.rho;
2660 white_point=(double) _image->columns*_image->rows;
2661 if ((flags & SigmaValue) != 0)
2662 white_point=geometry_info.sigma;
2663 if ((flags & PercentValue) != 0)
2665 black_point*=(double) _image->columns*_image->rows/100.0;
2666 white_point*=(double) _image->columns*_image->rows/100.0;
2668 if ((flags & SigmaValue) == 0)
2669 white_point=(double) _image->columns*_image->rows-
2671 (void) LinearStretchImage(_image,black_point,white_point,_exception);
2674 if (LocaleCompare("liquid-rescale",option+1) == 0)
2676 /* FUTURE: Roll into a resize special operator */
2677 if (IsGeometry(arg1) == MagickFalse)
2678 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2679 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
2680 if ((flags & XValue) == 0)
2682 if ((flags & YValue) == 0)
2684 new_image=LiquidRescaleImage(_image,geometry.width,
2685 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
2688 if (LocaleCompare("local-contrast",option+1) == 0)
2693 flags=ParseGeometry(arg1,&geometry_info);
2694 if ((flags & RhoValue) == 0)
2695 geometry_info.rho=10;
2696 if ((flags & SigmaValue) == 0)
2697 geometry_info.sigma=12.5;
2698 new_image=LocalContrastImage(_image,geometry_info.rho,
2699 geometry_info.sigma,exception);
2702 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2706 if (LocaleCompare("magnify",option+1) == 0)
2708 new_image=MagnifyImage(_image,_exception);
2711 if (LocaleCompare("map",option+1) == 0)
2713 CLIWandWarnReplaced("-remap");
2714 (void) CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL,exception);
2717 if (LocaleCompare("mask",option+1) == 0)
2727 (void) SetImageMask(_image,WritePixelMask,(Image *) NULL,
2734 mask=GetImageCache(_image_info,arg1,_exception);
2735 if (mask == (Image *) NULL)
2737 (void) SetImageMask(_image,WritePixelMask,mask,_exception);
2738 mask=DestroyImage(mask);
2741 if (LocaleCompare("matte",option+1) == 0)
2743 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
2744 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2745 DeactivateAlphaChannel, _exception);
2748 if (LocaleCompare("mean-shift",option+1) == 0)
2750 flags=ParseGeometry(arg1,&geometry_info);
2751 if ((flags & (RhoValue|SigmaValue)) == 0)
2752 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2753 if ((flags & SigmaValue) == 0)
2754 geometry_info.sigma=1.0;
2755 if ((flags & XiValue) == 0)
2756 geometry_info.xi=0.10*QuantumRange;
2757 if ((flags & PercentValue) != 0)
2758 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2759 new_image=MeanShiftImage(_image,(size_t) geometry_info.rho,
2760 (size_t) geometry_info.sigma,geometry_info.xi,_exception);
2763 if (LocaleCompare("median",option+1) == 0)
2765 CLIWandWarnReplaced("-statistic Median");
2766 (void) CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1,exception);
2769 if (LocaleCompare("mode",option+1) == 0)
2771 /* FUTURE: note this is also a special "montage" option */
2772 CLIWandWarnReplaced("-statistic Mode");
2773 (void) CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1,exception);
2776 if (LocaleCompare("modulate",option+1) == 0)
2778 if (IsGeometry(arg1) == MagickFalse)
2779 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2780 (void) ModulateImage(_image,arg1,_exception);
2783 if (LocaleCompare("monitor",option+1) == 0)
2785 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
2786 (MagickProgressMonitor) NULL,(void *) NULL);
2789 if (LocaleCompare("monochrome",option+1) == 0)
2791 (void) SetImageType(_image,BilevelType,_exception);
2794 if (LocaleCompare("morphology",option+1) == 0)
2797 token[MagickPathExtent];
2809 GetNextToken(p,&p,MagickPathExtent,token);
2810 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2812 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",option,
2815 GetNextToken(p,&p,MagickPathExtent,token);
2816 if ((*p == ':') || (*p == ','))
2817 GetNextToken(p,&p,MagickPathExtent,token);
2819 iterations=(ssize_t) StringToLong(p);
2820 kernel=AcquireKernelInfo(arg2,exception);
2821 if (kernel == (KernelInfo *) NULL)
2822 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",option,arg2);
2823 new_image=MorphologyImage(_image,(MorphologyMethod)parse,iterations,
2825 kernel=DestroyKernelInfo(kernel);
2828 if (LocaleCompare("motion-blur",option+1) == 0)
2830 flags=ParseGeometry(arg1,&geometry_info);
2831 if ((flags & (RhoValue|SigmaValue)) == 0)
2832 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2833 if ((flags & SigmaValue) == 0)
2834 geometry_info.sigma=1.0;
2835 new_image=MotionBlurImage(_image,geometry_info.rho,geometry_info.sigma,
2836 geometry_info.xi,_exception);
2839 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2843 if (LocaleCompare("negate",option+1) == 0)
2845 (void) NegateImage(_image, IsPlusOp, _exception);
2848 if (LocaleCompare("noise",option+1) == 0)
2858 CLIWandWarnReplaced("-statistic NonPeak");
2859 (void) CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1,exception);
2862 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2864 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2867 value=GetImageOption(_image_info,"attenuate");
2868 if (value != (const char *) NULL)
2869 attenuate=StringToDouble(value,(char **) NULL);
2870 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2874 if (LocaleCompare("normalize",option+1) == 0)
2876 (void) NormalizeImage(_image,_exception);
2879 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2883 if (LocaleCompare("opaque",option+1) == 0)
2888 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2889 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,IsPlusOp,
2893 if (LocaleCompare("ordered-dither",option+1) == 0)
2895 (void) OrderedDitherImage(_image,arg1,_exception);
2898 if (LocaleCompare("otsu-threshold",option+1) == 0)
2900 (void) OTSUThresholdImage(_image,_exception);
2903 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2907 if (LocaleCompare("paint",option+1) == 0)
2909 flags=ParseGeometry(arg1,&geometry_info);
2910 if ((flags & (RhoValue|SigmaValue)) == 0)
2911 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2912 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2916 if (LocaleCompare("perceptible",option+1) == 0)
2918 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2922 if (LocaleCompare("polaroid",option+1) == 0)
2934 random_info=AcquireRandomInfo();
2935 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2936 random_info=DestroyRandomInfo(random_info);
2939 flags=ParseGeometry(arg1,&geometry_info);
2940 if ((flags & RhoValue) == 0)
2941 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2942 angle=geometry_info.rho;
2944 caption=GetImageProperty(_image,"caption",_exception);
2945 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2946 _image->interpolate,_exception);
2949 if (LocaleCompare("posterize",option+1) == 0)
2951 flags=ParseGeometry(arg1,&geometry_info);
2952 if ((flags & RhoValue) == 0)
2953 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2954 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
2955 _quantize_info->dither_method,_exception);
2958 if (LocaleCompare("preview",option+1) == 0)
2960 /* FUTURE: should be a 'Genesis' option?
2961 Option however is also in WandSettingOptionInfo()
2964 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2966 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2968 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
2971 if (LocaleCompare("profile",option+1) == 0)
2985 /* Note: arguments do not have percent escapes expanded */
2987 { /* Remove a profile from the _image. */
2988 (void) ProfileImage(_image,arg1,(const unsigned char *)
2992 /* Associate a profile with the _image. */
2993 profile_info=CloneImageInfo(_image_info);
2994 profile=GetImageProfile(_image,"iptc");
2995 if (profile != (StringInfo *) NULL)
2996 profile_info->profile=(void *) CloneStringInfo(profile);
2997 profile_image=GetImageCache(profile_info,arg1,_exception);
2998 profile_info=DestroyImageInfo(profile_info);
2999 if (profile_image == (Image *) NULL)
3004 profile_info=CloneImageInfo(_image_info);
3005 (void) CopyMagickString(profile_info->filename,arg1,
3007 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
3008 if (profile != (StringInfo *) NULL)
3010 (void) SetImageInfo(profile_info,0,_exception);
3011 (void) ProfileImage(_image,profile_info->magick,
3012 GetStringInfoDatum(profile),(size_t)
3013 GetStringInfoLength(profile),_exception);
3014 profile=DestroyStringInfo(profile);
3016 profile_info=DestroyImageInfo(profile_info);
3019 ResetImageProfileIterator(profile_image);
3020 name=GetNextImageProfile(profile_image);
3021 while (name != (const char *) NULL)
3023 profile=GetImageProfile(profile_image,name);
3024 if (profile != (StringInfo *) NULL)
3025 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3026 (size_t) GetStringInfoLength(profile),_exception);
3027 name=GetNextImageProfile(profile_image);
3029 profile_image=DestroyImage(profile_image);
3032 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3036 if (LocaleCompare("raise",option+1) == 0)
3038 if (IsGeometry(arg1) == MagickFalse)
3039 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3040 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3041 (void) RaiseImage(_image,&geometry,IsNormalOp,_exception);
3044 if (LocaleCompare("random-threshold",option+1) == 0)
3050 if (IsGeometry(arg1) == MagickFalse)
3051 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3053 max_threshold=(double) QuantumRange;
3054 flags=ParseGeometry(arg1,&geometry_info);
3055 min_threshold=geometry_info.rho;
3056 max_threshold=geometry_info.sigma;
3057 if ((flags & SigmaValue) == 0)
3058 max_threshold=min_threshold;
3059 if (strchr(arg1,'%') != (char *) NULL)
3061 max_threshold*=(double) (0.01*QuantumRange);
3062 min_threshold*=(double) (0.01*QuantumRange);
3064 (void) RandomThresholdImage(_image,min_threshold,max_threshold,
3068 if (LocaleCompare("range-threshold",option+1) == 0)
3071 Range threshold image.
3073 if (IsGeometry(arg1) == MagickFalse)
3074 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3075 flags=ParseGeometry(arg1,&geometry_info);
3076 if ((flags & SigmaValue) == 0)
3077 geometry_info.sigma=geometry_info.rho;
3078 if ((flags & XiValue) == 0)
3079 geometry_info.xi=geometry_info.sigma;
3080 if ((flags & PsiValue) == 0)
3081 geometry_info.psi=geometry_info.xi;
3082 if (strchr(arg1,'%') != (char *) NULL)
3084 geometry_info.rho*=(double) (0.01*QuantumRange);
3085 geometry_info.sigma*=(double) (0.01*QuantumRange);
3086 geometry_info.xi*=(double) (0.01*QuantumRange);
3087 geometry_info.psi*=(double) (0.01*QuantumRange);
3089 (void) RangeThresholdImage(_image,geometry_info.rho,
3090 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3093 if (LocaleCompare("read-mask",option+1) == 0)
3095 /* Note: arguments do not have percent escapes expanded */
3100 { /* Remove a mask. */
3101 (void) SetImageMask(_image,ReadPixelMask,(Image *) NULL,
3105 /* Set the image mask. */
3106 mask=GetImageCache(_image_info,arg1,_exception);
3107 if (mask == (Image *) NULL)
3109 (void) SetImageMask(_image,ReadPixelMask,mask,_exception);
3110 mask=DestroyImage(mask);
3113 if (LocaleCompare("recolor",option+1) == 0)
3115 CLIWandWarnReplaced("-color-matrix");
3116 (void) CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL,
3119 if (LocaleCompare("region",option+1) == 0)
3123 (void) SetImageRegionMask(_image,WritePixelMask,
3124 (const RectangleInfo *) NULL,_exception);
3127 if (IsGeometry(arg1) == MagickFalse)
3128 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3129 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3130 (void) SetImageRegionMask(_image,WritePixelMask,&geometry,_exception);
3133 if (LocaleCompare("remap",option+1) == 0)
3135 /* Note: arguments do not have percent escapes expanded */
3139 remap_image=GetImageCache(_image_info,arg1,_exception);
3140 if (remap_image == (Image *) NULL)
3142 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
3143 remap_image=DestroyImage(remap_image);
3146 if (LocaleCompare("repage",option+1) == 0)
3150 if (IsGeometry(arg1) == MagickFalse)
3151 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3153 (void) ResetImagePage(_image,arg1);
3156 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
3159 if (LocaleCompare("resample",option+1) == 0)
3161 /* FUTURE: Roll into a resize special operation */
3162 flags=ParseGeometry(arg1,&geometry_info);
3163 if ((flags & (RhoValue|SigmaValue)) == 0)
3164 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3165 if ((flags & SigmaValue) == 0)
3166 geometry_info.sigma=geometry_info.rho;
3167 new_image=ResampleImage(_image,geometry_info.rho,
3168 geometry_info.sigma,_image->filter,_exception);
3171 if (LocaleCompare("resize",option+1) == 0)
3173 if (IsGeometry(arg1) == MagickFalse)
3174 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3175 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3176 new_image=ResizeImage(_image,geometry.width,geometry.height,
3177 _image->filter,_exception);
3180 if (LocaleCompare("roll",option+1) == 0)
3182 if (IsGeometry(arg1) == MagickFalse)
3183 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3184 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3185 if ((flags & PercentValue) != 0)
3187 geometry.x*=(double) _image->columns/100.0;
3188 geometry.y*=(double) _image->rows/100.0;
3190 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
3193 if (LocaleCompare("rotate",option+1) == 0)
3195 flags=ParseGeometry(arg1,&geometry_info);
3196 if ((flags & RhoValue) == 0)
3197 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3198 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
3200 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3202 new_image=RotateImage(_image,geometry_info.rho,_exception);
3205 if (LocaleCompare("rotational-blur",option+1) == 0)
3207 flags=ParseGeometry(arg1,&geometry_info);
3208 if ((flags & RhoValue) == 0)
3209 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3210 new_image=RotationalBlurImage(_image,geometry_info.rho,_exception);
3213 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3217 if (LocaleCompare("sample",option+1) == 0)
3219 /* FUTURE: Roll into a resize special operator */
3220 if (IsGeometry(arg1) == MagickFalse)
3221 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3222 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3223 new_image=SampleImage(_image,geometry.width,geometry.height,
3227 if (LocaleCompare("scale",option+1) == 0)
3229 /* FUTURE: Roll into a resize special operator */
3230 if (IsGeometry(arg1) == MagickFalse)
3231 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3232 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3233 new_image=ScaleImage(_image,geometry.width,geometry.height,
3237 if (LocaleCompare("segment",option+1) == 0)
3239 flags=ParseGeometry(arg1,&geometry_info);
3240 if ((flags & (RhoValue|SigmaValue)) == 0)
3241 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3242 if ((flags & SigmaValue) == 0)
3243 geometry_info.sigma=1.0;
3244 (void) SegmentImage(_image,_image->colorspace,
3245 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3249 if (LocaleCompare("selective-blur",option+1) == 0)
3251 flags=ParseGeometry(arg1,&geometry_info);
3252 if ((flags & (RhoValue|SigmaValue)) == 0)
3253 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3254 if ((flags & SigmaValue) == 0)
3255 geometry_info.sigma=1.0;
3256 if ((flags & PercentValue) != 0)
3257 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3258 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3259 geometry_info.sigma,geometry_info.xi,_exception);
3262 if (LocaleCompare("separate",option+1) == 0)
3264 /* WARNING: This can generate multiple images! */
3265 /* FUTURE - this may be replaced by a "-channel" method */
3266 new_image=SeparateImages(_image,_exception);
3269 if (LocaleCompare("sepia-tone",option+1) == 0)
3271 if (IsGeometry(arg1) == MagickFalse)
3272 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3273 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3274 (double) QuantumRange+1.0),_exception);
3277 if (LocaleCompare("shade",option+1) == 0)
3279 flags=ParseGeometry(arg1,&geometry_info);
3280 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3281 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3282 new_image=ShadeImage(_image,IsNormalOp,geometry_info.rho,
3283 geometry_info.sigma,_exception);
3286 if (LocaleCompare("shadow",option+1) == 0)
3288 flags=ParseGeometry(arg1,&geometry_info);
3289 if ((flags & (RhoValue|SigmaValue)) == 0)
3290 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3291 if ((flags & SigmaValue) == 0)
3292 geometry_info.sigma=1.0;
3293 if ((flags & XiValue) == 0)
3294 geometry_info.xi=4.0;
3295 if ((flags & PsiValue) == 0)
3296 geometry_info.psi=4.0;
3297 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3298 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3299 ceil(geometry_info.psi-0.5),_exception);
3302 if (LocaleCompare("sharpen",option+1) == 0)
3304 flags=ParseGeometry(arg1,&geometry_info);
3305 if ((flags & (RhoValue|SigmaValue)) == 0)
3306 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3307 if ((flags & SigmaValue) == 0)
3308 geometry_info.sigma=1.0;
3309 if ((flags & XiValue) == 0)
3310 geometry_info.xi=0.0;
3311 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3315 if (LocaleCompare("shave",option+1) == 0)
3317 if (IsGeometry(arg1) == MagickFalse)
3318 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3319 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3320 new_image=ShaveImage(_image,&geometry,_exception);
3323 if (LocaleCompare("shear",option+1) == 0)
3325 flags=ParseGeometry(arg1,&geometry_info);
3326 if ((flags & RhoValue) == 0)
3327 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3328 if ((flags & SigmaValue) == 0)
3329 geometry_info.sigma=geometry_info.rho;
3330 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3334 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
3336 flags=ParseGeometry(arg1,&geometry_info);
3337 if ((flags & RhoValue) == 0)
3338 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3339 if ((flags & SigmaValue) == 0)
3340 geometry_info.sigma=(double) QuantumRange/2.0;
3341 if ((flags & PercentValue) != 0)
3342 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3344 (void) SigmoidalContrastImage(_image,IsNormalOp,geometry_info.rho,
3345 geometry_info.sigma,_exception);
3348 if (LocaleCompare("sketch",option+1) == 0)
3350 flags=ParseGeometry(arg1,&geometry_info);
3351 if ((flags & (RhoValue|SigmaValue)) == 0)
3352 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3353 if ((flags & SigmaValue) == 0)
3354 geometry_info.sigma=1.0;
3355 new_image=SketchImage(_image,geometry_info.rho,
3356 geometry_info.sigma,geometry_info.xi,_exception);
3359 if (LocaleCompare("solarize",option+1) == 0)
3361 if (IsGeometry(arg1) == MagickFalse)
3362 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3363 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3364 QuantumRange+1.0),_exception);
3367 if (LocaleCompare("sparse-color",option+1) == 0)
3369 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3371 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3373 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3377 if (LocaleCompare("splice",option+1) == 0)
3379 if (IsGeometry(arg1) == MagickFalse)
3380 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3381 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
3382 new_image=SpliceImage(_image,&geometry,_exception);
3385 if (LocaleCompare("spread",option+1) == 0)
3387 flags=ParseGeometry(arg1,&geometry_info);
3388 if ((flags & RhoValue) == 0)
3389 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3390 new_image=SpreadImage(_image,_image->interpolate,geometry_info.rho,
3394 if (LocaleCompare("statistic",option+1) == 0)
3396 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3398 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
3400 flags=ParseGeometry(arg2,&geometry_info);
3401 if ((flags & RhoValue) == 0)
3402 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3403 if ((flags & SigmaValue) == 0)
3404 geometry_info.sigma=geometry_info.rho;
3405 new_image=StatisticImage(_image,(StatisticType)parse,
3406 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3410 if (LocaleCompare("strip",option+1) == 0)
3412 (void) StripImage(_image,_exception);
3415 if (LocaleCompare("swirl",option+1) == 0)
3417 flags=ParseGeometry(arg1,&geometry_info);
3418 if ((flags & RhoValue) == 0)
3419 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3420 new_image=SwirlImage(_image,geometry_info.rho,
3421 _image->interpolate,_exception);
3424 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3428 if (LocaleCompare("threshold",option+1) == 0)
3433 threshold=(double) QuantumRange/2;
3435 if (IsGeometry(arg1) == MagickFalse)
3436 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3437 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
3439 (void) BilevelImage(_image,threshold,_exception);
3442 if (LocaleCompare("thumbnail",option+1) == 0)
3444 if (IsGeometry(arg1) == MagickFalse)
3445 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3446 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3447 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3451 if (LocaleCompare("tint",option+1) == 0)
3453 if (IsGeometry(arg1) == MagickFalse)
3454 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3455 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
3458 if (LocaleCompare("transform",option+1) == 0)
3460 CLIWandWarnReplaced("+distort AffineProjection");
3461 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
3464 if (LocaleCompare("transparent",option+1) == 0)
3469 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3470 (void) TransparentPaintImage(_image,&target,(Quantum)
3471 TransparentAlpha,IsPlusOp,_exception);
3474 if (LocaleCompare("transpose",option+1) == 0)
3476 new_image=TransposeImage(_image,_exception);
3479 if (LocaleCompare("transverse",option+1) == 0)
3481 new_image=TransverseImage(_image,_exception);
3484 if (LocaleCompare("trim",option+1) == 0)
3486 new_image=TrimImage(_image,_exception);
3489 if (LocaleCompare("type",option+1) == 0)
3491 /* Note that "type" setting should have already been defined */
3492 (void) SetImageType(_image,_image_info->type,_exception);
3495 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3499 if (LocaleCompare("unique",option+1) == 0)
3501 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3502 Option is not documented, bt appears to be for "identify".
3503 We may need a identify specific verbose!
3506 (void) DeleteImageArtifact(_image,"identify:unique-colors");
3509 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3510 (void) SetImageArtifact(_image,"verbose","true");
3513 if (LocaleCompare("unique-colors",option+1) == 0)
3515 new_image=UniqueImageColors(_image,_exception);
3518 if (LocaleCompare("unsharp",option+1) == 0)
3520 flags=ParseGeometry(arg1,&geometry_info);
3521 if ((flags & (RhoValue|SigmaValue)) == 0)
3522 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3523 if ((flags & SigmaValue) == 0)
3524 geometry_info.sigma=1.0;
3525 if ((flags & XiValue) == 0)
3526 geometry_info.xi=1.0;
3527 if ((flags & PsiValue) == 0)
3528 geometry_info.psi=0.05;
3529 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3530 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
3533 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3537 if (LocaleCompare("verbose",option+1) == 0)
3539 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
3540 three places! ImageArtifact ImageOption _image_info->verbose
3541 Some how new images also get this artifact!
3543 (void) SetImageArtifact(_image,option+1,
3544 IfNormalOp ? "true" : "false" );
3547 if (LocaleCompare("vignette",option+1) == 0)
3549 flags=ParseGeometry(arg1,&geometry_info);
3550 if ((flags & (RhoValue|SigmaValue)) == 0)
3551 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3552 if ((flags & SigmaValue) == 0)
3553 geometry_info.sigma=1.0;
3554 if ((flags & XiValue) == 0)
3555 geometry_info.xi=0.1*_image->columns;
3556 if ((flags & PsiValue) == 0)
3557 geometry_info.psi=0.1*_image->rows;
3558 if ((flags & PercentValue) != 0)
3560 geometry_info.xi*=(double) _image->columns/100.0;
3561 geometry_info.psi*=(double) _image->rows/100.0;
3563 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3564 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3565 ceil(geometry_info.psi-0.5),_exception);
3568 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3572 if (LocaleCompare("wave",option+1) == 0)
3574 flags=ParseGeometry(arg1,&geometry_info);
3575 if ((flags & (RhoValue|SigmaValue)) == 0)
3576 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3577 if ((flags & SigmaValue) == 0)
3578 geometry_info.sigma=1.0;
3579 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3580 _image->interpolate,_exception);
3583 if (LocaleCompare("wavelet-denoise",option+1) == 0)
3585 flags=ParseGeometry(arg1,&geometry_info);
3586 if ((flags & RhoValue) == 0)
3587 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3588 if ((flags & PercentValue) != 0)
3590 geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
3591 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
3593 if ((flags & SigmaValue) == 0)
3594 geometry_info.sigma=0.0;
3595 new_image=WaveletDenoiseImage(_image,geometry_info.rho,
3596 geometry_info.sigma,_exception);
3599 if (LocaleCompare("white-threshold",option+1) == 0)
3601 if (IsGeometry(arg1) == MagickFalse)
3602 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3603 (void) WhiteThresholdImage(_image,arg1,_exception);
3606 if (LocaleCompare("write-mask",option+1) == 0)
3608 /* Note: arguments do not have percent escapes expanded */
3613 { /* Remove a mask. */
3614 (void) SetImageMask(_image,WritePixelMask,(Image *) NULL,
3618 /* Set the image mask. */
3619 mask=GetImageCache(_image_info,arg1,_exception);
3620 if (mask == (Image *) NULL)
3622 (void) SetImageMask(_image,WritePixelMask,mask,_exception);
3623 mask=DestroyImage(mask);
3626 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3629 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3631 /* clean up percent escape interpreted strings */
3633 arg1=DestroyString((char *)arg1);
3635 arg2=DestroyString((char *)arg2);
3637 /* Replace current image with any image that was generated
3638 and set image point to last image (so image->next is correct) */
3639 if (new_image != (Image *) NULL)
3640 ReplaceImageInListReturnLast(&_image,new_image);
3645 #undef _quantize_info
3654 WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
3655 const char *option,const char *arg1,const char *arg2,ExceptionInfo *exception)
3657 #if !USE_WAND_METHODS
3663 assert(cli_wand != (MagickCLI *) NULL);
3664 assert(cli_wand->signature == MagickWandSignature);
3665 assert(cli_wand->wand.signature == MagickWandSignature);
3666 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3668 if (cli_wand->wand.debug != MagickFalse)
3669 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3670 "- Simple Operator: %s \"%s\" \"%s\"", option,arg1,arg2);
3672 #if !USE_WAND_METHODS
3673 /* FUTURE add appropriate tracing */
3675 n=GetImageListLength(cli_wand->wand.images);
3676 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3679 CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
3680 if ( cli_wand->wand.images->next == (Image *) NULL )
3682 cli_wand->wand.images=cli_wand->wand.images->next;
3685 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3687 MagickResetIterator(&cli_wand->wand);
3688 while (MagickNextImage(&cli_wand->wand) != MagickFalse)
3689 (void) CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
3690 MagickResetIterator(&cli_wand->wand);
3696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3700 + C L I L i s t O p e r a t o r I m a g e s %
3704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3706 % CLIListOperatorImages() applies a single operation that is apply to the
3707 % entire image list as a whole. The result is often a complete replacment
3708 % of the image list with a completely new list, or with just a single image
3711 % The format of the MogrifyImage method is:
3713 % MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3714 % const char *option,const char *arg1,const char *arg2)
3716 % A description of each parameter follows:
3718 % o cli_wand: structure holding settings to be applied
3720 % o option: The option string for the operation
3722 % o arg1, arg2: optional argument strings to the operation
3723 % arg2 is currently not used
3726 WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3727 const char *option,const char *arg1n,const char *arg2n)
3729 const char /* percent escaped versions of the args */
3742 #define _image_info (cli_wand->wand.image_info)
3743 #define _images (cli_wand->wand.images)
3744 #define _exception (cli_wand->wand.exception)
3745 #define _draw_info (cli_wand->draw_info)
3746 #define _quantize_info (cli_wand->quantize_info)
3747 #define _process_flags (cli_wand->process_flags)
3748 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
3749 #define IfNormalOp (*option=='-')
3750 #define IfPlusOp (*option!='-')
3751 #define IsNormalOp IfNormalOp ? MagickTrue : MagickFalse
3753 assert(cli_wand != (MagickCLI *) NULL);
3754 assert(cli_wand->signature == MagickWandSignature);
3755 assert(cli_wand->wand.signature == MagickWandSignature);
3756 assert(_images != (Image *) NULL); /* _images must be present */
3758 if (cli_wand->wand.debug != MagickFalse)
3759 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3760 "- List Operator: %s \"%s\" \"%s\"", option,
3761 arg1n == (const char *) NULL ? "null" : arg1n,
3762 arg2n == (const char *) NULL ? "null" : arg2n);
3767 /* Interpret Percent Escapes in Arguments - using first image */
3768 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3769 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3770 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3771 /* Interpret Percent escapes in argument 1 */
3772 if (arg1n != (char *) NULL) {
3773 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3774 if (arg1 == (char *) NULL) {
3775 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3776 arg1=arg1n; /* use the given argument as is */
3779 if (arg2n != (char *) NULL) {
3780 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3781 if (arg2 == (char *) NULL) {
3782 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3783 arg2=arg2n; /* use the given argument as is */
3787 #undef _process_flags
3791 new_images=NewImageList();
3793 switch (*(option+1))
3797 if (LocaleCompare("append",option+1) == 0)
3799 new_images=AppendImages(_images,IsNormalOp,_exception);
3802 if (LocaleCompare("average",option+1) == 0)
3804 CLIWandWarnReplaced("-evaluate-sequence Mean");
3805 (void) CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",
3809 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3813 if (LocaleCompare("channel-fx",option+1) == 0)
3815 new_images=ChannelFxImage(_images,arg1,_exception);
3818 if (LocaleCompare("clut",option+1) == 0)
3823 /* FUTURE - make this a compose option, and thus can be used
3824 with layers compose or even compose last image over all other
3827 new_images=RemoveFirstImageFromList(&_images);
3828 clut_image=RemoveLastImageFromList(&_images);
3829 /* FUTURE - produce Exception, rather than silent fail */
3830 if (clut_image == (Image *) NULL)
3832 (void) ClutImage(new_images,clut_image,new_images->interpolate,
3834 clut_image=DestroyImage(clut_image);
3837 if (LocaleCompare("coalesce",option+1) == 0)
3839 new_images=CoalesceImages(_images,_exception);
3842 if (LocaleCompare("combine",option+1) == 0)
3844 parse=(ssize_t) _images->colorspace;
3845 if (_images->number_channels < GetImageListLength(_images))
3846 parse=sRGBColorspace;
3848 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
3850 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
3852 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
3855 if (LocaleCompare("compare",option+1) == 0)
3868 Mathematically and visually annotate the difference between an
3869 image and its reconstruction.
3871 image=RemoveFirstImageFromList(&_images);
3872 reconstruct_image=RemoveFirstImageFromList(&_images);
3873 /* FUTURE - produce Exception, rather than silent fail */
3874 if (reconstruct_image == (Image *) NULL)
3876 metric=UndefinedErrorMetric;
3877 option=GetImageOption(_image_info,"metric");
3878 if (option != (const char *) NULL)
3879 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
3880 MagickFalse,option);
3881 new_images=CompareImages(image,reconstruct_image,metric,&distortion,
3884 reconstruct_image=DestroyImage(reconstruct_image);
3885 image=DestroyImage(image);
3888 if (LocaleCompare("complex",option+1) == 0)
3890 parse=ParseCommandOption(MagickComplexOptions,MagickFalse,arg1);
3892 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3894 new_images=ComplexImages(_images,(ComplexOperator) parse,_exception);
3897 if (LocaleCompare("composite",option+1) == 0)
3915 /* Compose value from "-compose" option only */
3916 value=GetImageOption(_image_info,"compose");
3917 if (value == (const char *) NULL)
3918 compose=OverCompositeOp; /* use Over not source_image->compose */
3920 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3923 /* Get "clip-to-self" expert setting (false is normal) */
3924 clip_to_self=GetCompositeClipToSelf(compose);
3925 value=GetImageOption(_image_info,"compose:clip-to-self");
3926 if (value != (const char *) NULL)
3927 clip_to_self=IsStringTrue(value);
3928 value=GetImageOption(_image_info,"compose:outside-overlay");
3929 if (value != (const char *) NULL)
3930 clip_to_self=IsStringFalse(value); /* deprecated */
3932 new_images=RemoveFirstImageFromList(&_images);
3933 source_image=RemoveFirstImageFromList(&_images);
3934 if (source_image == (Image *) NULL)
3935 break; /* FUTURE - produce Exception, rather than silent fail */
3937 /* FUTURE - this should not be here! - should be part of -geometry */
3938 if (source_image->geometry != (char *) NULL)
3943 (void) ParseRegionGeometry(source_image,source_image->geometry,
3944 &resize_geometry,_exception);
3945 if ((source_image->columns != resize_geometry.width) ||
3946 (source_image->rows != resize_geometry.height))
3951 resize_image=ResizeImage(source_image,resize_geometry.width,
3952 resize_geometry.height,source_image->filter,_exception);
3953 if (resize_image != (Image *) NULL)
3955 source_image=DestroyImage(source_image);
3956 source_image=resize_image;
3960 SetGeometry(source_image,&geometry);
3961 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3962 GravityAdjustGeometry(new_images->columns,new_images->rows,
3963 new_images->gravity, &geometry);
3964 mask_image=RemoveFirstImageFromList(&_images);
3965 if (mask_image == (Image *) NULL)
3966 status&=CompositeImage(new_images,source_image,compose,clip_to_self,
3967 geometry.x,geometry.y,_exception);
3970 if ((compose == DisplaceCompositeOp) ||
3971 (compose == DistortCompositeOp))
3973 status&=CompositeImage(source_image,mask_image,
3974 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3975 status&=CompositeImage(new_images,source_image,compose,
3976 clip_to_self,geometry.x,geometry.y,_exception);
3983 clone_image=CloneImage(new_images,0,0,MagickTrue,_exception);
3984 if (clone_image == (Image *) NULL)
3986 status&=CompositeImage(new_images,source_image,compose,
3987 clip_to_self,geometry.x,geometry.y,_exception);
3988 status&=CompositeImage(new_images,mask_image,
3989 CopyAlphaCompositeOp,MagickTrue,0,0,_exception);
3990 status&=CompositeImage(clone_image,new_images,OverCompositeOp,
3991 clip_to_self,0,0,_exception);
3992 new_images=DestroyImage(new_images);
3993 new_images=clone_image;
3995 mask_image=DestroyImage(mask_image);
3997 source_image=DestroyImage(source_image);
4000 if (LocaleCompare("copy",option+1) == 0)
4014 if (IsGeometry(arg1) == MagickFalse)
4015 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4016 if (IsGeometry(arg2) == MagickFalse)
4017 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4018 (void) ParsePageGeometry(_images,arg2,&geometry,_exception);
4019 offset.x=geometry.x;
4020 offset.y=geometry.y;
4021 source_image=_images;
4022 if (source_image->next != (Image *) NULL)
4023 source_image=source_image->next;
4024 (void) ParsePageGeometry(source_image,arg1,&geometry,_exception);
4025 (void) CopyImagePixels(_images,source_image,&geometry,&offset,
4029 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4033 if (LocaleCompare("deconstruct",option+1) == 0)
4035 CLIWandWarnReplaced("-layer CompareAny");
4036 (void) CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
4039 if (LocaleCompare("delete",option+1) == 0)
4042 DeleteImages(&_images,arg1,_exception);
4044 DeleteImages(&_images,"-1",_exception);
4047 if (LocaleCompare("duplicate",option+1) == 0)
4057 if (IsGeometry(arg1) == MagickFalse)
4058 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
4060 number_duplicates=(size_t) StringToLong(arg1);
4062 if (p == (const char *) NULL)
4063 new_images=DuplicateImages(_images,number_duplicates,"-1",
4066 new_images=DuplicateImages(_images,number_duplicates,p,
4070 new_images=DuplicateImages(_images,1,"-1",_exception);
4071 AppendImageToList(&_images, new_images);
4072 new_images=(Image *) NULL;
4075 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4079 if (LocaleCompare("evaluate-sequence",option+1) == 0)
4081 parse=ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
4083 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
4085 new_images=EvaluateImages(_images,(MagickEvaluateOperator) parse,
4089 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4093 if (LocaleCompare("fft",option+1) == 0)
4095 new_images=ForwardFourierTransformImage(_images,IsNormalOp,
4099 if (LocaleCompare("flatten",option+1) == 0)
4101 /* REDIRECTED to use -layers flatten instead */
4102 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
4105 if (LocaleCompare("fx",option+1) == 0)
4107 new_images=FxImage(_images,arg1,_exception);
4110 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4114 if (LocaleCompare("hald-clut",option+1) == 0)
4116 /* FUTURE - make this a compose option (and thus layers compose )
4117 or perhaps compose last image over all other _images.
4122 new_images=RemoveFirstImageFromList(&_images);
4123 hald_image=RemoveLastImageFromList(&_images);
4124 if (hald_image == (Image *) NULL)
4126 (void) HaldClutImage(new_images,hald_image,_exception);
4127 hald_image=DestroyImage(hald_image);
4130 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4134 if (LocaleCompare("ift",option+1) == 0)
4140 magnitude_image=RemoveFirstImageFromList(&_images);
4141 phase_image=RemoveFirstImageFromList(&_images);
4142 /* FUTURE - produce Exception, rather than silent fail */
4143 if (phase_image == (Image *) NULL)
4145 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
4146 IsNormalOp,_exception);
4147 magnitude_image=DestroyImage(magnitude_image);
4148 phase_image=DestroyImage(phase_image);
4151 if (LocaleCompare("insert",option+1) == 0)
4160 if (IfNormalOp && (IsGeometry(arg1) == MagickFalse))
4161 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4163 insert_image=RemoveLastImageFromList(&_images);
4165 index=(ssize_t) StringToLong(arg1);
4166 index_image=insert_image;
4168 PrependImageToList(&_images,insert_image);
4169 else if (index == (ssize_t) GetImageListLength(_images))
4170 AppendImageToList(&_images,insert_image);
4173 index_image=GetImageFromList(_images,index-1);
4174 if (index_image == (Image *) NULL)
4175 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
4176 InsertImageInList(&index_image,insert_image);
4178 _images=GetFirstImageInList(index_image);
4181 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4185 if (LocaleCompare("layers",option+1) == 0)
4187 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4189 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4191 switch ((LayerMethod) parse)
4195 new_images=CoalesceImages(_images,_exception);
4198 case CompareAnyLayer:
4199 case CompareClearLayer:
4200 case CompareOverlayLayer:
4203 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
4210 case TrimBoundsLayer:
4212 new_images=MergeImageLayers(_images,(LayerMethod) parse,
4218 new_images=DisposeImages(_images,_exception);
4221 case OptimizeImageLayer:
4223 new_images=OptimizeImageLayers(_images,_exception);
4226 case OptimizePlusLayer:
4228 new_images=OptimizePlusImageLayers(_images,_exception);
4231 case OptimizeTransLayer:
4233 OptimizeImageTransparency(_images,_exception);
4236 case RemoveDupsLayer:
4238 RemoveDuplicateLayers(&_images,_exception);
4241 case RemoveZeroLayer:
4243 RemoveZeroDelayLayers(&_images,_exception);
4247 { /* General Purpose, GIF Animation Optimizer. */
4248 new_images=CoalesceImages(_images,_exception);
4249 if (new_images == (Image *) NULL)
4251 _images=DestroyImageList(_images);
4252 _images=OptimizeImageLayers(new_images,_exception);
4253 if (_images == (Image *) NULL)
4255 new_images=DestroyImageList(new_images);
4256 OptimizeImageTransparency(_images,_exception);
4257 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4261 case CompositeLayer:
4275 value=GetImageOption(_image_info,"compose");
4276 compose=OverCompositeOp; /* Default to Over */
4277 if (value != (const char *) NULL)
4278 compose=(CompositeOperator) ParseCommandOption(
4279 MagickComposeOptions,MagickFalse,value);
4281 /* Split image sequence at the first 'NULL:' image. */
4283 while (source != (Image *) NULL)
4285 source=GetNextImageInList(source);
4286 if ((source != (Image *) NULL) &&
4287 (LocaleCompare(source->magick,"NULL") == 0))
4290 if (source != (Image *) NULL)
4292 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4293 (GetNextImageInList(source) == (Image *) NULL))
4294 source=(Image *) NULL;
4296 { /* Separate the two lists, junk the null: image. */
4297 source=SplitImageList(source->previous);
4298 DeleteImageFromList(&source);
4301 if (source == (Image *) NULL)
4303 (void) ThrowMagickException(_exception,GetMagickModule(),
4304 OptionError,"MissingNullSeparator","layers Composite");
4307 /* Adjust offset with gravity and virtual canvas. */
4308 SetGeometry(_images,&geometry);
4309 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
4310 geometry.width=source->page.width != 0 ?
4311 source->page.width : source->columns;
4312 geometry.height=source->page.height != 0 ?
4313 source->page.height : source->rows;
4314 GravityAdjustGeometry(_images->page.width != 0 ?
4315 _images->page.width : _images->columns,
4316 _images->page.height != 0 ? _images->page.height :
4317 _images->rows,_images->gravity,&geometry);
4319 /* Compose the two image sequences together */
4320 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4322 source=DestroyImageList(source);
4328 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4332 if (LocaleCompare("map",option+1) == 0)
4334 CLIWandWarnReplaced("+remap");
4335 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4338 if (LocaleCompare("metric",option+1) == 0)
4340 (void) SetImageOption(_image_info,option+1,arg1);
4343 if (LocaleCompare("morph",option+1) == 0)
4348 if (IsGeometry(arg1) == MagickFalse)
4349 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4350 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4352 if (morph_image == (Image *) NULL)
4354 _images=DestroyImageList(_images);
4355 _images=morph_image;
4358 if (LocaleCompare("mosaic",option+1) == 0)
4360 /* REDIRECTED to use -layers mosaic instead */
4361 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
4364 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4368 if (LocaleCompare("poly",option+1) == 0)
4376 /* convert argument string into an array of doubles */
4377 args = StringToArrayOfDoubles(arg1,&count,_exception);
4378 if (args == (double *) NULL )
4379 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg1);
4380 new_images=PolynomialImage(_images,(size_t) (count >> 1),args,
4382 args=(double *) RelinquishMagickMemory(args);
4385 if (LocaleCompare("process",option+1) == 0)
4387 /* FUTURE: better parsing using ScriptToken() from string ??? */
4395 arguments=StringToArgv(arg1,&number_arguments);
4396 if (arguments == (char **) NULL)
4398 if (strchr(arguments[1],'=') != (char *) NULL)
4419 Support old style syntax, filter="-option arg1".
4421 assert(arg1 != (const char *) NULL);
4422 length=strlen(arg1);
4423 token=(char *) NULL;
4424 if (~length >= (MagickPathExtent-1))
4425 token=(char *) AcquireQuantumMemory(length+MagickPathExtent,
4427 if (token == (char *) NULL)
4431 token_info=AcquireTokenInfo();
4432 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4433 "\"",'\0',&breaker,&next,"e);
4434 token_info=DestroyTokenInfo(token_info);
4440 argv=(&(arguments[next]));
4441 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4444 token=DestroyString(token);
4447 (void) SubstituteString(&arguments[1],"-","");
4448 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4449 number_arguments-2,(const char **) arguments+2,_exception);
4450 for (j=0; j < number_arguments; j++)
4451 arguments[j]=DestroyString(arguments[j]);
4452 arguments=(char **) RelinquishMagickMemory(arguments);
4455 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4459 if (LocaleCompare("remap",option+1) == 0)
4461 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4464 if (LocaleCompare("reverse",option+1) == 0)
4466 ReverseImageList(&_images);
4469 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4473 if (LocaleCompare("smush",option+1) == 0)
4475 /* FUTURE: this option needs more work to make better */
4479 if (IsGeometry(arg1) == MagickFalse)
4480 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4481 offset=(ssize_t) StringToLong(arg1);
4482 new_images=SmushImages(_images,IsNormalOp,offset,_exception);
4485 if (LocaleCompare("subimage",option+1) == 0)
4503 base_image=GetImageFromList(_images,0);
4504 compare_image=GetImageFromList(_images,1);
4506 /* Comparision Metric */
4507 metric=UndefinedErrorMetric;
4508 value=GetImageOption(_image_info,"metric");
4509 if (value != (const char *) NULL)
4510 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4513 new_images=SimilarityImage(base_image,compare_image,metric,0.0,
4514 &offset,&similarity,_exception);
4516 if (new_images != (Image *) NULL)
4519 result[MagickPathExtent];
4521 (void) FormatLocaleString(result,MagickPathExtent,"%lf",
4523 (void) SetImageProperty(new_images,"subimage:similarity",result,
4525 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",(long)
4527 (void) SetImageProperty(new_images,"subimage:x",result,
4529 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",(long)
4531 (void) SetImageProperty(new_images,"subimage:y",result,
4533 (void) FormatLocaleString(result,MagickPathExtent,
4534 "%lux%lu%+ld%+ld",(unsigned long) offset.width,(unsigned long)
4535 offset.height,(long) offset.x,(long) offset.y);
4536 (void) SetImageProperty(new_images,"subimage:offset",result,
4541 if (LocaleCompare("swap",option+1) == 0)
4562 flags=ParseGeometry(arg1,&geometry_info);
4563 if ((flags & RhoValue) == 0)
4564 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4565 index=(ssize_t) geometry_info.rho;
4566 if ((flags & SigmaValue) != 0)
4567 swap_index=(ssize_t) geometry_info.sigma;
4569 p=GetImageFromList(_images,index);
4570 q=GetImageFromList(_images,swap_index);
4571 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4573 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4575 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4578 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
4579 swap=CloneImage(p,0,0,MagickTrue,_exception);
4580 if (swap == (Image *) NULL)
4581 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4582 option,GetExceptionMessage(errno));
4583 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4584 ReplaceImageInList(&q,swap);
4585 _images=GetFirstImageInList(q);
4588 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4591 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4594 /* clean up percent escape interpreted strings */
4596 arg1=DestroyString((char *)arg1);
4598 arg2=DestroyString((char *)arg2);
4600 /* if new image list generated, replace existing image list */
4601 if (new_images == (Image *) NULL)
4602 return(status == 0 ? MagickFalse : MagickTrue);
4603 _images=DestroyImageList(_images);
4604 _images=GetFirstImageInList(new_images);
4605 return(status == 0 ? MagickFalse : MagickTrue);
4611 #undef _quantize_info
4618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4622 + C L I N o I m a g e O p e r a t i o n s %
4626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4628 % CLINoImageOperator() Applies operations that may not actually need images
4631 % The classic operators of this type is "-read", which actually creates
4632 % images even when no images are present. Or image stack operators, which
4633 % can be applied (push or pop) to an empty image list.
4635 % Note that these operators may involve other special 'option' prefix
4636 % characters other than '-' or '+', namely parenthesis and braces.
4638 % The format of the CLINoImageOption method is:
4640 % void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4641 % const char *arg1, const char *arg2)
4643 % A description of each parameter follows:
4645 % o cli_wand: the main CLI Wand to use. (sometimes not required)
4647 % o option: The special option (with any switch char) to process
4649 % o arg1 & arg2: Argument for option, if required
4650 % Currently arg2 is not used.
4653 WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
4654 const char *option,const char *arg1n,const char *arg2n)
4656 const char /* percent escaped versions of the args */
4660 #define _image_info (cli_wand->wand.image_info)
4661 #define _images (cli_wand->wand.images)
4662 #define _exception (cli_wand->wand.exception)
4663 #define _process_flags (cli_wand->process_flags)
4664 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
4665 #define IfNormalOp (*option=='-')
4666 #define IfPlusOp (*option!='-')
4668 assert(cli_wand != (MagickCLI *) NULL);
4669 assert(cli_wand->signature == MagickWandSignature);
4670 assert(cli_wand->wand.signature == MagickWandSignature);
4672 if (cli_wand->wand.debug != MagickFalse)
4673 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
4674 "- NoImage Operator: %s \"%s\" \"%s\"", option,
4675 arg1n != (char *) NULL ? arg1n : "",
4676 arg2n != (char *) NULL ? arg2n : "");
4681 /* Interpret Percent Escapes in Arguments - using first image */
4682 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4683 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4684 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4685 /* Interpret Percent escapes in argument 1 */
4686 if (arg1n != (char *) NULL) {
4687 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4688 if (arg1 == (char *) NULL) {
4689 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4690 arg1=arg1n; /* use the given argument as is */
4693 if (arg2n != (char *) NULL) {
4694 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4695 if (arg2 == (char *) NULL) {
4696 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4697 arg2=arg2n; /* use the given argument as is */
4701 #undef _process_flags
4704 do { /* break to exit code */
4706 No-op options (ignore these)
4708 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
4710 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4712 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4714 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
4716 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4721 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4722 ( LocaleCompare("--",option) == 0 ) ) {
4723 /* Do Glob filename Expansion for 'arg1' then read all images.
4725 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4726 * (but attaching to the filenames in the generated argument list) any
4727 * [...] read modifiers that may be present.
4729 * For example: It will expand '*.gif[20x20]' into a list such as
4730 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4732 * NOTE: In IMv6 this was done globally across all images. This
4733 * meant you could include IM options in '@filename' lists, but you
4734 * could not include comments. Doing it only for image read makes
4735 * it far more secure.
4737 * Note: arguments do not have percent escapes expanded for security
4745 argv = (char **) &arg1;
4747 /* Expand 'glob' expressions in the given filename.
4748 Expansion handles any 'coder:' prefix, or read modifiers attached
4749 to the filename, including them in the resulting expanded list.
4751 if (ExpandFilenames(&argc,&argv) == MagickFalse)
4752 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4753 option,GetExceptionMessage(errno));
4755 /* loop over expanded filename list, and read then all in */
4756 for (i=0; i < (ssize_t) argc; i++) {
4759 if (_image_info->ping != MagickFalse)
4760 new_images=PingImages(_image_info,argv[i],_exception);
4762 new_images=ReadImages(_image_info,argv[i],_exception);
4763 AppendImageToList(&_images, new_images);
4764 argv[i]=DestroyString(argv[i]);
4766 argv=(char **) RelinquishMagickMemory(argv);
4771 Note: Writing a empty image list is valid in specific cases
4773 if (LocaleCompare("write",option+1) == 0) {
4774 /* Note: arguments do not have percent escapes expanded */
4776 key[MagickPathExtent];
4784 /* Need images, unless a "null:" output coder is used */
4785 if ( _images == (Image *) NULL ) {
4786 if ( LocaleCompare(arg1,"null:") == 0 )
4788 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4791 (void) FormatLocaleString(key,MagickPathExtent,"cache:%s",arg1);
4792 (void) DeleteImageRegistry(key);
4793 write_images=_images;
4795 write_images=CloneImageList(_images,_exception);
4796 write_info=CloneImageInfo(_image_info);
4797 (void) WriteImages(write_info,write_images,arg1,_exception);
4798 write_info=DestroyImageInfo(write_info);
4800 write_images=DestroyImageList(write_images);
4804 Parenthesis and Brace operations
4806 if (LocaleCompare("(",option) == 0) {
4807 /* stack 'push' images */
4815 node=cli_wand->image_list_stack;
4816 for ( ; node != (Stack *) NULL; node=node->next)
4818 if ( size >= MAX_STACK_DEPTH )
4819 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4820 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4821 if (node == (Stack *) NULL)
4822 CLIWandExceptionBreak(ResourceLimitFatalError,
4823 "MemoryAllocationFailed",option);
4824 node->data = (void *)cli_wand->wand.images;
4825 node->next = cli_wand->image_list_stack;
4826 cli_wand->image_list_stack = node;
4827 cli_wand->wand.images = NewImageList();
4829 /* handle respect-parenthesis */
4830 if (IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4831 "respect-parenthesis")) != MagickFalse)
4832 option="{"; /* fall-thru so as to push image settings too */
4835 /* fall thru to operation */
4837 if (LocaleCompare("{",option) == 0) {
4838 /* stack 'push' of image_info settings */
4846 node=cli_wand->image_info_stack;
4847 for ( ; node != (Stack *) NULL; node=node->next)
4849 if ( size >= MAX_STACK_DEPTH )
4850 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4851 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4852 if (node == (Stack *) NULL)
4853 CLIWandExceptionBreak(ResourceLimitFatalError,
4854 "MemoryAllocationFailed",option);
4856 node->data = (void *)cli_wand->wand.image_info;
4857 node->next = cli_wand->image_info_stack;
4859 cli_wand->image_info_stack = node;
4860 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4861 if (cli_wand->wand.image_info == (ImageInfo *) NULL) {
4862 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4864 cli_wand->wand.image_info = (ImageInfo *)node->data;
4865 node = (Stack *)RelinquishMagickMemory(node);
4871 if (LocaleCompare(")",option) == 0) {
4872 /* pop images from stack */
4876 node = (Stack *)cli_wand->image_list_stack;
4877 if ( node == (Stack *) NULL)
4878 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4879 cli_wand->image_list_stack = node->next;
4881 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4882 cli_wand->wand.images= (Image *)node->data;
4883 node = (Stack *)RelinquishMagickMemory(node);
4885 /* handle respect-parenthesis - of the previous 'pushed' settings */
4886 node = cli_wand->image_info_stack;
4887 if ( node != (Stack *) NULL)
4889 if (IsStringTrue(GetImageOption(
4890 cli_wand->wand.image_info,"respect-parenthesis")) != MagickFalse)
4891 option="}"; /* fall-thru so as to pop image settings too */
4897 /* fall thru to next if */
4899 if (LocaleCompare("}",option) == 0) {
4900 /* pop image_info settings from stack */
4904 node = (Stack *)cli_wand->image_info_stack;
4905 if ( node == (Stack *) NULL)
4906 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4907 cli_wand->image_info_stack = node->next;
4909 (void) DestroyImageInfo(cli_wand->wand.image_info);
4910 cli_wand->wand.image_info = (ImageInfo *)node->data;
4911 node = (Stack *)RelinquishMagickMemory(node);
4913 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4914 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4915 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4919 if (LocaleCompare("print",option+1) == 0)
4921 (void) FormatLocaleFile(stdout,"%s",arg1);
4924 if (LocaleCompare("set",option+1) == 0)
4926 /* Settings are applied to each image in memory in turn (if any).
4927 While a option: only need to be applied once globally.
4929 NOTE: rguments have not been automatically percent expaneded
4932 /* escape the 'key' once only, using first image. */
4933 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4934 if (arg1 == (char *) NULL)
4935 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4938 if (LocaleNCompare(arg1,"registry:",9) == 0)
4942 (void) DeleteImageRegistry(arg1+9);
4943 arg1=DestroyString((char *)arg1);
4946 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4947 if (arg2 == (char *) NULL) {
4948 arg1=DestroyString((char *)arg1);
4949 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4952 (void) SetImageRegistry(StringRegistryType,arg1+9,arg2,_exception);
4953 arg1=DestroyString((char *)arg1);
4954 arg2=DestroyString((char *)arg2);
4957 if (LocaleNCompare(arg1,"option:",7) == 0)
4959 /* delete equivelent artifact from all images (if any) */
4960 if (_images != (Image *) NULL)
4962 MagickResetIterator(&cli_wand->wand);
4963 while (MagickNextImage(&cli_wand->wand) != MagickFalse)
4964 (void) DeleteImageArtifact(_images,arg1+7);
4965 MagickResetIterator(&cli_wand->wand);
4967 /* now set/delete the global option as needed */
4968 /* FUTURE: make escapes in a global 'option:' delayed */
4972 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4973 if (arg2 == (char *) NULL)
4974 CLIWandExceptionBreak(OptionWarning,
4975 "InterpretPropertyFailure",option);
4977 (void) SetImageOption(_image_info,arg1+7,arg2);
4978 arg1=DestroyString((char *)arg1);
4979 arg2=DestroyString((char *)arg2);
4982 /* Set Artifacts/Properties/Attributes all images (required) */
4983 if ( _images == (Image *) NULL )
4984 CLIWandExceptArgBreak(OptionWarning,"NoImageForProperty",option,arg1);
4986 MagickResetIterator(&cli_wand->wand);
4987 while (MagickNextImage(&cli_wand->wand) != MagickFalse)
4992 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4993 if (arg2 == (char *) NULL)
4994 CLIWandExceptionBreak(OptionWarning,
4995 "InterpretPropertyFailure",option);
4997 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4998 (void) SetImageArtifact(_images,arg1+9,arg2);
4999 else if (LocaleNCompare(arg1,"property:",9) == 0)
5000 (void) SetImageProperty(_images,arg1+9,arg2,_exception);
5002 (void) SetImageProperty(_images,arg1,arg2,_exception);
5003 arg2=DestroyString((char *)arg2);
5005 MagickResetIterator(&cli_wand->wand);
5006 arg1=DestroyString((char *)arg1);
5009 if (LocaleCompare("clone",option+1) == 0) {
5014 arg1=AcquireString("-1");
5015 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
5016 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
5017 if ( cli_wand->image_list_stack == (Stack *) NULL)
5018 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
5019 new_images = (Image *)cli_wand->image_list_stack->data;
5020 if (new_images == (Image *) NULL)
5021 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
5022 new_images=CloneImages(new_images,arg1,_exception);
5023 if (new_images == (Image *) NULL)
5024 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
5025 AppendImageToList(&_images,new_images);
5029 Informational Operations.
5031 Note that these do not require either a cli-wand or images!
5032 Though currently a cli-wand much be provided regardless.
5034 if (LocaleCompare("version",option+1) == 0)
5036 ListMagickVersion(stdout);
5039 if (LocaleCompare("list",option+1) == 0) {
5041 FUTURE: This 'switch' should really be part of MagickCore
5046 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
5048 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
5053 case MagickCoderOptions:
5055 (void) ListCoderInfo((FILE *) NULL,_exception);
5058 case MagickColorOptions:
5060 (void) ListColorInfo((FILE *) NULL,_exception);
5063 case MagickConfigureOptions:
5065 (void) ListConfigureInfo((FILE *) NULL,_exception);
5068 case MagickDelegateOptions:
5070 (void) ListDelegateInfo((FILE *) NULL,_exception);
5073 case MagickFontOptions:
5075 (void) ListTypeInfo((FILE *) NULL,_exception);
5078 case MagickFormatOptions:
5079 (void) ListMagickInfo((FILE *) NULL,_exception);
5081 case MagickLocaleOptions:
5082 (void) ListLocaleInfo((FILE *) NULL,_exception);
5084 case MagickLogOptions:
5085 (void) ListLogInfo((FILE *) NULL,_exception);
5087 case MagickMagicOptions:
5088 (void) ListMagicInfo((FILE *) NULL,_exception);
5090 case MagickMimeOptions:
5091 (void) ListMimeInfo((FILE *) NULL,_exception);
5093 case MagickModuleOptions:
5094 (void) ListModuleInfo((FILE *) NULL,_exception);
5096 case MagickPolicyOptions:
5097 (void) ListPolicyInfo((FILE *) NULL,_exception);
5099 case MagickResourceOptions:
5100 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
5102 case MagickThresholdOptions:
5103 (void) ListThresholdMaps((FILE *) NULL,_exception);
5106 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
5113 CLIWandException(OptionError,"UnrecognizedOption",option);
5115 DisableMSCWarning(4127)
5116 } while (0); /* break to exit code. */
5119 /* clean up percent escape interpreted strings */
5121 arg1=DestroyString((char *)arg1);
5123 arg2=DestroyString((char *)arg2);
5133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5137 + C L I O p t i o n %
5141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5143 % CLIOption() Processes the given option using the given CLI Magick Wand.
5144 % The option arguments can be variable in number, though at this time no more
5145 % that two is actually used by any option (this may change). Excess options
5146 % are simply ignored.
5148 % If the cli_wand->command pointer is non-null, then it is assumed that the
5149 % option has already been search for up from the CommandOptions[] table in
5150 % "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
5151 % routine will do the lookup instead. The pointer is reset afterward.
5153 % This action allows the caller to lookup and pre-handle any 'special'
5154 % options, (such as implicit reads) before calling this general option
5155 % handler to deal with 'standard' command line options.
5157 % The format of the CLIOption method is:
5159 % void CLIOption(MagickCLI *cli_wand,const char *option, ...)
5161 % A description of each parameter follows:
5163 % o cli_wand: the main CLI Wand to use.
5165 % o option: The special option (with any switch char) to process
5167 % o args: any required arguments for an option (variable number)
5171 % CLIoption(cli_wand,"-read","rose:");
5172 % CLIoption(cli_wand,"-virtual-pixel","transparent");
5173 % CLIoption(cli_wand,"-distort","SRT:","30");
5174 % CLIoption(cli_wand,"-write","rotated_rose.png");
5177 WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
5179 const char /* extracted option args from args */
5186 assert(cli_wand != (MagickCLI *) NULL);
5187 assert(cli_wand->signature == MagickWandSignature);
5188 assert(cli_wand->wand.signature == MagickWandSignature);
5190 do { /* Break Code Block for error handling */
5192 /* get information about option */
5193 if ( cli_wand->command == (const OptionInfo *) NULL )
5194 cli_wand->command = GetCommandOptionInfo(option);
5196 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
5197 option, cli_wand->command->mnemonic );
5199 option_type=(CommandOptionFlags) cli_wand->command->flags;
5201 if ( option_type == UndefinedOptionFlag )
5202 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
5204 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
5206 /* deprecated options */
5207 if ( (option_type & DeprecateOptionFlag) != 0 )
5208 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
5210 /* options that this module does not handle */
5211 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
5212 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
5214 /* Get argument strings from VarArgs
5215 How can you determine if enough arguments was supplied?
5216 What happens if not enough arguments were supplied?
5219 count = (size_t) cli_wand->command->type;
5224 va_start(operands,option);
5228 arg1=(const char *) va_arg(operands, const char *);
5230 arg2=(const char *) va_arg(operands, const char *);
5234 (void) FormatLocaleFile(stderr,
5235 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
5236 option,(long) count,option_type,arg1,arg2);
5241 Call the appropriate option handler
5244 /* FUTURE: this is temporary - get 'settings' to handle distribution of
5245 settings to images attributes,proprieties,artifacts */
5246 if ( cli_wand->wand.images != (Image *) NULL )
5247 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
5248 cli_wand->wand.exception);
5250 if ( (option_type & SettingOptionFlags) != 0 ) {
5251 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
5253 FUTURE: Sync Specific Settings into Image Properities (not global)
5257 /* Operators that do not need images - read, write, stack, clone */
5258 if ((option_type & NoImageOperatorFlag) != 0)
5259 CLINoImageOperator(cli_wand, option, arg1, arg2);
5261 /* FUTURE: The not a setting part below is a temporary hack due to
5262 * some options being both a Setting and a Simple operator.
5263 * Specifically -monitor, -depth, and -colorspace */
5264 if ( cli_wand->wand.images == (Image *) NULL )
5265 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
5266 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
5267 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
5269 /* Operators which loop of individual images, simply */
5270 if ( (option_type & SimpleOperatorFlag) != 0 &&
5271 cli_wand->wand.images != (Image *) NULL) /* temp hack */
5273 ExceptionInfo *exception=AcquireExceptionInfo();
5274 (void) CLISimpleOperatorImages(cli_wand, option, arg1, arg2,exception);
5275 exception=DestroyExceptionInfo(exception);
5278 /* Operators that work on the image list as a whole */
5279 if ( (option_type & ListOperatorFlag) != 0 )
5280 (void) CLIListOperatorImages(cli_wand, option, arg1, arg2);
5282 DisableMSCWarning(4127)
5283 } while (0); /* end Break code block */
5286 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */