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 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2902 if (LocaleCompare("paint",option+1) == 0)
2904 flags=ParseGeometry(arg1,&geometry_info);
2905 if ((flags & (RhoValue|SigmaValue)) == 0)
2906 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2907 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2911 if (LocaleCompare("perceptible",option+1) == 0)
2913 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2917 if (LocaleCompare("polaroid",option+1) == 0)
2929 random_info=AcquireRandomInfo();
2930 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2931 random_info=DestroyRandomInfo(random_info);
2934 flags=ParseGeometry(arg1,&geometry_info);
2935 if ((flags & RhoValue) == 0)
2936 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2937 angle=geometry_info.rho;
2939 caption=GetImageProperty(_image,"caption",_exception);
2940 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2941 _image->interpolate,_exception);
2944 if (LocaleCompare("posterize",option+1) == 0)
2946 flags=ParseGeometry(arg1,&geometry_info);
2947 if ((flags & RhoValue) == 0)
2948 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2949 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
2950 _quantize_info->dither_method,_exception);
2953 if (LocaleCompare("preview",option+1) == 0)
2955 /* FUTURE: should be a 'Genesis' option?
2956 Option however is also in WandSettingOptionInfo()
2959 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2961 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2963 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
2966 if (LocaleCompare("profile",option+1) == 0)
2980 /* Note: arguments do not have percent escapes expanded */
2982 { /* Remove a profile from the _image. */
2983 (void) ProfileImage(_image,arg1,(const unsigned char *)
2987 /* Associate a profile with the _image. */
2988 profile_info=CloneImageInfo(_image_info);
2989 profile=GetImageProfile(_image,"iptc");
2990 if (profile != (StringInfo *) NULL)
2991 profile_info->profile=(void *) CloneStringInfo(profile);
2992 profile_image=GetImageCache(profile_info,arg1,_exception);
2993 profile_info=DestroyImageInfo(profile_info);
2994 if (profile_image == (Image *) NULL)
2999 profile_info=CloneImageInfo(_image_info);
3000 (void) CopyMagickString(profile_info->filename,arg1,
3002 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
3003 if (profile != (StringInfo *) NULL)
3005 (void) SetImageInfo(profile_info,0,_exception);
3006 (void) ProfileImage(_image,profile_info->magick,
3007 GetStringInfoDatum(profile),(size_t)
3008 GetStringInfoLength(profile),_exception);
3009 profile=DestroyStringInfo(profile);
3011 profile_info=DestroyImageInfo(profile_info);
3014 ResetImageProfileIterator(profile_image);
3015 name=GetNextImageProfile(profile_image);
3016 while (name != (const char *) NULL)
3018 profile=GetImageProfile(profile_image,name);
3019 if (profile != (StringInfo *) NULL)
3020 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3021 (size_t) GetStringInfoLength(profile),_exception);
3022 name=GetNextImageProfile(profile_image);
3024 profile_image=DestroyImage(profile_image);
3027 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3031 if (LocaleCompare("raise",option+1) == 0)
3033 if (IsGeometry(arg1) == MagickFalse)
3034 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3035 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3036 (void) RaiseImage(_image,&geometry,IsNormalOp,_exception);
3039 if (LocaleCompare("random-threshold",option+1) == 0)
3045 if (IsGeometry(arg1) == MagickFalse)
3046 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3048 max_threshold=(double) QuantumRange;
3049 flags=ParseGeometry(arg1,&geometry_info);
3050 min_threshold=geometry_info.rho;
3051 max_threshold=geometry_info.sigma;
3052 if ((flags & SigmaValue) == 0)
3053 max_threshold=min_threshold;
3054 if (strchr(arg1,'%') != (char *) NULL)
3056 max_threshold*=(double) (0.01*QuantumRange);
3057 min_threshold*=(double) (0.01*QuantumRange);
3059 (void) RandomThresholdImage(_image,min_threshold,max_threshold,
3063 if (LocaleCompare("range-threshold",option+1) == 0)
3066 Range threshold image.
3068 if (IsGeometry(arg1) == MagickFalse)
3069 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3070 flags=ParseGeometry(arg1,&geometry_info);
3071 if ((flags & SigmaValue) == 0)
3072 geometry_info.sigma=geometry_info.rho;
3073 if ((flags & XiValue) == 0)
3074 geometry_info.xi=geometry_info.sigma;
3075 if ((flags & PsiValue) == 0)
3076 geometry_info.psi=geometry_info.xi;
3077 if (strchr(arg1,'%') != (char *) NULL)
3079 geometry_info.rho*=(double) (0.01*QuantumRange);
3080 geometry_info.sigma*=(double) (0.01*QuantumRange);
3081 geometry_info.xi*=(double) (0.01*QuantumRange);
3082 geometry_info.psi*=(double) (0.01*QuantumRange);
3084 (void) RangeThresholdImage(_image,geometry_info.rho,
3085 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3088 if (LocaleCompare("read-mask",option+1) == 0)
3090 /* Note: arguments do not have percent escapes expanded */
3095 { /* Remove a mask. */
3096 (void) SetImageMask(_image,ReadPixelMask,(Image *) NULL,
3100 /* Set the image mask. */
3101 mask=GetImageCache(_image_info,arg1,_exception);
3102 if (mask == (Image *) NULL)
3104 (void) SetImageMask(_image,ReadPixelMask,mask,_exception);
3105 mask=DestroyImage(mask);
3108 if (LocaleCompare("recolor",option+1) == 0)
3110 CLIWandWarnReplaced("-color-matrix");
3111 (void) CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL,
3114 if (LocaleCompare("region",option+1) == 0)
3118 (void) SetImageRegionMask(_image,WritePixelMask,
3119 (const RectangleInfo *) NULL,_exception);
3122 if (IsGeometry(arg1) == MagickFalse)
3123 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3124 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3125 (void) SetImageRegionMask(_image,WritePixelMask,&geometry,_exception);
3128 if (LocaleCompare("remap",option+1) == 0)
3130 /* Note: arguments do not have percent escapes expanded */
3134 remap_image=GetImageCache(_image_info,arg1,_exception);
3135 if (remap_image == (Image *) NULL)
3137 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
3138 remap_image=DestroyImage(remap_image);
3141 if (LocaleCompare("repage",option+1) == 0)
3145 if (IsGeometry(arg1) == MagickFalse)
3146 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3148 (void) ResetImagePage(_image,arg1);
3151 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
3154 if (LocaleCompare("resample",option+1) == 0)
3156 /* FUTURE: Roll into a resize special operation */
3157 flags=ParseGeometry(arg1,&geometry_info);
3158 if ((flags & (RhoValue|SigmaValue)) == 0)
3159 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3160 if ((flags & SigmaValue) == 0)
3161 geometry_info.sigma=geometry_info.rho;
3162 new_image=ResampleImage(_image,geometry_info.rho,
3163 geometry_info.sigma,_image->filter,_exception);
3166 if (LocaleCompare("resize",option+1) == 0)
3168 if (IsGeometry(arg1) == MagickFalse)
3169 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3170 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3171 new_image=ResizeImage(_image,geometry.width,geometry.height,
3172 _image->filter,_exception);
3175 if (LocaleCompare("roll",option+1) == 0)
3177 if (IsGeometry(arg1) == MagickFalse)
3178 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3179 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3180 if ((flags & PercentValue) != 0)
3182 geometry.x*=(double) _image->columns/100.0;
3183 geometry.y*=(double) _image->rows/100.0;
3185 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
3188 if (LocaleCompare("rotate",option+1) == 0)
3190 flags=ParseGeometry(arg1,&geometry_info);
3191 if ((flags & RhoValue) == 0)
3192 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3193 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
3195 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3197 new_image=RotateImage(_image,geometry_info.rho,_exception);
3200 if (LocaleCompare("rotational-blur",option+1) == 0)
3202 flags=ParseGeometry(arg1,&geometry_info);
3203 if ((flags & RhoValue) == 0)
3204 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3205 new_image=RotationalBlurImage(_image,geometry_info.rho,_exception);
3208 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3212 if (LocaleCompare("sample",option+1) == 0)
3214 /* FUTURE: Roll into a resize special operator */
3215 if (IsGeometry(arg1) == MagickFalse)
3216 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3217 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3218 new_image=SampleImage(_image,geometry.width,geometry.height,
3222 if (LocaleCompare("scale",option+1) == 0)
3224 /* FUTURE: Roll into a resize special operator */
3225 if (IsGeometry(arg1) == MagickFalse)
3226 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3227 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3228 new_image=ScaleImage(_image,geometry.width,geometry.height,
3232 if (LocaleCompare("segment",option+1) == 0)
3234 flags=ParseGeometry(arg1,&geometry_info);
3235 if ((flags & (RhoValue|SigmaValue)) == 0)
3236 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3237 if ((flags & SigmaValue) == 0)
3238 geometry_info.sigma=1.0;
3239 (void) SegmentImage(_image,_image->colorspace,
3240 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3244 if (LocaleCompare("selective-blur",option+1) == 0)
3246 flags=ParseGeometry(arg1,&geometry_info);
3247 if ((flags & (RhoValue|SigmaValue)) == 0)
3248 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3249 if ((flags & SigmaValue) == 0)
3250 geometry_info.sigma=1.0;
3251 if ((flags & PercentValue) != 0)
3252 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3253 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3254 geometry_info.sigma,geometry_info.xi,_exception);
3257 if (LocaleCompare("separate",option+1) == 0)
3259 /* WARNING: This can generate multiple images! */
3260 /* FUTURE - this may be replaced by a "-channel" method */
3261 new_image=SeparateImages(_image,_exception);
3264 if (LocaleCompare("sepia-tone",option+1) == 0)
3266 if (IsGeometry(arg1) == MagickFalse)
3267 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3268 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3269 (double) QuantumRange+1.0),_exception);
3272 if (LocaleCompare("shade",option+1) == 0)
3274 flags=ParseGeometry(arg1,&geometry_info);
3275 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3276 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3277 new_image=ShadeImage(_image,IsNormalOp,geometry_info.rho,
3278 geometry_info.sigma,_exception);
3281 if (LocaleCompare("shadow",option+1) == 0)
3283 flags=ParseGeometry(arg1,&geometry_info);
3284 if ((flags & (RhoValue|SigmaValue)) == 0)
3285 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3286 if ((flags & SigmaValue) == 0)
3287 geometry_info.sigma=1.0;
3288 if ((flags & XiValue) == 0)
3289 geometry_info.xi=4.0;
3290 if ((flags & PsiValue) == 0)
3291 geometry_info.psi=4.0;
3292 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3293 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3294 ceil(geometry_info.psi-0.5),_exception);
3297 if (LocaleCompare("sharpen",option+1) == 0)
3299 flags=ParseGeometry(arg1,&geometry_info);
3300 if ((flags & (RhoValue|SigmaValue)) == 0)
3301 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3302 if ((flags & SigmaValue) == 0)
3303 geometry_info.sigma=1.0;
3304 if ((flags & XiValue) == 0)
3305 geometry_info.xi=0.0;
3306 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3310 if (LocaleCompare("shave",option+1) == 0)
3312 if (IsGeometry(arg1) == MagickFalse)
3313 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3314 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3315 new_image=ShaveImage(_image,&geometry,_exception);
3318 if (LocaleCompare("shear",option+1) == 0)
3320 flags=ParseGeometry(arg1,&geometry_info);
3321 if ((flags & RhoValue) == 0)
3322 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3323 if ((flags & SigmaValue) == 0)
3324 geometry_info.sigma=geometry_info.rho;
3325 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3329 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
3331 flags=ParseGeometry(arg1,&geometry_info);
3332 if ((flags & RhoValue) == 0)
3333 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3334 if ((flags & SigmaValue) == 0)
3335 geometry_info.sigma=(double) QuantumRange/2.0;
3336 if ((flags & PercentValue) != 0)
3337 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3339 (void) SigmoidalContrastImage(_image,IsNormalOp,geometry_info.rho,
3340 geometry_info.sigma,_exception);
3343 if (LocaleCompare("sketch",option+1) == 0)
3345 flags=ParseGeometry(arg1,&geometry_info);
3346 if ((flags & (RhoValue|SigmaValue)) == 0)
3347 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3348 if ((flags & SigmaValue) == 0)
3349 geometry_info.sigma=1.0;
3350 new_image=SketchImage(_image,geometry_info.rho,
3351 geometry_info.sigma,geometry_info.xi,_exception);
3354 if (LocaleCompare("solarize",option+1) == 0)
3356 if (IsGeometry(arg1) == MagickFalse)
3357 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3358 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3359 QuantumRange+1.0),_exception);
3362 if (LocaleCompare("sparse-color",option+1) == 0)
3364 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3366 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3368 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3372 if (LocaleCompare("splice",option+1) == 0)
3374 if (IsGeometry(arg1) == MagickFalse)
3375 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3376 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
3377 new_image=SpliceImage(_image,&geometry,_exception);
3380 if (LocaleCompare("spread",option+1) == 0)
3382 flags=ParseGeometry(arg1,&geometry_info);
3383 if ((flags & RhoValue) == 0)
3384 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3385 new_image=SpreadImage(_image,_image->interpolate,geometry_info.rho,
3389 if (LocaleCompare("statistic",option+1) == 0)
3391 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3393 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
3395 flags=ParseGeometry(arg2,&geometry_info);
3396 if ((flags & RhoValue) == 0)
3397 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3398 if ((flags & SigmaValue) == 0)
3399 geometry_info.sigma=geometry_info.rho;
3400 new_image=StatisticImage(_image,(StatisticType)parse,
3401 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3405 if (LocaleCompare("strip",option+1) == 0)
3407 (void) StripImage(_image,_exception);
3410 if (LocaleCompare("swirl",option+1) == 0)
3412 flags=ParseGeometry(arg1,&geometry_info);
3413 if ((flags & RhoValue) == 0)
3414 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3415 new_image=SwirlImage(_image,geometry_info.rho,
3416 _image->interpolate,_exception);
3419 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3423 if (LocaleCompare("threshold",option+1) == 0)
3428 threshold=(double) QuantumRange/2;
3430 if (IsGeometry(arg1) == MagickFalse)
3431 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3432 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
3434 (void) BilevelImage(_image,threshold,_exception);
3437 if (LocaleCompare("thumbnail",option+1) == 0)
3439 if (IsGeometry(arg1) == MagickFalse)
3440 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3441 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3442 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3446 if (LocaleCompare("tint",option+1) == 0)
3448 if (IsGeometry(arg1) == MagickFalse)
3449 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3450 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
3453 if (LocaleCompare("transform",option+1) == 0)
3455 CLIWandWarnReplaced("+distort AffineProjection");
3456 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
3459 if (LocaleCompare("transparent",option+1) == 0)
3464 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3465 (void) TransparentPaintImage(_image,&target,(Quantum)
3466 TransparentAlpha,IsPlusOp,_exception);
3469 if (LocaleCompare("transpose",option+1) == 0)
3471 new_image=TransposeImage(_image,_exception);
3474 if (LocaleCompare("transverse",option+1) == 0)
3476 new_image=TransverseImage(_image,_exception);
3479 if (LocaleCompare("trim",option+1) == 0)
3481 new_image=TrimImage(_image,_exception);
3484 if (LocaleCompare("type",option+1) == 0)
3486 /* Note that "type" setting should have already been defined */
3487 (void) SetImageType(_image,_image_info->type,_exception);
3490 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3494 if (LocaleCompare("unique",option+1) == 0)
3496 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3497 Option is not documented, bt appears to be for "identify".
3498 We may need a identify specific verbose!
3501 (void) DeleteImageArtifact(_image,"identify:unique-colors");
3504 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3505 (void) SetImageArtifact(_image,"verbose","true");
3508 if (LocaleCompare("unique-colors",option+1) == 0)
3510 new_image=UniqueImageColors(_image,_exception);
3513 if (LocaleCompare("unsharp",option+1) == 0)
3515 flags=ParseGeometry(arg1,&geometry_info);
3516 if ((flags & (RhoValue|SigmaValue)) == 0)
3517 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3518 if ((flags & SigmaValue) == 0)
3519 geometry_info.sigma=1.0;
3520 if ((flags & XiValue) == 0)
3521 geometry_info.xi=1.0;
3522 if ((flags & PsiValue) == 0)
3523 geometry_info.psi=0.05;
3524 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3525 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
3528 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3532 if (LocaleCompare("verbose",option+1) == 0)
3534 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
3535 three places! ImageArtifact ImageOption _image_info->verbose
3536 Some how new images also get this artifact!
3538 (void) SetImageArtifact(_image,option+1,
3539 IfNormalOp ? "true" : "false" );
3542 if (LocaleCompare("vignette",option+1) == 0)
3544 flags=ParseGeometry(arg1,&geometry_info);
3545 if ((flags & (RhoValue|SigmaValue)) == 0)
3546 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3547 if ((flags & SigmaValue) == 0)
3548 geometry_info.sigma=1.0;
3549 if ((flags & XiValue) == 0)
3550 geometry_info.xi=0.1*_image->columns;
3551 if ((flags & PsiValue) == 0)
3552 geometry_info.psi=0.1*_image->rows;
3553 if ((flags & PercentValue) != 0)
3555 geometry_info.xi*=(double) _image->columns/100.0;
3556 geometry_info.psi*=(double) _image->rows/100.0;
3558 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3559 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3560 ceil(geometry_info.psi-0.5),_exception);
3563 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3567 if (LocaleCompare("wave",option+1) == 0)
3569 flags=ParseGeometry(arg1,&geometry_info);
3570 if ((flags & (RhoValue|SigmaValue)) == 0)
3571 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3572 if ((flags & SigmaValue) == 0)
3573 geometry_info.sigma=1.0;
3574 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3575 _image->interpolate,_exception);
3578 if (LocaleCompare("wavelet-denoise",option+1) == 0)
3580 flags=ParseGeometry(arg1,&geometry_info);
3581 if ((flags & RhoValue) == 0)
3582 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3583 if ((flags & PercentValue) != 0)
3585 geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
3586 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
3588 if ((flags & SigmaValue) == 0)
3589 geometry_info.sigma=0.0;
3590 new_image=WaveletDenoiseImage(_image,geometry_info.rho,
3591 geometry_info.sigma,_exception);
3594 if (LocaleCompare("white-threshold",option+1) == 0)
3596 if (IsGeometry(arg1) == MagickFalse)
3597 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3598 (void) WhiteThresholdImage(_image,arg1,_exception);
3601 if (LocaleCompare("write-mask",option+1) == 0)
3603 /* Note: arguments do not have percent escapes expanded */
3608 { /* Remove a mask. */
3609 (void) SetImageMask(_image,WritePixelMask,(Image *) NULL,
3613 /* Set the image mask. */
3614 mask=GetImageCache(_image_info,arg1,_exception);
3615 if (mask == (Image *) NULL)
3617 (void) SetImageMask(_image,WritePixelMask,mask,_exception);
3618 mask=DestroyImage(mask);
3621 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3624 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3626 /* clean up percent escape interpreted strings */
3628 arg1=DestroyString((char *)arg1);
3630 arg2=DestroyString((char *)arg2);
3632 /* Replace current image with any image that was generated
3633 and set image point to last image (so image->next is correct) */
3634 if (new_image != (Image *) NULL)
3635 ReplaceImageInListReturnLast(&_image,new_image);
3640 #undef _quantize_info
3649 WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
3650 const char *option,const char *arg1,const char *arg2,ExceptionInfo *exception)
3652 #if !USE_WAND_METHODS
3658 assert(cli_wand != (MagickCLI *) NULL);
3659 assert(cli_wand->signature == MagickWandSignature);
3660 assert(cli_wand->wand.signature == MagickWandSignature);
3661 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3663 if (cli_wand->wand.debug != MagickFalse)
3664 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3665 "- Simple Operator: %s \"%s\" \"%s\"", option,arg1,arg2);
3667 #if !USE_WAND_METHODS
3668 /* FUTURE add appropriate tracing */
3670 n=GetImageListLength(cli_wand->wand.images);
3671 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3674 CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
3675 if ( cli_wand->wand.images->next == (Image *) NULL )
3677 cli_wand->wand.images=cli_wand->wand.images->next;
3680 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3682 MagickResetIterator(&cli_wand->wand);
3683 while (MagickNextImage(&cli_wand->wand) != MagickFalse)
3684 (void) CLISimpleOperatorImage(cli_wand, option, arg1, arg2,exception);
3685 MagickResetIterator(&cli_wand->wand);
3691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3695 + C L I L i s t O p e r a t o r I m a g e s %
3699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3701 % CLIListOperatorImages() applies a single operation that is apply to the
3702 % entire image list as a whole. The result is often a complete replacment
3703 % of the image list with a completely new list, or with just a single image
3706 % The format of the MogrifyImage method is:
3708 % MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3709 % const char *option,const char *arg1,const char *arg2)
3711 % A description of each parameter follows:
3713 % o cli_wand: structure holding settings to be applied
3715 % o option: The option string for the operation
3717 % o arg1, arg2: optional argument strings to the operation
3718 % arg2 is currently not used
3721 WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
3722 const char *option,const char *arg1n,const char *arg2n)
3724 const char /* percent escaped versions of the args */
3737 #define _image_info (cli_wand->wand.image_info)
3738 #define _images (cli_wand->wand.images)
3739 #define _exception (cli_wand->wand.exception)
3740 #define _draw_info (cli_wand->draw_info)
3741 #define _quantize_info (cli_wand->quantize_info)
3742 #define _process_flags (cli_wand->process_flags)
3743 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
3744 #define IfNormalOp (*option=='-')
3745 #define IfPlusOp (*option!='-')
3746 #define IsNormalOp IfNormalOp ? MagickTrue : MagickFalse
3748 assert(cli_wand != (MagickCLI *) NULL);
3749 assert(cli_wand->signature == MagickWandSignature);
3750 assert(cli_wand->wand.signature == MagickWandSignature);
3751 assert(_images != (Image *) NULL); /* _images must be present */
3753 if (cli_wand->wand.debug != MagickFalse)
3754 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
3755 "- List Operator: %s \"%s\" \"%s\"", option,
3756 arg1n == (const char *) NULL ? "null" : arg1n,
3757 arg2n == (const char *) NULL ? "null" : arg2n);
3762 /* Interpret Percent Escapes in Arguments - using first image */
3763 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3764 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3765 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3766 /* Interpret Percent escapes in argument 1 */
3767 if (arg1n != (char *) NULL) {
3768 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3769 if (arg1 == (char *) NULL) {
3770 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3771 arg1=arg1n; /* use the given argument as is */
3774 if (arg2n != (char *) NULL) {
3775 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3776 if (arg2 == (char *) NULL) {
3777 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3778 arg2=arg2n; /* use the given argument as is */
3782 #undef _process_flags
3786 new_images=NewImageList();
3788 switch (*(option+1))
3792 if (LocaleCompare("append",option+1) == 0)
3794 new_images=AppendImages(_images,IsNormalOp,_exception);
3797 if (LocaleCompare("average",option+1) == 0)
3799 CLIWandWarnReplaced("-evaluate-sequence Mean");
3800 (void) CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",
3804 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3808 if (LocaleCompare("channel-fx",option+1) == 0)
3810 new_images=ChannelFxImage(_images,arg1,_exception);
3813 if (LocaleCompare("clut",option+1) == 0)
3818 /* FUTURE - make this a compose option, and thus can be used
3819 with layers compose or even compose last image over all other
3822 new_images=RemoveFirstImageFromList(&_images);
3823 clut_image=RemoveLastImageFromList(&_images);
3824 /* FUTURE - produce Exception, rather than silent fail */
3825 if (clut_image == (Image *) NULL)
3827 (void) ClutImage(new_images,clut_image,new_images->interpolate,
3829 clut_image=DestroyImage(clut_image);
3832 if (LocaleCompare("coalesce",option+1) == 0)
3834 new_images=CoalesceImages(_images,_exception);
3837 if (LocaleCompare("combine",option+1) == 0)
3839 parse=(ssize_t) _images->colorspace;
3840 if (_images->number_channels < GetImageListLength(_images))
3841 parse=sRGBColorspace;
3843 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
3845 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
3847 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
3850 if (LocaleCompare("compare",option+1) == 0)
3863 Mathematically and visually annotate the difference between an
3864 image and its reconstruction.
3866 image=RemoveFirstImageFromList(&_images);
3867 reconstruct_image=RemoveFirstImageFromList(&_images);
3868 /* FUTURE - produce Exception, rather than silent fail */
3869 if (reconstruct_image == (Image *) NULL)
3871 metric=UndefinedErrorMetric;
3872 option=GetImageOption(_image_info,"metric");
3873 if (option != (const char *) NULL)
3874 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
3875 MagickFalse,option);
3876 new_images=CompareImages(image,reconstruct_image,metric,&distortion,
3879 reconstruct_image=DestroyImage(reconstruct_image);
3880 image=DestroyImage(image);
3883 if (LocaleCompare("complex",option+1) == 0)
3885 parse=ParseCommandOption(MagickComplexOptions,MagickFalse,arg1);
3887 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3889 new_images=ComplexImages(_images,(ComplexOperator) parse,_exception);
3892 if (LocaleCompare("composite",option+1) == 0)
3910 /* Compose value from "-compose" option only */
3911 value=GetImageOption(_image_info,"compose");
3912 if (value == (const char *) NULL)
3913 compose=OverCompositeOp; /* use Over not source_image->compose */
3915 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3918 /* Get "clip-to-self" expert setting (false is normal) */
3919 clip_to_self=GetCompositeClipToSelf(compose);
3920 value=GetImageOption(_image_info,"compose:clip-to-self");
3921 if (value != (const char *) NULL)
3922 clip_to_self=IsStringTrue(value);
3923 value=GetImageOption(_image_info,"compose:outside-overlay");
3924 if (value != (const char *) NULL)
3925 clip_to_self=IsStringFalse(value); /* deprecated */
3927 new_images=RemoveFirstImageFromList(&_images);
3928 source_image=RemoveFirstImageFromList(&_images);
3929 if (source_image == (Image *) NULL)
3930 break; /* FUTURE - produce Exception, rather than silent fail */
3932 /* FUTURE - this should not be here! - should be part of -geometry */
3933 if (source_image->geometry != (char *) NULL)
3938 (void) ParseRegionGeometry(source_image,source_image->geometry,
3939 &resize_geometry,_exception);
3940 if ((source_image->columns != resize_geometry.width) ||
3941 (source_image->rows != resize_geometry.height))
3946 resize_image=ResizeImage(source_image,resize_geometry.width,
3947 resize_geometry.height,source_image->filter,_exception);
3948 if (resize_image != (Image *) NULL)
3950 source_image=DestroyImage(source_image);
3951 source_image=resize_image;
3955 SetGeometry(source_image,&geometry);
3956 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3957 GravityAdjustGeometry(new_images->columns,new_images->rows,
3958 new_images->gravity, &geometry);
3959 mask_image=RemoveFirstImageFromList(&_images);
3960 if (mask_image == (Image *) NULL)
3961 status&=CompositeImage(new_images,source_image,compose,clip_to_self,
3962 geometry.x,geometry.y,_exception);
3965 if ((compose == DisplaceCompositeOp) ||
3966 (compose == DistortCompositeOp))
3968 status&=CompositeImage(source_image,mask_image,
3969 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3970 status&=CompositeImage(new_images,source_image,compose,
3971 clip_to_self,geometry.x,geometry.y,_exception);
3978 clone_image=CloneImage(new_images,0,0,MagickTrue,_exception);
3979 if (clone_image == (Image *) NULL)
3981 status&=CompositeImage(new_images,source_image,compose,
3982 clip_to_self,geometry.x,geometry.y,_exception);
3983 status&=CompositeImage(new_images,mask_image,
3984 CopyAlphaCompositeOp,MagickTrue,0,0,_exception);
3985 status&=CompositeImage(clone_image,new_images,OverCompositeOp,
3986 clip_to_self,0,0,_exception);
3987 new_images=DestroyImage(new_images);
3988 new_images=clone_image;
3990 mask_image=DestroyImage(mask_image);
3992 source_image=DestroyImage(source_image);
3995 if (LocaleCompare("copy",option+1) == 0)
4009 if (IsGeometry(arg1) == MagickFalse)
4010 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4011 if (IsGeometry(arg2) == MagickFalse)
4012 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4013 (void) ParsePageGeometry(_images,arg2,&geometry,_exception);
4014 offset.x=geometry.x;
4015 offset.y=geometry.y;
4016 source_image=_images;
4017 if (source_image->next != (Image *) NULL)
4018 source_image=source_image->next;
4019 (void) ParsePageGeometry(source_image,arg1,&geometry,_exception);
4020 (void) CopyImagePixels(_images,source_image,&geometry,&offset,
4024 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4028 if (LocaleCompare("deconstruct",option+1) == 0)
4030 CLIWandWarnReplaced("-layer CompareAny");
4031 (void) CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
4034 if (LocaleCompare("delete",option+1) == 0)
4037 DeleteImages(&_images,arg1,_exception);
4039 DeleteImages(&_images,"-1",_exception);
4042 if (LocaleCompare("duplicate",option+1) == 0)
4052 if (IsGeometry(arg1) == MagickFalse)
4053 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
4055 number_duplicates=(size_t) StringToLong(arg1);
4057 if (p == (const char *) NULL)
4058 new_images=DuplicateImages(_images,number_duplicates,"-1",
4061 new_images=DuplicateImages(_images,number_duplicates,p,
4065 new_images=DuplicateImages(_images,1,"-1",_exception);
4066 AppendImageToList(&_images, new_images);
4067 new_images=(Image *) NULL;
4070 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4074 if (LocaleCompare("evaluate-sequence",option+1) == 0)
4076 parse=ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
4078 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
4080 new_images=EvaluateImages(_images,(MagickEvaluateOperator) parse,
4084 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4088 if (LocaleCompare("fft",option+1) == 0)
4090 new_images=ForwardFourierTransformImage(_images,IsNormalOp,
4094 if (LocaleCompare("flatten",option+1) == 0)
4096 /* REDIRECTED to use -layers flatten instead */
4097 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
4100 if (LocaleCompare("fx",option+1) == 0)
4102 new_images=FxImage(_images,arg1,_exception);
4105 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4109 if (LocaleCompare("hald-clut",option+1) == 0)
4111 /* FUTURE - make this a compose option (and thus layers compose )
4112 or perhaps compose last image over all other _images.
4117 new_images=RemoveFirstImageFromList(&_images);
4118 hald_image=RemoveLastImageFromList(&_images);
4119 if (hald_image == (Image *) NULL)
4121 (void) HaldClutImage(new_images,hald_image,_exception);
4122 hald_image=DestroyImage(hald_image);
4125 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4129 if (LocaleCompare("ift",option+1) == 0)
4135 magnitude_image=RemoveFirstImageFromList(&_images);
4136 phase_image=RemoveFirstImageFromList(&_images);
4137 /* FUTURE - produce Exception, rather than silent fail */
4138 if (phase_image == (Image *) NULL)
4140 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
4141 IsNormalOp,_exception);
4142 magnitude_image=DestroyImage(magnitude_image);
4143 phase_image=DestroyImage(phase_image);
4146 if (LocaleCompare("insert",option+1) == 0)
4155 if (IfNormalOp && (IsGeometry(arg1) == MagickFalse))
4156 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4158 insert_image=RemoveLastImageFromList(&_images);
4160 index=(ssize_t) StringToLong(arg1);
4161 index_image=insert_image;
4163 PrependImageToList(&_images,insert_image);
4164 else if (index == (ssize_t) GetImageListLength(_images))
4165 AppendImageToList(&_images,insert_image);
4168 index_image=GetImageFromList(_images,index-1);
4169 if (index_image == (Image *) NULL)
4170 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
4171 InsertImageInList(&index_image,insert_image);
4173 _images=GetFirstImageInList(index_image);
4176 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4180 if (LocaleCompare("layers",option+1) == 0)
4182 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4184 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4186 switch ((LayerMethod) parse)
4190 new_images=CoalesceImages(_images,_exception);
4193 case CompareAnyLayer:
4194 case CompareClearLayer:
4195 case CompareOverlayLayer:
4198 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
4205 case TrimBoundsLayer:
4207 new_images=MergeImageLayers(_images,(LayerMethod) parse,
4213 new_images=DisposeImages(_images,_exception);
4216 case OptimizeImageLayer:
4218 new_images=OptimizeImageLayers(_images,_exception);
4221 case OptimizePlusLayer:
4223 new_images=OptimizePlusImageLayers(_images,_exception);
4226 case OptimizeTransLayer:
4228 OptimizeImageTransparency(_images,_exception);
4231 case RemoveDupsLayer:
4233 RemoveDuplicateLayers(&_images,_exception);
4236 case RemoveZeroLayer:
4238 RemoveZeroDelayLayers(&_images,_exception);
4242 { /* General Purpose, GIF Animation Optimizer. */
4243 new_images=CoalesceImages(_images,_exception);
4244 if (new_images == (Image *) NULL)
4246 _images=DestroyImageList(_images);
4247 _images=OptimizeImageLayers(new_images,_exception);
4248 if (_images == (Image *) NULL)
4250 new_images=DestroyImageList(new_images);
4251 OptimizeImageTransparency(_images,_exception);
4252 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4256 case CompositeLayer:
4270 value=GetImageOption(_image_info,"compose");
4271 compose=OverCompositeOp; /* Default to Over */
4272 if (value != (const char *) NULL)
4273 compose=(CompositeOperator) ParseCommandOption(
4274 MagickComposeOptions,MagickFalse,value);
4276 /* Split image sequence at the first 'NULL:' image. */
4278 while (source != (Image *) NULL)
4280 source=GetNextImageInList(source);
4281 if ((source != (Image *) NULL) &&
4282 (LocaleCompare(source->magick,"NULL") == 0))
4285 if (source != (Image *) NULL)
4287 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4288 (GetNextImageInList(source) == (Image *) NULL))
4289 source=(Image *) NULL;
4291 { /* Separate the two lists, junk the null: image. */
4292 source=SplitImageList(source->previous);
4293 DeleteImageFromList(&source);
4296 if (source == (Image *) NULL)
4298 (void) ThrowMagickException(_exception,GetMagickModule(),
4299 OptionError,"MissingNullSeparator","layers Composite");
4302 /* Adjust offset with gravity and virtual canvas. */
4303 SetGeometry(_images,&geometry);
4304 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
4305 geometry.width=source->page.width != 0 ?
4306 source->page.width : source->columns;
4307 geometry.height=source->page.height != 0 ?
4308 source->page.height : source->rows;
4309 GravityAdjustGeometry(_images->page.width != 0 ?
4310 _images->page.width : _images->columns,
4311 _images->page.height != 0 ? _images->page.height :
4312 _images->rows,_images->gravity,&geometry);
4314 /* Compose the two image sequences together */
4315 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4317 source=DestroyImageList(source);
4323 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4327 if (LocaleCompare("map",option+1) == 0)
4329 CLIWandWarnReplaced("+remap");
4330 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4333 if (LocaleCompare("metric",option+1) == 0)
4335 (void) SetImageOption(_image_info,option+1,arg1);
4338 if (LocaleCompare("morph",option+1) == 0)
4343 if (IsGeometry(arg1) == MagickFalse)
4344 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4345 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4347 if (morph_image == (Image *) NULL)
4349 _images=DestroyImageList(_images);
4350 _images=morph_image;
4353 if (LocaleCompare("mosaic",option+1) == 0)
4355 /* REDIRECTED to use -layers mosaic instead */
4356 (void) CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
4359 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4363 if (LocaleCompare("poly",option+1) == 0)
4371 /* convert argument string into an array of doubles */
4372 args = StringToArrayOfDoubles(arg1,&count,_exception);
4373 if (args == (double *) NULL )
4374 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg1);
4375 new_images=PolynomialImage(_images,(size_t) (count >> 1),args,
4377 args=(double *) RelinquishMagickMemory(args);
4380 if (LocaleCompare("process",option+1) == 0)
4382 /* FUTURE: better parsing using ScriptToken() from string ??? */
4390 arguments=StringToArgv(arg1,&number_arguments);
4391 if (arguments == (char **) NULL)
4393 if (strchr(arguments[1],'=') != (char *) NULL)
4414 Support old style syntax, filter="-option arg1".
4416 assert(arg1 != (const char *) NULL);
4417 length=strlen(arg1);
4418 token=(char *) NULL;
4419 if (~length >= (MagickPathExtent-1))
4420 token=(char *) AcquireQuantumMemory(length+MagickPathExtent,
4422 if (token == (char *) NULL)
4426 token_info=AcquireTokenInfo();
4427 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4428 "\"",'\0',&breaker,&next,"e);
4429 token_info=DestroyTokenInfo(token_info);
4435 argv=(&(arguments[next]));
4436 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4439 token=DestroyString(token);
4442 (void) SubstituteString(&arguments[1],"-","");
4443 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4444 number_arguments-2,(const char **) arguments+2,_exception);
4445 for (j=0; j < number_arguments; j++)
4446 arguments[j]=DestroyString(arguments[j]);
4447 arguments=(char **) RelinquishMagickMemory(arguments);
4450 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4454 if (LocaleCompare("remap",option+1) == 0)
4456 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4459 if (LocaleCompare("reverse",option+1) == 0)
4461 ReverseImageList(&_images);
4464 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4468 if (LocaleCompare("smush",option+1) == 0)
4470 /* FUTURE: this option needs more work to make better */
4474 if (IsGeometry(arg1) == MagickFalse)
4475 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4476 offset=(ssize_t) StringToLong(arg1);
4477 new_images=SmushImages(_images,IsNormalOp,offset,_exception);
4480 if (LocaleCompare("subimage",option+1) == 0)
4498 base_image=GetImageFromList(_images,0);
4499 compare_image=GetImageFromList(_images,1);
4501 /* Comparision Metric */
4502 metric=UndefinedErrorMetric;
4503 value=GetImageOption(_image_info,"metric");
4504 if (value != (const char *) NULL)
4505 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4508 new_images=SimilarityImage(base_image,compare_image,metric,0.0,
4509 &offset,&similarity,_exception);
4511 if (new_images != (Image *) NULL)
4514 result[MagickPathExtent];
4516 (void) FormatLocaleString(result,MagickPathExtent,"%lf",
4518 (void) SetImageProperty(new_images,"subimage:similarity",result,
4520 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",(long)
4522 (void) SetImageProperty(new_images,"subimage:x",result,
4524 (void) FormatLocaleString(result,MagickPathExtent,"%+ld",(long)
4526 (void) SetImageProperty(new_images,"subimage:y",result,
4528 (void) FormatLocaleString(result,MagickPathExtent,
4529 "%lux%lu%+ld%+ld",(unsigned long) offset.width,(unsigned long)
4530 offset.height,(long) offset.x,(long) offset.y);
4531 (void) SetImageProperty(new_images,"subimage:offset",result,
4536 if (LocaleCompare("swap",option+1) == 0)
4557 flags=ParseGeometry(arg1,&geometry_info);
4558 if ((flags & RhoValue) == 0)
4559 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4560 index=(ssize_t) geometry_info.rho;
4561 if ((flags & SigmaValue) != 0)
4562 swap_index=(ssize_t) geometry_info.sigma;
4564 p=GetImageFromList(_images,index);
4565 q=GetImageFromList(_images,swap_index);
4566 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4568 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4570 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4573 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
4574 swap=CloneImage(p,0,0,MagickTrue,_exception);
4575 if (swap == (Image *) NULL)
4576 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4577 option,GetExceptionMessage(errno));
4578 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4579 ReplaceImageInList(&q,swap);
4580 _images=GetFirstImageInList(q);
4583 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4586 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4589 /* clean up percent escape interpreted strings */
4591 arg1=DestroyString((char *)arg1);
4593 arg2=DestroyString((char *)arg2);
4595 /* if new image list generated, replace existing image list */
4596 if (new_images == (Image *) NULL)
4597 return(status == 0 ? MagickFalse : MagickTrue);
4598 _images=DestroyImageList(_images);
4599 _images=GetFirstImageInList(new_images);
4600 return(status == 0 ? MagickFalse : MagickTrue);
4606 #undef _quantize_info
4613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4617 + C L I N o I m a g e O p e r a t i o n s %
4621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4623 % CLINoImageOperator() Applies operations that may not actually need images
4626 % The classic operators of this type is "-read", which actually creates
4627 % images even when no images are present. Or image stack operators, which
4628 % can be applied (push or pop) to an empty image list.
4630 % Note that these operators may involve other special 'option' prefix
4631 % characters other than '-' or '+', namely parenthesis and braces.
4633 % The format of the CLINoImageOption method is:
4635 % void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4636 % const char *arg1, const char *arg2)
4638 % A description of each parameter follows:
4640 % o cli_wand: the main CLI Wand to use. (sometimes not required)
4642 % o option: The special option (with any switch char) to process
4644 % o arg1 & arg2: Argument for option, if required
4645 % Currently arg2 is not used.
4648 WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
4649 const char *option,const char *arg1n,const char *arg2n)
4651 const char /* percent escaped versions of the args */
4655 #define _image_info (cli_wand->wand.image_info)
4656 #define _images (cli_wand->wand.images)
4657 #define _exception (cli_wand->wand.exception)
4658 #define _process_flags (cli_wand->process_flags)
4659 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
4660 #define IfNormalOp (*option=='-')
4661 #define IfPlusOp (*option!='-')
4663 assert(cli_wand != (MagickCLI *) NULL);
4664 assert(cli_wand->signature == MagickWandSignature);
4665 assert(cli_wand->wand.signature == MagickWandSignature);
4667 if (cli_wand->wand.debug != MagickFalse)
4668 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
4669 "- NoImage Operator: %s \"%s\" \"%s\"", option,
4670 arg1n != (char *) NULL ? arg1n : "",
4671 arg2n != (char *) NULL ? arg2n : "");
4676 /* Interpret Percent Escapes in Arguments - using first image */
4677 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4678 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4679 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4680 /* Interpret Percent escapes in argument 1 */
4681 if (arg1n != (char *) NULL) {
4682 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4683 if (arg1 == (char *) NULL) {
4684 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4685 arg1=arg1n; /* use the given argument as is */
4688 if (arg2n != (char *) NULL) {
4689 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4690 if (arg2 == (char *) NULL) {
4691 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4692 arg2=arg2n; /* use the given argument as is */
4696 #undef _process_flags
4699 do { /* break to exit code */
4701 No-op options (ignore these)
4703 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
4705 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4707 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4709 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
4711 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4716 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4717 ( LocaleCompare("--",option) == 0 ) ) {
4718 /* Do Glob filename Expansion for 'arg1' then read all images.
4720 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4721 * (but attaching to the filenames in the generated argument list) any
4722 * [...] read modifiers that may be present.
4724 * For example: It will expand '*.gif[20x20]' into a list such as
4725 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4727 * NOTE: In IMv6 this was done globally across all images. This
4728 * meant you could include IM options in '@filename' lists, but you
4729 * could not include comments. Doing it only for image read makes
4730 * it far more secure.
4732 * Note: arguments do not have percent escapes expanded for security
4740 argv = (char **) &arg1;
4742 /* Expand 'glob' expressions in the given filename.
4743 Expansion handles any 'coder:' prefix, or read modifiers attached
4744 to the filename, including them in the resulting expanded list.
4746 if (ExpandFilenames(&argc,&argv) == MagickFalse)
4747 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4748 option,GetExceptionMessage(errno));
4750 /* loop over expanded filename list, and read then all in */
4751 for (i=0; i < (ssize_t) argc; i++) {
4754 if (_image_info->ping != MagickFalse)
4755 new_images=PingImages(_image_info,argv[i],_exception);
4757 new_images=ReadImages(_image_info,argv[i],_exception);
4758 AppendImageToList(&_images, new_images);
4759 argv[i]=DestroyString(argv[i]);
4761 argv=(char **) RelinquishMagickMemory(argv);
4766 Note: Writing a empty image list is valid in specific cases
4768 if (LocaleCompare("write",option+1) == 0) {
4769 /* Note: arguments do not have percent escapes expanded */
4771 key[MagickPathExtent];
4779 /* Need images, unless a "null:" output coder is used */
4780 if ( _images == (Image *) NULL ) {
4781 if ( LocaleCompare(arg1,"null:") == 0 )
4783 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4786 (void) FormatLocaleString(key,MagickPathExtent,"cache:%s",arg1);
4787 (void) DeleteImageRegistry(key);
4788 write_images=_images;
4790 write_images=CloneImageList(_images,_exception);
4791 write_info=CloneImageInfo(_image_info);
4792 (void) WriteImages(write_info,write_images,arg1,_exception);
4793 write_info=DestroyImageInfo(write_info);
4795 write_images=DestroyImageList(write_images);
4799 Parenthesis and Brace operations
4801 if (LocaleCompare("(",option) == 0) {
4802 /* stack 'push' images */
4810 node=cli_wand->image_list_stack;
4811 for ( ; node != (Stack *) NULL; node=node->next)
4813 if ( size >= MAX_STACK_DEPTH )
4814 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4815 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4816 if (node == (Stack *) NULL)
4817 CLIWandExceptionBreak(ResourceLimitFatalError,
4818 "MemoryAllocationFailed",option);
4819 node->data = (void *)cli_wand->wand.images;
4820 node->next = cli_wand->image_list_stack;
4821 cli_wand->image_list_stack = node;
4822 cli_wand->wand.images = NewImageList();
4824 /* handle respect-parenthesis */
4825 if (IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4826 "respect-parenthesis")) != MagickFalse)
4827 option="{"; /* fall-thru so as to push image settings too */
4830 /* fall thru to operation */
4832 if (LocaleCompare("{",option) == 0) {
4833 /* stack 'push' of image_info settings */
4841 node=cli_wand->image_info_stack;
4842 for ( ; node != (Stack *) NULL; node=node->next)
4844 if ( size >= MAX_STACK_DEPTH )
4845 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4846 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4847 if (node == (Stack *) NULL)
4848 CLIWandExceptionBreak(ResourceLimitFatalError,
4849 "MemoryAllocationFailed",option);
4851 node->data = (void *)cli_wand->wand.image_info;
4852 node->next = cli_wand->image_info_stack;
4854 cli_wand->image_info_stack = node;
4855 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4856 if (cli_wand->wand.image_info == (ImageInfo *) NULL) {
4857 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4859 cli_wand->wand.image_info = (ImageInfo *)node->data;
4860 node = (Stack *)RelinquishMagickMemory(node);
4866 if (LocaleCompare(")",option) == 0) {
4867 /* pop images from stack */
4871 node = (Stack *)cli_wand->image_list_stack;
4872 if ( node == (Stack *) NULL)
4873 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4874 cli_wand->image_list_stack = node->next;
4876 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4877 cli_wand->wand.images= (Image *)node->data;
4878 node = (Stack *)RelinquishMagickMemory(node);
4880 /* handle respect-parenthesis - of the previous 'pushed' settings */
4881 node = cli_wand->image_info_stack;
4882 if ( node != (Stack *) NULL)
4884 if (IsStringTrue(GetImageOption(
4885 cli_wand->wand.image_info,"respect-parenthesis")) != MagickFalse)
4886 option="}"; /* fall-thru so as to pop image settings too */
4892 /* fall thru to next if */
4894 if (LocaleCompare("}",option) == 0) {
4895 /* pop image_info settings from stack */
4899 node = (Stack *)cli_wand->image_info_stack;
4900 if ( node == (Stack *) NULL)
4901 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4902 cli_wand->image_info_stack = node->next;
4904 (void) DestroyImageInfo(cli_wand->wand.image_info);
4905 cli_wand->wand.image_info = (ImageInfo *)node->data;
4906 node = (Stack *)RelinquishMagickMemory(node);
4908 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4909 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4910 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4914 if (LocaleCompare("print",option+1) == 0)
4916 (void) FormatLocaleFile(stdout,"%s",arg1);
4919 if (LocaleCompare("set",option+1) == 0)
4921 /* Settings are applied to each image in memory in turn (if any).
4922 While a option: only need to be applied once globally.
4924 NOTE: rguments have not been automatically percent expaneded
4927 /* escape the 'key' once only, using first image. */
4928 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4929 if (arg1 == (char *) NULL)
4930 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4933 if (LocaleNCompare(arg1,"registry:",9) == 0)
4937 (void) DeleteImageRegistry(arg1+9);
4938 arg1=DestroyString((char *)arg1);
4941 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4942 if (arg2 == (char *) NULL) {
4943 arg1=DestroyString((char *)arg1);
4944 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4947 (void) SetImageRegistry(StringRegistryType,arg1+9,arg2,_exception);
4948 arg1=DestroyString((char *)arg1);
4949 arg2=DestroyString((char *)arg2);
4952 if (LocaleNCompare(arg1,"option:",7) == 0)
4954 /* delete equivelent artifact from all images (if any) */
4955 if (_images != (Image *) NULL)
4957 MagickResetIterator(&cli_wand->wand);
4958 while (MagickNextImage(&cli_wand->wand) != MagickFalse)
4959 (void) DeleteImageArtifact(_images,arg1+7);
4960 MagickResetIterator(&cli_wand->wand);
4962 /* now set/delete the global option as needed */
4963 /* FUTURE: make escapes in a global 'option:' delayed */
4967 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4968 if (arg2 == (char *) NULL)
4969 CLIWandExceptionBreak(OptionWarning,
4970 "InterpretPropertyFailure",option);
4972 (void) SetImageOption(_image_info,arg1+7,arg2);
4973 arg1=DestroyString((char *)arg1);
4974 arg2=DestroyString((char *)arg2);
4977 /* Set Artifacts/Properties/Attributes all images (required) */
4978 if ( _images == (Image *) NULL )
4979 CLIWandExceptArgBreak(OptionWarning,"NoImageForProperty",option,arg1);
4981 MagickResetIterator(&cli_wand->wand);
4982 while (MagickNextImage(&cli_wand->wand) != MagickFalse)
4987 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4988 if (arg2 == (char *) NULL)
4989 CLIWandExceptionBreak(OptionWarning,
4990 "InterpretPropertyFailure",option);
4992 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4993 (void) SetImageArtifact(_images,arg1+9,arg2);
4994 else if (LocaleNCompare(arg1,"property:",9) == 0)
4995 (void) SetImageProperty(_images,arg1+9,arg2,_exception);
4997 (void) SetImageProperty(_images,arg1,arg2,_exception);
4998 arg2=DestroyString((char *)arg2);
5000 MagickResetIterator(&cli_wand->wand);
5001 arg1=DestroyString((char *)arg1);
5004 if (LocaleCompare("clone",option+1) == 0) {
5009 arg1=AcquireString("-1");
5010 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
5011 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
5012 if ( cli_wand->image_list_stack == (Stack *) NULL)
5013 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
5014 new_images = (Image *)cli_wand->image_list_stack->data;
5015 if (new_images == (Image *) NULL)
5016 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
5017 new_images=CloneImages(new_images,arg1,_exception);
5018 if (new_images == (Image *) NULL)
5019 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
5020 AppendImageToList(&_images,new_images);
5024 Informational Operations.
5026 Note that these do not require either a cli-wand or images!
5027 Though currently a cli-wand much be provided regardless.
5029 if (LocaleCompare("version",option+1) == 0)
5031 ListMagickVersion(stdout);
5034 if (LocaleCompare("list",option+1) == 0) {
5036 FUTURE: This 'switch' should really be part of MagickCore
5041 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
5043 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
5048 case MagickCoderOptions:
5050 (void) ListCoderInfo((FILE *) NULL,_exception);
5053 case MagickColorOptions:
5055 (void) ListColorInfo((FILE *) NULL,_exception);
5058 case MagickConfigureOptions:
5060 (void) ListConfigureInfo((FILE *) NULL,_exception);
5063 case MagickDelegateOptions:
5065 (void) ListDelegateInfo((FILE *) NULL,_exception);
5068 case MagickFontOptions:
5070 (void) ListTypeInfo((FILE *) NULL,_exception);
5073 case MagickFormatOptions:
5074 (void) ListMagickInfo((FILE *) NULL,_exception);
5076 case MagickLocaleOptions:
5077 (void) ListLocaleInfo((FILE *) NULL,_exception);
5079 case MagickLogOptions:
5080 (void) ListLogInfo((FILE *) NULL,_exception);
5082 case MagickMagicOptions:
5083 (void) ListMagicInfo((FILE *) NULL,_exception);
5085 case MagickMimeOptions:
5086 (void) ListMimeInfo((FILE *) NULL,_exception);
5088 case MagickModuleOptions:
5089 (void) ListModuleInfo((FILE *) NULL,_exception);
5091 case MagickPolicyOptions:
5092 (void) ListPolicyInfo((FILE *) NULL,_exception);
5094 case MagickResourceOptions:
5095 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
5097 case MagickThresholdOptions:
5098 (void) ListThresholdMaps((FILE *) NULL,_exception);
5101 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
5108 CLIWandException(OptionError,"UnrecognizedOption",option);
5110 DisableMSCWarning(4127)
5111 } while (0); /* break to exit code. */
5114 /* clean up percent escape interpreted strings */
5116 arg1=DestroyString((char *)arg1);
5118 arg2=DestroyString((char *)arg2);
5128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5132 + C L I O p t i o n %
5136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5138 % CLIOption() Processes the given option using the given CLI Magick Wand.
5139 % The option arguments can be variable in number, though at this time no more
5140 % that two is actually used by any option (this may change). Excess options
5141 % are simply ignored.
5143 % If the cli_wand->command pointer is non-null, then it is assumed that the
5144 % option has already been search for up from the CommandOptions[] table in
5145 % "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
5146 % routine will do the lookup instead. The pointer is reset afterward.
5148 % This action allows the caller to lookup and pre-handle any 'special'
5149 % options, (such as implicit reads) before calling this general option
5150 % handler to deal with 'standard' command line options.
5152 % The format of the CLIOption method is:
5154 % void CLIOption(MagickCLI *cli_wand,const char *option, ...)
5156 % A description of each parameter follows:
5158 % o cli_wand: the main CLI Wand to use.
5160 % o option: The special option (with any switch char) to process
5162 % o args: any required arguments for an option (variable number)
5166 % CLIoption(cli_wand,"-read","rose:");
5167 % CLIoption(cli_wand,"-virtual-pixel","transparent");
5168 % CLIoption(cli_wand,"-distort","SRT:","30");
5169 % CLIoption(cli_wand,"-write","rotated_rose.png");
5172 WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
5174 const char /* extracted option args from args */
5181 assert(cli_wand != (MagickCLI *) NULL);
5182 assert(cli_wand->signature == MagickWandSignature);
5183 assert(cli_wand->wand.signature == MagickWandSignature);
5185 do { /* Break Code Block for error handling */
5187 /* get information about option */
5188 if ( cli_wand->command == (const OptionInfo *) NULL )
5189 cli_wand->command = GetCommandOptionInfo(option);
5191 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
5192 option, cli_wand->command->mnemonic );
5194 option_type=(CommandOptionFlags) cli_wand->command->flags;
5196 if ( option_type == UndefinedOptionFlag )
5197 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
5199 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
5201 /* deprecated options */
5202 if ( (option_type & DeprecateOptionFlag) != 0 )
5203 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
5205 /* options that this module does not handle */
5206 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
5207 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
5209 /* Get argument strings from VarArgs
5210 How can you determine if enough arguments was supplied?
5211 What happens if not enough arguments were supplied?
5214 count = (size_t) cli_wand->command->type;
5219 va_start(operands,option);
5223 arg1=(const char *) va_arg(operands, const char *);
5225 arg2=(const char *) va_arg(operands, const char *);
5229 (void) FormatLocaleFile(stderr,
5230 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
5231 option,(long) count,option_type,arg1,arg2);
5236 Call the appropriate option handler
5239 /* FUTURE: this is temporary - get 'settings' to handle distribution of
5240 settings to images attributes,proprieties,artifacts */
5241 if ( cli_wand->wand.images != (Image *) NULL )
5242 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
5243 cli_wand->wand.exception);
5245 if ( (option_type & SettingOptionFlags) != 0 ) {
5246 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
5248 FUTURE: Sync Specific Settings into Image Properities (not global)
5252 /* Operators that do not need images - read, write, stack, clone */
5253 if ((option_type & NoImageOperatorFlag) != 0)
5254 CLINoImageOperator(cli_wand, option, arg1, arg2);
5256 /* FUTURE: The not a setting part below is a temporary hack due to
5257 * some options being both a Setting and a Simple operator.
5258 * Specifically -monitor, -depth, and -colorspace */
5259 if ( cli_wand->wand.images == (Image *) NULL )
5260 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
5261 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
5262 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
5264 /* Operators which loop of individual images, simply */
5265 if ( (option_type & SimpleOperatorFlag) != 0 &&
5266 cli_wand->wand.images != (Image *) NULL) /* temp hack */
5268 ExceptionInfo *exception=AcquireExceptionInfo();
5269 (void) CLISimpleOperatorImages(cli_wand, option, arg1, arg2,exception);
5270 exception=DestroyExceptionInfo(exception);
5273 /* Operators that work on the image list as a whole */
5274 if ( (option_type & ListOperatorFlag) != 0 )
5275 (void) CLIListOperatorImages(cli_wand, option, arg1, arg2);
5277 DisableMSCWarning(4127)
5278 } while (0); /* end Break code block */
5281 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */