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-2013 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 % Apply the given options (settings, and simple, or sequence operations) to
37 % the given image(s) according to the current "image_info", "draw_info", and
38 % "quantize_info" settings, stored in a special CLI Image Wand.
40 % The final goal is to allow the execution in a strict one option at a time
41 % manner that is needed for 'pipelining and file scripting' of options in
44 % Anthony Thyssen, September 2011
50 #include "MagickWand/studio.h"
51 #include "MagickWand/MagickWand.h"
52 #include "MagickWand/magick-wand-private.h"
53 #include "MagickWand/wand.h"
54 #include "MagickWand/wandcli.h"
55 #include "MagickWand/wandcli-private.h"
56 #include "MagickWand/operation.h"
57 #include "MagickCore/monitor-private.h"
58 #include "MagickCore/thread-private.h"
59 #include "MagickCore/string-private.h"
60 #include "MagickCore/pixel-private.h"
65 #define USE_WAND_METHODS 1
66 #define MAX_STACK_DEPTH 32
67 #define UNDEFINED_COMPRESSION_QUALITY 0UL
69 /* FUTURE: why is this default so specific? */
70 #define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
73 Constant declaration. (temporary exports)
76 BackgroundColor[] = "#fff", /* white */
77 BorderColor[] = "#dfdfdf", /* sRGB gray */
78 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
80 /* For Debugging Geometry Input */
81 #define ReportGeometry(flags,info) \
82 (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
83 flags, info.rho, info.sigma, info.xi, info.psi )
86 ** Function to report on the progress of image operations
88 static MagickBooleanType MonitorProgress(const char *text,
89 const MagickOffsetType offset,const MagickSizeType extent,
90 void *wand_unused(cli_wandent_data))
93 message[MaxTextExtent],
104 (void) CopyMagickMemory(tag,text,MaxTextExtent);
106 if (p != (char *) NULL)
108 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
109 locale_message=GetLocaleMessage(message);
110 if (locale_message == message)
112 if (p == (char *) NULL)
113 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
114 locale_message,(long) offset,(unsigned long) extent,(long)
115 (100L*offset/(extent-1)));
117 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
118 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
119 (100L*offset/(extent-1)));
120 if (offset == (MagickOffsetType) (extent-1))
121 (void) FormatLocaleFile(stderr,"\n");
122 (void) fflush(stderr);
127 ** GetImageCache() will read an image into a image cache if not already
128 ** present then return the image that is in the cache under that filename.
130 static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
131 ExceptionInfo *exception)
145 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
146 sans_exception=AcquireExceptionInfo();
147 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
148 sans_exception=DestroyExceptionInfo(sans_exception);
149 if (image != (Image *) NULL)
151 read_info=CloneImageInfo(image_info);
152 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
153 image=ReadImage(read_info,exception);
154 read_info=DestroyImageInfo(read_info);
155 if (image != (Image *) NULL)
156 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
161 SparseColorOption() parse the complex -sparse-color argument into an
162 an array of floating point values than call SparseColorImage().
163 Argument is a complex mix of floating-point pixel coodinates, and color
164 specifications (or direct floating point numbers). The number of floats
165 needed to represent a color varies depending on teh current channel
168 This really should be in MagickCore, so that other API's can make use of it.
170 static Image *SparseColorOption(const Image *image,
171 const SparseColorMethod method,const char *arguments,
172 ExceptionInfo *exception)
175 token[MaxTextExtent];
199 assert(image != (Image *) NULL);
200 assert(image->signature == MagickSignature);
201 if (IfMagickTrue(image->debug))
202 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
203 assert(exception != (ExceptionInfo *) NULL);
204 assert(exception->signature == MagickSignature);
206 Limit channels according to image
207 add up number of values needed per color.
210 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
212 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
214 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
216 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
217 (image->colorspace == CMYKColorspace))
219 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
220 image->alpha_trait == BlendPixelTrait)
224 Read string, to determine number of arguments needed,
230 GetMagickToken(p,&p,token);
231 if ( token[0] == ',' ) continue;
232 if ( isalpha((int) token[0]) || token[0] == '#' )
233 x += number_colors; /* color argument found */
235 x++; /* floating point argument */
237 /* control points and color values */
238 error = IsMagickTrue( x % (2+number_colors) );
240 if ( IfMagickTrue(error) ) {
241 (void) ThrowMagickException(exception,GetMagickModule(),
242 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
243 "Invalid number of Arguments");
244 return( (Image *)NULL);
247 /* Allocate and fill in the floating point arguments */
248 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
249 sizeof(*sparse_arguments));
250 if (sparse_arguments == (double *) NULL) {
251 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
252 "MemoryAllocationFailed","%s","SparseColorOption");
253 return( (Image *)NULL);
255 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
256 sizeof(*sparse_arguments));
259 while( *p != '\0' && x < number_arguments ) {
261 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
262 if ( token[0] == '\0' ) break;
263 if ( isalpha((int) token[0]) || token[0] == '#' ) {
264 (void) ThrowMagickException(exception,GetMagickModule(),
265 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
266 "Color found, instead of X-coord");
270 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
272 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
273 if ( token[0] == '\0' ) break;
274 if ( isalpha((int) token[0]) || token[0] == '#' ) {
275 (void) ThrowMagickException(exception,GetMagickModule(),
276 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
277 "Color found, instead of Y-coord");
281 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
282 /* color name or function given in string argument */
283 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
284 if ( token[0] == '\0' ) break;
285 if ( isalpha((int) token[0]) || token[0] == '#' ) {
286 /* Color string given */
287 (void) QueryColorCompliance(token,AllCompliance,&color,
289 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
290 sparse_arguments[x++] = QuantumScale*color.red;
291 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
292 sparse_arguments[x++] = QuantumScale*color.green;
293 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
294 sparse_arguments[x++] = QuantumScale*color.blue;
295 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
296 (image->colorspace == CMYKColorspace))
297 sparse_arguments[x++] = QuantumScale*color.black;
298 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
299 image->alpha_trait == BlendPixelTrait)
300 sparse_arguments[x++] = QuantumScale*color.alpha;
303 /* Colors given as a set of floating point values - experimental */
304 /* NB: token contains the first floating point value to use! */
305 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
307 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
308 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
310 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
311 token[0] = ','; /* used this token - get another */
313 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
315 while ( token[0] == ',' ) GetMagickToken(p,&p,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 ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
323 while ( token[0] == ',' ) GetMagickToken(p,&p,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 (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
330 (image->colorspace == CMYKColorspace))
332 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
333 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
335 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
336 token[0] = ','; /* used this token - get another */
338 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
339 image->alpha_trait == BlendPixelTrait)
341 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
342 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
344 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
345 token[0] = ','; /* used this token - get another */
349 if ( number_arguments != x && !error ) {
350 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
351 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
352 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
353 return( (Image *)NULL);
356 return( (Image *)NULL);
358 /* Call the Sparse Color Interpolation function with the parsed arguments */
359 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
361 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
362 return( sparse_image );
366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370 % C L I S e t t i n g O p t i o n I n f o %
374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376 % CLISettingOptionInfo() applies a single settings option into a CLI wand
377 % holding the image_info, draw_info, quantize_info structures that will be
378 % used when processing the images.
380 % These options do no require images to be present in the CLI wand for them
381 % to be able to be set, in which case they will generally be applied to image
382 % that are read in later
384 % Options handled by this function are listed in CommandOptions[] of
385 % "option.c" that is one of "SettingOptionFlags" option flags.
387 % The format of the CLISettingOptionInfo method is:
389 % void CLISettingOptionInfo(MagickCLI *cli_wand,
390 % const char *option, const char *arg1, const char *arg2)
392 % A description of each parameter follows:
394 % o cli_wand: structure holding settings to be applied
396 % o option: The option string to be set
398 % o arg1, arg2: optional argument strings to the operation
399 % arg2 is currently only used by "-limit"
402 WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
403 const char *option,const char *arg1, const char *arg2)
406 parse; /* option argument parsing (string to value table lookup) */
408 assert(cli_wand != (MagickCLI *) NULL);
409 assert(cli_wand->signature == WandSignature);
410 assert(cli_wand->wand.signature == WandSignature);
411 if (IfMagickTrue(cli_wand->wand.debug))
412 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
414 #define _image_info (cli_wand->wand.image_info)
415 #define _exception (cli_wand->wand.exception)
416 #define _draw_info (cli_wand->draw_info)
417 #define _quantize_info (cli_wand->quantize_info)
418 #define IfSetOption (*option=='-')
419 #define ArgBoolean IsMagickTrue(IfSetOption)
420 #define ArgBooleanNot IsMagickFalse(IfSetOption)
421 #define ArgBooleanString (IfSetOption?"true":"false")
422 #define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
425 Setting are not directly involved with images, so can not
426 interpret Percent Escapes in Arguments, At least not yet */
428 #define _process_flags (cli_wand->process_flags)
429 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
430 /* Interpret Percent Escapes in Arguments - using first image */
433 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
434 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
435 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
436 /* Interpret Percent escapes in argument 1 */
437 if (arg1n != (char *) NULL) {
438 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
439 if (arg1 == (char *) NULL) {
440 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
441 arg1=arg1n; /* use the given argument as is */
444 if (arg2n != (char *) NULL) {
445 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
446 if (arg2 == (char *) NULL) {
447 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
448 arg2=arg2n; /* use the given argument as is */
452 #undef _process_flags
460 if (LocaleCompare("adjoin",option+1) == 0)
462 _image_info->adjoin = ArgBoolean;
465 if (LocaleCompare("affine",option+1) == 0)
467 CLIWandWarnReplaced("-draw 'affine ...'");
469 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
471 GetAffineMatrix(&_draw_info->affine);
474 if (LocaleCompare("antialias",option+1) == 0)
476 _image_info->antialias =
477 _draw_info->stroke_antialias =
478 _draw_info->text_antialias = ArgBoolean;
481 if (LocaleCompare("attenuate",option+1) == 0)
483 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
484 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
485 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
488 if (LocaleCompare("authenticate",option+1) == 0)
490 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
493 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
497 if (LocaleCompare("background",option+1) == 0)
499 /* FUTURE: both _image_info attribute & ImageOption in use!
500 _image_info only used directly for generating new images.
501 SyncImageSettings() used to set per-image attribute.
503 FUTURE: if _image_info->background_color is not set then
504 we should fall back to per-image background_color
506 At this time -background will 'wipe out' the per-image
509 Better error handling of QueryColorCompliance() needed.
511 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
512 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
513 &_image_info->background_color,_exception);
516 if (LocaleCompare("bias",option+1) == 0)
518 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
519 as it is actually rarely used except in direct convolve operations
520 Usage outside a direct convolve operation is actally non-sensible!
522 SyncImageSettings() used to set per-image attribute.
524 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
525 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
526 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
529 if (LocaleCompare("black-point-compensation",option+1) == 0)
531 /* Used as a image chromaticity setting
532 SyncImageSettings() used to set per-image attribute.
534 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
537 if (LocaleCompare("blue-primary",option+1) == 0)
539 /* Image chromaticity X,Y NB: Y=X if Y not defined
540 Used by many coders including PNG
541 SyncImageSettings() used to set per-image attribute.
543 arg1=ArgOption("0.0");
544 if (IfMagickFalse(IsGeometry(arg1)))
545 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
546 (void) SetImageOption(_image_info,option+1,arg1);
549 if (LocaleCompare("bordercolor",option+1) == 0)
551 /* FUTURE: both _image_info attribute & ImageOption in use!
552 SyncImageSettings() used to set per-image attribute.
553 Better error checking of QueryColorCompliance().
557 (void) SetImageOption(_image_info,option+1,arg1);
558 (void) QueryColorCompliance(arg1,AllCompliance,
559 &_image_info->border_color,_exception);
560 (void) QueryColorCompliance(arg1,AllCompliance,
561 &_draw_info->border_color,_exception);
564 (void) DeleteImageOption(_image_info,option+1);
565 (void) QueryColorCompliance(BorderColor,AllCompliance,
566 &_image_info->border_color,_exception);
567 (void) QueryColorCompliance(BorderColor,AllCompliance,
568 &_draw_info->border_color,_exception);
571 if (LocaleCompare("box",option+1) == 0)
573 CLIWandWarnReplaced("-undercolor");
574 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
577 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
581 if (LocaleCompare("cache",option+1) == 0)
586 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
587 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
588 limit=MagickResourceInfinity;
589 if (LocaleCompare("unlimited",arg1) != 0)
590 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
591 (void) SetMagickResourceLimit(MemoryResource,limit);
592 (void) SetMagickResourceLimit(MapResource,2*limit);
595 if (LocaleCompare("caption",option+1) == 0)
597 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
600 if (LocaleCompare("channel",option+1) == 0)
602 arg1=ArgOption("default");
603 parse=ParseChannelOption(arg1);
605 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
607 _image_info->channel=(ChannelType) parse;
608 (void) SetImageOption(_image_info,option+1,arg1);
611 if (LocaleCompare("colorspace",option+1) == 0)
613 /* Setting used for new images via AquireImage()
614 But also used as a SimpleImageOperator
615 Undefined colorspace means don't modify images on
616 read or as a operation */
617 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
618 ArgOption("undefined"));
620 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
622 _image_info->colorspace=(ColorspaceType) parse;
625 if (LocaleCompare("comment",option+1) == 0)
627 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
630 if (LocaleCompare("compose",option+1) == 0)
632 /* FUTURE: _image_info should be used,
633 SyncImageSettings() used to set per-image attribute. - REMOVE
635 This setting should NOT be used to set image 'compose'
636 "-layer" operators shoud use _image_info if defined otherwise
637 they should use a per-image compose setting.
639 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
640 ArgOption("undefined"));
642 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
644 _image_info->compose=(CompositeOperator) parse;
645 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
648 if (LocaleCompare("compress",option+1) == 0)
650 /* FUTURE: What should be used? _image_info or ImageOption ???
651 The former is more efficent, but Crisy prefers the latter!
652 SyncImageSettings() used to set per-image attribute.
654 The coders appears to use _image_info, not Image_Option
655 however the image attribute (for save) is set from the
658 Note that "undefined" is a different setting to "none".
660 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
661 ArgOption("undefined"));
663 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
665 _image_info->compression=(CompressionType) parse;
666 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
669 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
673 if (LocaleCompare("debug",option+1) == 0)
675 /* SyncImageSettings() used to set per-image attribute. */
676 arg1=ArgOption("none");
677 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
679 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
681 (void) SetLogEventMask(arg1);
682 _image_info->debug=IsEventLogging(); /* extract logging*/
683 cli_wand->wand.debug=IsEventLogging();
686 if (LocaleCompare("define",option+1) == 0)
688 if (LocaleNCompare(arg1,"registry:",9) == 0)
691 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
693 (void) DeleteImageRegistry(arg1+9);
696 /* DefineImageOption() equals SetImageOption() but with '=' */
698 (void) DefineImageOption(_image_info,arg1);
699 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
700 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
703 if (LocaleCompare("delay",option+1) == 0)
705 /* Only used for new images via AcquireImage()
706 FUTURE: Option should also be used for "-morph" (color morphing)
709 if (IfMagickFalse(IsGeometry(arg1)))
710 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
711 (void) SetImageOption(_image_info,option+1,arg1);
714 if (LocaleCompare("density",option+1) == 0)
716 /* FUTURE: strings used in _image_info attr and _draw_info!
717 Basically as density can be in a XxY form!
719 SyncImageSettings() used to set per-image attribute.
721 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
722 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
723 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
724 (void) CloneString(&_image_info->density,ArgOption(NULL));
725 (void) CloneString(&_draw_info->density,_image_info->density);
728 if (LocaleCompare("depth",option+1) == 0)
730 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
731 SyncImageSettings() used to set per-image attribute.
733 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
734 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
735 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
736 :MAGICKCORE_QUANTUM_DEPTH;
739 if (LocaleCompare("direction",option+1) == 0)
741 /* Image Option is only used to set _draw_info */
742 arg1=ArgOption("undefined");
743 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
745 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
747 _draw_info->direction=(DirectionType) parse;
748 (void) SetImageOption(_image_info,option+1,arg1);
751 if (LocaleCompare("display",option+1) == 0)
753 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
754 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
757 if (LocaleCompare("dispose",option+1) == 0)
759 /* only used in setting new images */
760 arg1=ArgOption("undefined");
761 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
763 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
765 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
768 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
770 /* FUTURE: this is only used by CompareImages() which is used
771 only by the "compare" CLI program at this time. */
772 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
773 if (IfMagickFalse(IsGeometry(arg1)))
774 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
775 (void) SetImageOption(_image_info,option+1,arg1);
778 if (LocaleCompare("dither",option+1) == 0)
780 /* _image_info attr (on/off), _quantize_info attr (on/off)
781 but also ImageInfo and _quantize_info method!
782 FUTURE: merge the duality of the dithering options
784 _image_info->dither = ArgBoolean;
785 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
786 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
787 MagickDitherOptions,MagickFalse,ArgOption("none"));
788 if (_quantize_info->dither_method == NoDitherMethod)
789 _image_info->dither = MagickFalse;
792 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
796 if (LocaleCompare("encoding",option+1) == 0)
798 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
799 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
802 if (LocaleCompare("endian",option+1) == 0)
804 /* Both _image_info attr and ImageInfo */
805 arg1 = ArgOption("undefined");
806 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
808 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
810 /* FUTURE: check alloc/free of endian string! - remove? */
811 _image_info->endian=(EndianType) (*arg1);
812 (void) SetImageOption(_image_info,option+1,arg1);
815 if (LocaleCompare("extract",option+1) == 0)
817 (void) CloneString(&_image_info->extract,ArgOption(NULL));
820 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
824 if (LocaleCompare("family",option+1) == 0)
826 (void) CloneString(&_draw_info->family,ArgOption(NULL));
829 if (LocaleCompare("fill",option+1) == 0)
831 /* Set "fill" OR "fill-pattern" in _draw_info
832 The original fill color is preserved if a fill-pattern is given.
833 That way it does not effect other operations that directly using
834 the fill color and, can be retored using "+tile".
845 arg1 = ArgOption("none"); /* +fill turns it off! */
846 (void) SetImageOption(_image_info,option+1,arg1);
847 if (_draw_info->fill_pattern != (Image *) NULL)
848 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
850 /* is it a color or a image? -- ignore exceptions */
851 sans=AcquireExceptionInfo();
852 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
853 sans=DestroyExceptionInfo(sans);
855 if (IfMagickFalse(status))
856 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
858 _draw_info->fill=color;
861 if (LocaleCompare("filter",option+1) == 0)
863 /* SyncImageSettings() used to set per-image attribute. */
864 arg1 = ArgOption("undefined");
865 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
867 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
869 (void) SetImageOption(_image_info,option+1,arg1);
872 if (LocaleCompare("font",option+1) == 0)
874 (void) CloneString(&_draw_info->font,ArgOption(NULL));
875 (void) CloneString(&_image_info->font,_draw_info->font);
878 if (LocaleCompare("format",option+1) == 0)
880 /* FUTURE: why the ping test, you could set ping after this! */
885 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
886 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
887 _image_info->ping=MagickFalse;
889 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
892 if (LocaleCompare("fuzz",option+1) == 0)
894 /* Option used to set image fuzz! unless blank canvas (from color)
895 Image attribute used for color compare operations
896 SyncImageSettings() used to set per-image attribute.
898 FUTURE: Can't find anything else using _image_info->fuzz directly!
899 remove direct sttribute from image_info
902 if (IfMagickFalse(IsGeometry(arg1)))
903 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
904 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
906 (void) SetImageOption(_image_info,option+1,arg1);
909 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
913 if (LocaleCompare("gravity",option+1) == 0)
915 /* SyncImageSettings() used to set per-image attribute. */
916 arg1 = ArgOption("none");
917 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
919 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
921 _draw_info->gravity=(GravityType) parse;
922 (void) SetImageOption(_image_info,option+1,arg1);
925 if (LocaleCompare("green-primary",option+1) == 0)
927 /* Image chromaticity X,Y NB: Y=X if Y not defined
928 SyncImageSettings() used to set per-image attribute.
929 Used directly by many coders
931 arg1=ArgOption("0.0");
932 if (IfMagickFalse(IsGeometry(arg1)))
933 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
934 (void) SetImageOption(_image_info,option+1,arg1);
937 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
941 if (LocaleCompare("highlight-color",option+1) == 0)
943 /* FUTURE: this is only used by CompareImages() which is used
944 only by the "compare" CLI program at this time. */
945 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
948 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
952 if (LocaleCompare("intent",option+1) == 0)
954 /* Only used by coders: MIFF, MPC, BMP, PNG
955 and for image profile call to AcquireTransformThreadSet()
956 SyncImageSettings() used to set per-image attribute.
958 arg1 = ArgOption("indefined");
959 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
961 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
963 (void) SetImageOption(_image_info,option+1,arg1);
966 if (LocaleCompare("interlace",option+1) == 0)
968 /* _image_info is directly used by coders (so why an image setting?)
969 SyncImageSettings() used to set per-image attribute.
971 arg1 = ArgOption("undefined");
972 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
974 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
976 _image_info->interlace=(InterlaceType) parse;
977 (void) SetImageOption(_image_info,option+1,arg1);
980 if (LocaleCompare("interline-spacing",option+1) == 0)
982 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
983 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
984 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
985 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
989 if (LocaleCompare("interpolate",option+1) == 0)
991 /* SyncImageSettings() used to set per-image attribute. */
992 arg1 = ArgOption("undefined");
993 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
995 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
997 (void) SetImageOption(_image_info,option+1,arg1);
1000 if (LocaleCompare("interword-spacing",option+1) == 0)
1002 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1003 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1004 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1005 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
1008 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1012 if (LocaleCompare("kerning",option+1) == 0)
1014 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1015 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1016 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1017 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
1020 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1024 if (LocaleCompare("label",option+1) == 0)
1026 /* only used for new images - not in SyncImageOptions() */
1027 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1030 if (LocaleCompare("limit",option+1) == 0)
1035 limit=MagickResourceInfinity;
1036 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1038 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1040 if (LocaleCompare("unlimited",arg2) != 0)
1041 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1042 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1045 if (LocaleCompare("log",option+1) == 0)
1048 if ((strchr(arg1,'%') == (char *) NULL))
1049 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1050 (void) SetLogFormat(arg1);
1054 if (LocaleCompare("lowlight-color",option+1) == 0)
1056 /* FUTURE: this is only used by CompareImages() which is used
1057 only by the "compare" CLI program at this time. */
1058 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1061 if (LocaleCompare("loop",option+1) == 0)
1063 /* SyncImageSettings() used to set per-image attribute. */
1064 arg1=ArgOption("0");
1065 if (IfMagickFalse(IsGeometry(arg1)))
1066 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1067 (void) SetImageOption(_image_info,option+1,arg1);
1070 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1074 if (LocaleCompare("mattecolor",option+1) == 0)
1076 /* SyncImageSettings() used to set per-image attribute. */
1077 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1078 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
1079 &_image_info->matte_color,_exception);
1082 if (LocaleCompare("metric",option+1) == 0)
1084 /* FUTURE: this is only used by CompareImages() which is used
1085 only by the "compare" CLI program at this time. */
1086 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1088 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1090 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1093 if (LocaleCompare("monitor",option+1) == 0)
1095 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
1096 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
1099 if (LocaleCompare("monochrome",option+1) == 0)
1101 /* Setting (used by some input coders!) -- why?
1102 Warning: This is also Special '-type' SimpleOperator
1104 _image_info->monochrome= ArgBoolean;
1107 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1111 if (LocaleCompare("orient",option+1) == 0)
1113 /* Is not used when defining for new images.
1114 This makes it more of a 'operation' than a setting
1115 FUTURE: make set meta-data operator instead.
1116 SyncImageSettings() used to set per-image attribute.
1118 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1119 ArgOption("undefined"));
1121 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1123 _image_info->orientation=(OrientationType)parse;
1124 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1127 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1131 if (LocaleCompare("page",option+1) == 0)
1133 /* Only used for new images and image generators.
1134 SyncImageSettings() used to set per-image attribute. ?????
1135 That last is WRONG!!!!
1136 FUTURE: adjust named 'page' sizes according density
1140 page[MaxTextExtent];
1153 (void) DeleteImageOption(_image_info,option+1);
1154 (void) CloneString(&_image_info->page,(char *) NULL);
1157 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1158 image_option=GetImageOption(_image_info,"page");
1159 if (image_option != (const char *) NULL)
1160 flags=ParseAbsoluteGeometry(image_option,&geometry);
1161 canonical_page=GetPageGeometry(arg1);
1162 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1163 canonical_page=DestroyString(canonical_page);
1164 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1165 (unsigned long) geometry.width,(unsigned long) geometry.height);
1166 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1167 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1168 (unsigned long) geometry.width,(unsigned long) geometry.height,
1169 (long) geometry.x,(long) geometry.y);
1170 (void) SetImageOption(_image_info,option+1,page);
1171 (void) CloneString(&_image_info->page,page);
1174 if (LocaleCompare("ping",option+1) == 0)
1176 _image_info->ping = ArgBoolean;
1179 if (LocaleCompare("pointsize",option+1) == 0)
1182 if (IfMagickFalse(IsGeometry(arg1)))
1183 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1184 _image_info->pointsize =
1185 _draw_info->pointsize =
1186 StringToDouble(arg1,(char **) NULL);
1189 _image_info->pointsize=0.0; /* unset pointsize */
1190 _draw_info->pointsize=12.0;
1194 if (LocaleCompare("precision",option+1) == 0)
1196 arg1=ArgOption("-1");
1197 if (IfMagickFalse(IsGeometry(arg1)))
1198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1199 (void) SetMagickPrecision(StringToInteger(arg1));
1202 /* FUTURE: Only the 'preview' coder appears to use this
1203 * DEPRECIATE the coder? Leaving only the 'preview' operator.
1204 if (LocaleCompare("preview",option+1) == 0)
1206 _image_info->preview_type=UndefinedPreview;
1208 _image_info->preview_type=(PreviewType) ParseCommandOption(
1209 MagickPreviewOptions,MagickFalse,arg1);
1213 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1217 if (LocaleCompare("quality",option+1) == 0)
1219 if (IfMagickFalse(IsGeometry(arg1)))
1220 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1221 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1222 : UNDEFINED_COMPRESSION_QUALITY;
1223 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1226 if (LocaleCompare("quantize",option+1) == 0)
1228 /* Just a set direct in _quantize_info */
1229 arg1=ArgOption("undefined");
1230 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1232 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1234 _quantize_info->colorspace=(ColorspaceType)parse;
1237 if (LocaleCompare("quiet",option+1) == 0)
1239 /* FUTURE: if two -quiet is performed you can not do +quiet!
1240 This needs to be checked over thoughly.
1242 static WarningHandler
1243 warning_handler = (WarningHandler) NULL;
1246 tmp = SetWarningHandler((WarningHandler) NULL);
1248 if ( tmp != (WarningHandler) NULL)
1249 warning_handler = tmp; /* remember the old handler */
1250 if (!IfSetOption) /* set the old handler */
1251 warning_handler=SetWarningHandler(warning_handler);
1254 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1258 if (LocaleCompare("red-primary",option+1) == 0)
1260 /* Image chromaticity X,Y NB: Y=X if Y not defined
1262 SyncImageSettings() used to set per-image attribute.
1264 arg1=ArgOption("0.0");
1265 if (IfMagickFalse(IsGeometry(arg1)))
1266 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1267 (void) SetImageOption(_image_info,option+1,arg1);
1270 if (LocaleCompare("regard-warnings",option+1) == 0)
1271 /* FUTURE: to be replaced by a 'fatal-level' type setting */
1273 if (LocaleCompare("render",option+1) == 0)
1275 /* _draw_info only setting */
1276 _draw_info->render= ArgBooleanNot;
1279 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1281 /* link image and setting stacks - option is itself saved on stack! */
1282 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1285 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1289 if (LocaleCompare("sampling-factor",option+1) == 0)
1291 /* FUTURE: should be converted to jpeg:sampling_factor */
1292 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1293 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1294 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
1297 if (LocaleCompare("scene",option+1) == 0)
1299 /* SyncImageSettings() used to set this as a per-image attribute.
1302 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1303 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1304 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1305 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
1308 if (LocaleCompare("seed",option+1) == 0)
1310 if (IfMagickFalse(IsGeometry(arg1)))
1311 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1313 IfSetOption ? (const unsigned long) StringToUnsignedLong(arg1)
1314 : (const unsigned long) time((time_t *) NULL) );
1317 if (LocaleCompare("size",option+1) == 0)
1319 /* FUTURE: string in _image_info -- convert to Option ???
1320 Look at the special handling for "size" in SetImageOption()
1322 (void) CloneString(&_image_info->size,ArgOption(NULL));
1325 if (LocaleCompare("stretch",option+1) == 0)
1327 arg1=ArgOption("undefined");
1328 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1330 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1332 _draw_info->stretch=(StretchType) parse;
1335 if (LocaleCompare("stroke",option+1) == 0)
1337 /* set stroke color OR stroke-pattern
1338 UPDATE: ensure stroke color is not destroyed is a pattern
1339 is given. Just in case the color is also used for other purposes.
1350 arg1 = ArgOption("none"); /* +fill turns it off! */
1351 (void) SetImageOption(_image_info,option+1,arg1);
1352 if (_draw_info->stroke_pattern != (Image *) NULL)
1353 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
1355 /* is it a color or a image? -- ignore exceptions */
1356 sans=AcquireExceptionInfo();
1357 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
1358 sans=DestroyExceptionInfo(sans);
1360 if (IfMagickFalse(status))
1361 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
1363 _draw_info->stroke=color;
1366 if (LocaleCompare("strokewidth",option+1) == 0)
1368 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1369 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1370 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1371 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1375 if (LocaleCompare("style",option+1) == 0)
1377 arg1=ArgOption("undefined");
1378 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1380 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1382 _draw_info->style=(StyleType) parse;
1386 if (LocaleCompare("subimage-search",option+1) == 0)
1388 /* FUTURE: this is only used by CompareImages() which is used
1389 only by the "compare" CLI program at this time. */
1390 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1394 if (LocaleCompare("synchronize",option+1) == 0)
1396 /* FUTURE: syncronize to storage - but what does that mean? */
1397 _image_info->synchronize = ArgBoolean;
1400 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1404 if (LocaleCompare("taint",option+1) == 0)
1406 /* SyncImageSettings() used to set per-image attribute. */
1407 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1410 if (LocaleCompare("texture",option+1) == 0)
1412 /* Note: arguments do not have percent escapes expanded */
1413 /* FUTURE: move _image_info string to option splay-tree
1414 Other than "montage" what uses "texture" ????
1416 (void) CloneString(&_image_info->texture,ArgOption(NULL));
1419 if (LocaleCompare("tile",option+1) == 0)
1421 /* Note: arguments do not have percent escapes expanded */
1422 _draw_info->fill_pattern=IfSetOption
1423 ?GetImageCache(_image_info,arg1,_exception)
1424 :DestroyImage(_draw_info->fill_pattern);
1427 if (LocaleCompare("tile-offset",option+1) == 0)
1429 /* SyncImageSettings() used to set per-image attribute. ??? */
1430 arg1=ArgOption("0");
1431 if (IfMagickFalse(IsGeometry(arg1)))
1432 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1433 (void) SetImageOption(_image_info,option+1,arg1);
1436 if (LocaleCompare("transparent-color",option+1) == 0)
1438 /* FUTURE: both _image_info attribute & ImageOption in use!
1439 _image_info only used for generating new images.
1440 SyncImageSettings() used to set per-image attribute.
1442 Note that +transparent-color, means fall-back to image
1443 attribute so ImageOption is deleted, not set to a default.
1445 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1446 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1447 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1448 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1449 &_image_info->transparent_color,_exception);
1452 if (LocaleCompare("treedepth",option+1) == 0)
1454 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1455 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1458 if (LocaleCompare("type",option+1) == 0)
1460 /* SyncImageSettings() used to set per-image attribute. */
1461 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1462 ArgOption("undefined"));
1464 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1466 _image_info->type=(ImageType) parse;
1467 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1470 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1474 if (LocaleCompare("undercolor",option+1) == 0)
1476 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1477 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1478 &_draw_info->undercolor,_exception);
1481 if (LocaleCompare("units",option+1) == 0)
1483 /* SyncImageSettings() used to set per-image attribute.
1484 Should this effect _draw_info X and Y resolution?
1485 FUTURE: this probably should be part of the density setting
1487 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1488 ArgOption("undefined"));
1490 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1492 _image_info->units=(ResolutionType) parse;
1493 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1496 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1500 if (LocaleCompare("verbose",option+1) == 0)
1502 /* FUTURE: Remember all options become image artifacts
1503 _image_info->verbose is only used by coders.
1505 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1506 _image_info->verbose= ArgBoolean;
1507 _image_info->ping=MagickFalse; /* verbose can't be a ping */
1510 if (LocaleCompare("view",option+1) == 0)
1512 /* FUTURE: Convert from _image_info to ImageOption
1513 Only used by coder FPX
1514 And it only tests existance, not its content!
1516 (void) CloneString(&_image_info->view,ArgOption(NULL));
1519 if (LocaleCompare("virtual-pixel",option+1) == 0)
1521 /* SyncImageSettings() used to set per-image attribute.
1522 This is VERY deep in the image caching structure.
1524 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1525 ArgOption("undefined"));
1527 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1529 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1532 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1536 if (LocaleCompare("weight",option+1) == 0)
1538 /* Just what does using a font 'weight' do ???
1539 There is no "-list weight" output (reference manual says there is)
1541 arg1=ArgOption("all");
1542 _draw_info->weight=StringToUnsignedLong(arg1);
1543 if (LocaleCompare(arg1,"all") == 0)
1544 _draw_info->weight=0;
1545 if (LocaleCompare(arg1,"bold") == 0)
1546 _draw_info->weight=700;
1547 if (LocaleCompare(arg1,"bolder") == 0)
1548 if (_draw_info->weight <= 800)
1549 _draw_info->weight+=100;
1550 if (LocaleCompare(arg1,"lighter") == 0)
1551 if (_draw_info->weight >= 100)
1552 _draw_info->weight-=100;
1553 if (LocaleCompare(arg1,"normal") == 0)
1554 _draw_info->weight=400;
1557 if (LocaleCompare("white-point",option+1) == 0)
1559 /* Used as a image chromaticity setting
1560 SyncImageSettings() used to set per-image attribute.
1562 arg1=ArgOption("0.0");
1563 if (IfMagickFalse(IsGeometry(arg1)))
1564 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1565 (void) SetImageOption(_image_info,option+1,arg1);
1568 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1571 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1575 /* clean up percent escape interpreted strings */
1577 arg1=DestroyString((char *)arg1);
1579 arg2=DestroyString((char *)arg2);
1585 #undef _quantize_info
1588 #undef ArgBooleanNot
1589 #undef ArgBooleanString
1596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1600 + C L I S i m p l e O p e r a t o r I m a g e s %
1604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1606 % CLISimpleOperatorImages() applys one simple image operation given to all
1607 % the images in the CLI wand, using any per-image or global settings that was
1608 % previously saved in the CLI wand.
1610 % It is assumed that any such settings are up-to-date.
1612 % The format of the WandSimpleOperatorImages method is:
1614 % void CLISimpleOperatorImages(MagickCLI *cli_wand,
1615 % const char *option, const char *arg1, const char *arg2)
1617 % A description of each parameter follows:
1619 % o cli_wand: structure holding settings and images to be operated on
1621 % o option: The option string for the operation
1623 % o arg1, arg2: optional argument strings to the operation
1628 CLISimpleOperatorImage() is an Internal subrountine to apply one simple
1629 image operation to the current image pointed to by the CLI wand.
1631 The image in the list may be modified in three different ways...
1632 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1633 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1634 * one image replace by a list of images (-separate and -crop only!)
1636 In each case the result replaces the single original image in the list, as
1637 well as the pointer to the modified image (last image added if replaced by a
1638 list of images) is returned.
1640 As the image pointed to may be replaced, the first image in the list may
1641 also change. GetFirstImageInList() should be used by caller if they wish
1642 return the Image pointer to the first image in list.
1644 static void CLISimpleOperatorImage(MagickCLI *cli_wand,
1645 const char *option, const char *arg1n, const char *arg2n)
1662 const char /* For percent escape interpretImageProperties() */
1666 #define _image_info (cli_wand->wand.image_info)
1667 #define _image (cli_wand->wand.images)
1668 #define _exception (cli_wand->wand.exception)
1669 #define _draw_info (cli_wand->draw_info)
1670 #define _quantize_info (cli_wand->quantize_info)
1671 #define _process_flags (cli_wand->process_flags)
1672 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
1673 #define IfNormalOp (*option=='-')
1674 #define IfPlusOp (*option!='-')
1675 #define normal_op IsMagickTrue(IfNormalOp)
1676 #define plus_alt_op IsMagickFalse(IfNormalOp)
1678 assert(cli_wand != (MagickCLI *) NULL);
1679 assert(cli_wand->signature == WandSignature);
1680 assert(cli_wand->wand.signature == WandSignature);
1681 assert(_image != (Image *) NULL); /* an image must be present */
1682 if (IfMagickTrue(cli_wand->wand.debug))
1683 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
1685 /* Interpret Percent Escapes in Arguments - using first image */
1688 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
1689 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
1690 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
1691 /* Interpret Percent escapes in argument 1 */
1692 if (arg1n != (char *) NULL) {
1693 arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
1694 if (arg1 == (char *) NULL) {
1695 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1696 arg1=arg1n; /* use the given argument as is */
1699 if (arg2n != (char *) NULL) {
1700 arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
1701 if (arg2 == (char *) NULL) {
1702 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
1703 arg2=arg2n; /* use the given argument as is */
1707 #undef _process_flags
1711 (void) FormatLocaleFile(stderr,
1712 "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
1715 new_image = (Image *)NULL; /* the replacement image, if not null at end */
1716 SetGeometryInfo(&geometry_info);
1718 switch (*(option+1))
1722 if (LocaleCompare("adaptive-blur",option+1) == 0)
1724 flags=ParseGeometry(arg1,&geometry_info);
1725 if ((flags & (RhoValue|SigmaValue)) == 0)
1726 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1727 if ((flags & SigmaValue) == 0)
1728 geometry_info.sigma=1.0;
1729 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1730 geometry_info.sigma,_exception);
1733 if (LocaleCompare("adaptive-resize",option+1) == 0)
1735 /* FUTURE: Roll into a resize special operator */
1736 if (IfMagickFalse(IsGeometry(arg1)))
1737 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1738 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1739 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1743 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
1745 flags=ParseGeometry(arg1,&geometry_info);
1746 if ((flags & (RhoValue|SigmaValue)) == 0)
1747 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1748 if ((flags & SigmaValue) == 0)
1749 geometry_info.sigma=1.0;
1750 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1751 geometry_info.sigma,_exception);
1754 if (LocaleCompare("alpha",option+1) == 0)
1756 parse=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,arg1);
1758 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelOption",
1760 (void) SetImageAlphaChannel(_image,(AlphaChannelOption)parse,
1764 if (LocaleCompare("annotate",option+1) == 0)
1767 geometry[MaxTextExtent];
1769 SetGeometryInfo(&geometry_info);
1770 flags=ParseGeometry(arg1,&geometry_info);
1772 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1773 if ((flags & SigmaValue) == 0)
1774 geometry_info.sigma=geometry_info.rho;
1775 (void) CloneString(&_draw_info->text,arg2);
1776 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1777 geometry_info.xi,geometry_info.psi);
1778 (void) CloneString(&_draw_info->geometry,geometry);
1779 _draw_info->affine.sx=cos(DegreesToRadians(
1780 fmod(geometry_info.rho,360.0)));
1781 _draw_info->affine.rx=sin(DegreesToRadians(
1782 fmod(geometry_info.rho,360.0)));
1783 _draw_info->affine.ry=(-sin(DegreesToRadians(
1784 fmod(geometry_info.sigma,360.0))));
1785 _draw_info->affine.sy=cos(DegreesToRadians(
1786 fmod(geometry_info.sigma,360.0)));
1787 (void) AnnotateImage(_image,_draw_info,_exception);
1788 GetAffineMatrix(&_draw_info->affine);
1791 if (LocaleCompare("auto-gamma",option+1) == 0)
1793 (void) AutoGammaImage(_image,_exception);
1796 if (LocaleCompare("auto-level",option+1) == 0)
1798 (void) AutoLevelImage(_image,_exception);
1801 if (LocaleCompare("auto-orient",option+1) == 0)
1803 new_image=AutoOrientImage(_image,_image->orientation,_exception);
1806 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1810 if (LocaleCompare("black-threshold",option+1) == 0)
1812 if (IfMagickFalse(IsGeometry(arg1)))
1813 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1814 (void) BlackThresholdImage(_image,arg1,_exception);
1817 if (LocaleCompare("blue-shift",option+1) == 0)
1819 geometry_info.rho=1.5;
1821 flags=ParseGeometry(arg1,&geometry_info);
1822 if ((flags & RhoValue) == 0)
1823 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1825 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
1828 if (LocaleCompare("blur",option+1) == 0)
1830 flags=ParseGeometry(arg1,&geometry_info);
1831 if ((flags & (RhoValue|SigmaValue)) == 0)
1832 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1833 if ((flags & SigmaValue) == 0)
1834 geometry_info.sigma=1.0;
1835 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1839 if (LocaleCompare("border",option+1) == 0)
1847 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
1848 if ((flags & (WidthValue | HeightValue)) == 0)
1849 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1850 compose=OverCompositeOp;
1851 value=GetImageOption(_image_info,"compose");
1852 if (value != (const char *) NULL)
1853 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
1855 new_image=BorderImage(_image,&geometry,compose,_exception);
1858 if (LocaleCompare("brightness-contrast",option+1) == 0)
1870 flags=ParseGeometry(arg1,&geometry_info);
1871 if ((flags & RhoValue) == 0)
1872 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1873 brightness=geometry_info.rho;
1875 if ((flags & SigmaValue) != 0)
1876 contrast=geometry_info.sigma;
1877 (void) BrightnessContrastImage(_image,brightness,contrast,
1881 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1885 if (LocaleCompare("cdl",option+1) == 0)
1887 /* Note: arguments do not have percent escapes expanded */
1889 *color_correction_collection;
1892 Color correct with a color decision list.
1894 color_correction_collection=FileToString(arg1,~0,_exception);
1895 if (color_correction_collection == (char *) NULL)
1897 (void) ColorDecisionListImage(_image,color_correction_collection,
1901 if (LocaleCompare("charcoal",option+1) == 0)
1903 flags=ParseGeometry(arg1,&geometry_info);
1904 if ((flags & (RhoValue|SigmaValue)) == 0)
1905 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1906 if ((flags & SigmaValue) == 0)
1907 geometry_info.sigma=1.0;
1908 if ((flags & XiValue) == 0)
1909 geometry_info.xi=1.0;
1910 new_image=CharcoalImage(_image,geometry_info.rho,geometry_info.sigma,
1914 if (LocaleCompare("chop",option+1) == 0)
1916 if (IfMagickFalse(IsGeometry(arg1)))
1917 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1918 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1919 new_image=ChopImage(_image,&geometry,_exception);
1922 if (LocaleCompare("clamp",option+1) == 0)
1924 (void) ClampImage(_image,_exception);
1927 if (LocaleCompare("clip",option+1) == 0)
1930 (void) ClipImage(_image,_exception);
1931 else /* "+mask" remove the write mask */
1932 (void) SetImageMask(_image,(Image *) NULL,_exception);
1935 if (LocaleCompare("clip-mask",option+1) == 0)
1937 /* Note: arguments do not have percent escapes expanded */
1954 /* use "+clip-mask" Remove the write mask for -clip-path */
1955 (void) SetImageMask(_image,(Image *) NULL,_exception);
1958 mask_image=GetImageCache(_image_info,arg1,_exception);
1959 if (mask_image == (Image *) NULL)
1961 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
1963 /* Create a write mask from cli_wand mask image */
1964 /* FUTURE: use Alpha operations instead and create a Grey Image */
1965 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
1966 for (y=0; y < (ssize_t) mask_image->rows; y++)
1968 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1970 if (q == (Quantum *) NULL)
1972 for (x=0; x < (ssize_t) mask_image->columns; x++)
1974 if (IfMagickFalse(mask_image->alpha_trait))
1975 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1976 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1977 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1978 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1979 q+=GetPixelChannels(mask_image);
1981 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
1984 /* clean up and set the write mask */
1985 mask_view=DestroyCacheView(mask_view);
1986 mask_image->alpha_trait=BlendPixelTrait;
1987 (void) SetImageMask(_image,mask_image,_exception);
1988 mask_image=DestroyImage(mask_image);
1991 if (LocaleCompare("clip-path",option+1) == 0)
1993 (void) ClipImagePath(_image,arg1,normal_op,_exception);
1994 /* Note: Use "+clip-mask" remove the write mask added */
1997 if (LocaleCompare("colorize",option+1) == 0)
1999 if (IfMagickFalse(IsGeometry(arg1)))
2000 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2001 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
2004 if (LocaleCompare("color-matrix",option+1) == 0)
2009 kernel=AcquireKernelInfo(arg1);
2010 if (kernel == (KernelInfo *) NULL)
2011 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2012 new_image=ColorMatrixImage(_image,kernel,_exception);
2013 kernel=DestroyKernelInfo(kernel);
2016 if (LocaleCompare("colors",option+1) == 0)
2018 /* Reduce the number of colors in the image.
2019 FUTURE: also provide 'plus version with image 'color counts'
2021 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2022 if (_quantize_info->number_colors == 0)
2023 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2024 if ((_image->storage_class == DirectClass) ||
2025 _image->colors > _quantize_info->number_colors)
2026 (void) QuantizeImage(_quantize_info,_image,_exception);
2028 (void) CompressImageColormap(_image,_exception);
2031 if (LocaleCompare("colorspace",option+1) == 0)
2033 /* WARNING: this is both a image_info setting (already done)
2034 and a operator to change image colorspace.
2036 FUTURE: default colorspace should be sRGB!
2037 Unless some type of 'linear colorspace' mode is set.
2039 Note that +colorspace sets "undefined" or no effect on
2040 new images, but forces images already in memory back to RGB!
2041 That seems to be a little strange!
2043 (void) TransformImageColorspace(_image,
2044 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2048 if (LocaleCompare("contrast",option+1) == 0)
2050 CLIWandWarnReplaced(normal_op?"-level":"+level");
2051 (void) ContrastImage(_image,normal_op,_exception);
2054 if (LocaleCompare("contrast-stretch",option+1) == 0)
2063 flags=ParseGeometry(arg1,&geometry_info);
2064 if ((flags & RhoValue) == 0)
2065 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2066 black_point=geometry_info.rho;
2067 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2069 if ((flags & PercentValue) != 0) {
2070 black_point*=(double) _image->columns*_image->rows/100.0;
2071 white_point*=(double) _image->columns*_image->rows/100.0;
2073 white_point=(double) _image->columns*_image->rows-
2075 (void) ContrastStretchImage(_image,black_point,white_point,
2079 if (LocaleCompare("convolve",option+1) == 0)
2084 kernel_info=AcquireKernelInfo(arg1);
2085 if (kernel_info == (KernelInfo *) NULL)
2086 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2087 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2089 kernel_info=DestroyKernelInfo(kernel_info);
2092 if (LocaleCompare("crop",option+1) == 0)
2094 /* WARNING: This can generate multiple images! */
2095 if (IfMagickFalse(IsGeometry(arg1)))
2096 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2097 new_image=CropImageToTiles(_image,arg1,_exception);
2100 if (LocaleCompare("cycle",option+1) == 0)
2102 if (IfMagickFalse(IsGeometry(arg1)))
2103 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2104 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2108 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2112 if (LocaleCompare("decipher",option+1) == 0)
2114 /* Note: arguments do not have percent escapes expanded */
2118 passkey=FileToStringInfo(arg1,~0,_exception);
2119 if (passkey == (StringInfo *) NULL)
2120 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2122 (void) PasskeyDecipherImage(_image,passkey,_exception);
2123 passkey=DestroyStringInfo(passkey);
2126 if (LocaleCompare("depth",option+1) == 0)
2128 /* The _image_info->depth setting has already been set
2129 We just need to apply it to all images in current sequence
2131 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2132 That is it really is an operation, not a setting! Arrgghhh
2134 FUTURE: this should not be an operator!!!
2136 (void) SetImageDepth(_image,_image_info->depth,_exception);
2139 if (LocaleCompare("deskew",option+1) == 0)
2145 if (IfMagickFalse(IsGeometry(arg1)))
2146 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2147 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
2150 threshold=40.0*QuantumRange/100.0;
2151 new_image=DeskewImage(_image,threshold,_exception);
2154 if (LocaleCompare("despeckle",option+1) == 0)
2156 new_image=DespeckleImage(_image,_exception);
2159 if (LocaleCompare("distort",option+1) == 0)
2167 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2169 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2171 if ((DistortImageMethod) parse == ResizeDistortion)
2175 /* Special Case - Argument is actually a resize geometry!
2176 ** Convert that to an appropriate distortion argument array.
2177 ** FUTURE: make a separate special resize operator
2178 Roll into a resize special operator */
2179 if (IfMagickFalse(IsGeometry(arg2)))
2180 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2182 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
2183 resize_args[0]=(double) geometry.width;
2184 resize_args[1]=(double) geometry.height;
2185 new_image=DistortImage(_image,(DistortImageMethod) parse,
2186 (size_t)2,resize_args,MagickTrue,_exception);
2189 /* convert argument string into an array of doubles */
2190 args = StringToArrayOfDoubles(arg2,&count,_exception);
2191 if (args == (double *)NULL )
2192 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2194 new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
2195 plus_alt_op,_exception);
2196 args=(double *) RelinquishMagickMemory(args);
2199 if (LocaleCompare("draw",option+1) == 0)
2201 (void) CloneString(&_draw_info->primitive,arg1);
2202 (void) DrawImage(_image,_draw_info,_exception);
2203 (void) CloneString(&_draw_info->primitive,(char *)NULL);
2206 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2210 if (LocaleCompare("edge",option+1) == 0)
2212 flags=ParseGeometry(arg1,&geometry_info);
2213 if ((flags & (RhoValue|SigmaValue)) == 0)
2214 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2215 if ((flags & SigmaValue) == 0)
2216 geometry_info.sigma=1.0;
2217 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2221 if (LocaleCompare("emboss",option+1) == 0)
2223 flags=ParseGeometry(arg1,&geometry_info);
2224 if ((flags & (RhoValue|SigmaValue)) == 0)
2225 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2226 if ((flags & SigmaValue) == 0)
2227 geometry_info.sigma=1.0;
2228 new_image=EmbossImage(_image,geometry_info.rho,
2229 geometry_info.sigma,_exception);
2232 if (LocaleCompare("encipher",option+1) == 0)
2234 /* Note: arguments do not have percent escapes expanded */
2238 passkey=FileToStringInfo(arg1,~0,_exception);
2239 if (passkey != (StringInfo *) NULL)
2241 (void) PasskeyEncipherImage(_image,passkey,_exception);
2242 passkey=DestroyStringInfo(passkey);
2246 if (LocaleCompare("enhance",option+1) == 0)
2248 new_image=EnhanceImage(_image,_exception);
2251 if (LocaleCompare("equalize",option+1) == 0)
2253 (void) EqualizeImage(_image,_exception);
2256 if (LocaleCompare("evaluate",option+1) == 0)
2261 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2263 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2265 if (IfMagickFalse(IsGeometry(arg2)))
2266 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
2267 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
2268 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2272 if (LocaleCompare("extent",option+1) == 0)
2274 if (IfMagickFalse(IsGeometry(arg1)))
2275 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2276 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
2277 if (geometry.width == 0)
2278 geometry.width=_image->columns;
2279 if (geometry.height == 0)
2280 geometry.height=_image->rows;
2281 new_image=ExtentImage(_image,&geometry,_exception);
2284 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2288 if (LocaleCompare("features",option+1) == 0)
2290 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
2292 (void) DeleteImageArtifact(_image,"identify:features");
2295 (void) SetImageArtifact(_image,"identify:features","true");
2296 (void) SetImageArtifact(_image,"verbose","true");
2299 if (LocaleCompare("flip",option+1) == 0)
2301 new_image=FlipImage(_image,_exception);
2304 if (LocaleCompare("flop",option+1) == 0)
2306 new_image=FlopImage(_image,_exception);
2309 if (LocaleCompare("floodfill",option+1) == 0)
2314 if (IfMagickFalse(IsGeometry(arg1)))
2315 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2316 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2317 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2318 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2319 geometry.y,plus_alt_op,_exception);
2322 if (LocaleCompare("frame",option+1) == 0)
2333 value=GetImageOption(_image_info,"compose");
2334 compose=OverCompositeOp; /* use Over not _image->compose */
2335 if (value != (const char *) NULL)
2336 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
2338 if (IfMagickFalse(IsGeometry(arg1)))
2339 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2340 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
2341 frame_info.width=geometry.width;
2342 frame_info.height=geometry.height;
2343 frame_info.outer_bevel=geometry.x;
2344 frame_info.inner_bevel=geometry.y;
2345 frame_info.x=(ssize_t) frame_info.width;
2346 frame_info.y=(ssize_t) frame_info.height;
2347 frame_info.width=_image->columns+2*frame_info.width;
2348 frame_info.height=_image->rows+2*frame_info.height;
2349 new_image=FrameImage(_image,&frame_info,compose,_exception);
2352 if (LocaleCompare("function",option+1) == 0)
2360 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2362 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2364 /* convert argument string into an array of doubles */
2365 args = StringToArrayOfDoubles(arg2,&count,_exception);
2366 if (args == (double *)NULL )
2367 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2369 (void) FunctionImage(_image,(MagickFunction)parse,count,args,
2371 args=(double *) RelinquishMagickMemory(args);
2374 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2378 if (LocaleCompare("gamma",option+1) == 0)
2383 if (IfMagickFalse(IsGeometry(arg1)))
2384 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2385 constant=StringToDouble(arg1,(char **) NULL);
2387 /* Using Gamma, via a cache */
2389 constant=PerceptibleReciprocal(constant);
2390 (void) GammaImage(_image,constant,_exception);
2392 /* Using Evaluate POW, direct update of values - more accurite */
2394 constant=PerceptibleReciprocal(constant);
2395 (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
2397 /* Set gamma setting -- Old meaning of "+gamma"
2398 * _image->gamma=StringToDouble(arg1,(char **) NULL);
2402 if (LocaleCompare("gaussian-blur",option+1) == 0)
2404 flags=ParseGeometry(arg1,&geometry_info);
2405 if ((flags & (RhoValue|SigmaValue)) == 0)
2406 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2407 if ((flags & SigmaValue) == 0)
2408 geometry_info.sigma=1.0;
2409 new_image=GaussianBlurImage(_image,geometry_info.rho,
2410 geometry_info.sigma,_exception);
2413 if (LocaleCompare("gaussian",option+1) == 0)
2415 CLIWandWarnReplaced("-gaussian-blur");
2416 CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL);
2418 if (LocaleCompare("geometry",option+1) == 0)
2421 Record Image offset for composition. (A Setting)
2422 Resize last _image. (ListOperator) -- DEPRECIATE
2423 FUTURE: Why if no 'offset' does this resize ALL images?
2424 Also why is the setting recorded in the IMAGE non-sense!
2427 { /* remove the previous composition geometry offset! */
2428 if (_image->geometry != (char *) NULL)
2429 _image->geometry=DestroyString(_image->geometry);
2432 if (IfMagickFalse(IsGeometry(arg1)))
2433 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2434 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
2435 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2436 (void) CloneString(&_image->geometry,arg1);
2438 new_image=ResizeImage(_image,geometry.width,geometry.height,
2439 _image->filter,_exception);
2442 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2446 if (LocaleCompare("identify",option+1) == 0)
2452 format=GetImageOption(_image_info,"format");
2453 if (format == (char *) NULL) {
2454 (void) IdentifyImage(_image,stdout,_image_info->verbose,_exception);
2457 text=InterpretImageProperties(_image_info,_image,format,_exception);
2458 if (text == (char *) NULL)
2459 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
2461 (void) fputs(text,stdout);
2462 (void) fputc('\n',stdout);
2463 text=DestroyString((char *)text);
2466 if (LocaleCompare("implode",option+1) == 0)
2468 flags=ParseGeometry(arg1,&geometry_info);
2469 if ((flags & RhoValue) == 0)
2470 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2471 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2475 if (LocaleCompare("interpolative-resize",option+1) == 0)
2477 /* FUTURE: New to IMv7
2478 Roll into a resize special operator */
2479 if (IfMagickFalse(IsGeometry(arg1)))
2480 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2481 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2482 new_image=InterpolativeResizeImage(_image,geometry.width,
2483 geometry.height,_image->interpolate,_exception);
2486 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2490 if (LocaleCompare("lat",option+1) == 0)
2492 flags=ParseGeometry(arg1,&geometry_info);
2493 if ((flags & (RhoValue|SigmaValue)) == 0)
2494 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2495 if ((flags & SigmaValue) == 0)
2496 geometry_info.sigma=1.0;
2497 if ((flags & PercentValue) != 0)
2498 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2499 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
2500 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2504 if (LocaleCompare("level",option+1) == 0)
2514 flags=ParseGeometry(arg1,&geometry_info);
2515 if ((flags & RhoValue) == 0)
2516 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2517 black_point=geometry_info.rho;
2518 white_point=(double) QuantumRange;
2519 if ((flags & SigmaValue) != 0)
2520 white_point=geometry_info.sigma;
2522 if ((flags & XiValue) != 0)
2523 gamma=geometry_info.xi;
2524 if ((flags & PercentValue) != 0)
2526 black_point*=(double) (QuantumRange/100.0);
2527 white_point*=(double) (QuantumRange/100.0);
2529 if ((flags & SigmaValue) == 0)
2530 white_point=(double) QuantumRange-black_point;
2531 if (IfPlusOp || ((flags & AspectValue) != 0))
2532 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
2534 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
2537 if (LocaleCompare("level-colors",option+1) == 0)
2540 token[MaxTextExtent];
2549 p=(const char *) arg1;
2550 GetMagickToken(p,&p,token); /* get black point color */
2551 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2552 (void) QueryColorCompliance(token,AllCompliance,
2553 &black_point,_exception);
2555 (void) QueryColorCompliance("#000000",AllCompliance,
2556 &black_point,_exception);
2557 if (isalpha((int) token[0]) || (token[0] == '#'))
2558 GetMagickToken(p,&p,token);
2560 white_point=black_point; /* set everything to that color */
2563 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2564 GetMagickToken(p,&p,token); /* Get white point color. */
2565 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2566 (void) QueryColorCompliance(token,AllCompliance,
2567 &white_point,_exception);
2569 (void) QueryColorCompliance("#ffffff",AllCompliance,
2570 &white_point,_exception);
2572 (void) LevelImageColors(_image,&black_point,&white_point,
2573 plus_alt_op,_exception);
2576 if (LocaleCompare("linear-stretch",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) _image->columns*_image->rows;
2590 if ((flags & SigmaValue) != 0)
2591 white_point=geometry_info.sigma;
2592 if ((flags & PercentValue) != 0)
2594 black_point*=(double) _image->columns*_image->rows/100.0;
2595 white_point*=(double) _image->columns*_image->rows/100.0;
2597 if ((flags & SigmaValue) == 0)
2598 white_point=(double) _image->columns*_image->rows-
2600 (void) LinearStretchImage(_image,black_point,white_point,_exception);
2603 if (LocaleCompare("liquid-rescale",option+1) == 0)
2605 /* FUTURE: Roll into a resize special operator */
2606 if (IfMagickFalse(IsGeometry(arg1)))
2607 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2608 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
2609 if ((flags & XValue) == 0)
2611 if ((flags & YValue) == 0)
2613 new_image=LiquidRescaleImage(_image,geometry.width,
2614 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
2617 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2621 if (LocaleCompare("map",option+1) == 0)
2623 CLIWandWarnReplaced("-remap");
2624 CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL);
2627 if (LocaleCompare("mask",option+1) == 0)
2629 /* Note: arguments do not have percent escapes expanded */
2634 { /* Remove a mask. */
2635 (void) SetImageMask(_image,(Image *) NULL,_exception);
2638 /* Set the image mask. */
2639 mask=GetImageCache(_image_info,arg1,_exception);
2640 if (mask == (Image *) NULL)
2642 (void) SetImageMask(_image,mask,_exception);
2643 mask=DestroyImage(mask);
2646 if (LocaleCompare("matte",option+1) == 0)
2648 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
2649 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2650 DeactivateAlphaChannel, _exception);
2653 if (LocaleCompare("median",option+1) == 0)
2655 CLIWandWarnReplaced("-statistic Median");
2656 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2659 if (LocaleCompare("mode",option+1) == 0)
2661 /* FUTURE: note this is also a special "montage" option */
2662 CLIWandWarnReplaced("-statistic Mode");
2663 CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1);
2666 if (LocaleCompare("modulate",option+1) == 0)
2668 if (IfMagickFalse(IsGeometry(arg1)))
2669 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2670 (void) ModulateImage(_image,arg1,_exception);
2673 if (LocaleCompare("monitor",option+1) == 0)
2675 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
2676 (MagickProgressMonitor) NULL,(void *) NULL);
2679 if (LocaleCompare("monochrome",option+1) == 0)
2681 (void) SetImageType(_image,BilevelType,_exception);
2684 if (LocaleCompare("morphology",option+1) == 0)
2687 token[MaxTextExtent];
2699 GetMagickToken(p,&p,token);
2700 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2702 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2705 GetMagickToken(p,&p,token);
2706 if ((*p == ':') || (*p == ','))
2707 GetMagickToken(p,&p,token);
2709 iterations=(ssize_t) StringToLong(p);
2710 kernel=AcquireKernelInfo(arg2);
2711 if (kernel == (KernelInfo *) NULL)
2712 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2714 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2715 iterations,kernel,_exception);
2716 kernel=DestroyKernelInfo(kernel);
2719 if (LocaleCompare("motion-blur",option+1) == 0)
2721 flags=ParseGeometry(arg1,&geometry_info);
2722 if ((flags & (RhoValue|SigmaValue)) == 0)
2723 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2724 if ((flags & SigmaValue) == 0)
2725 geometry_info.sigma=1.0;
2726 new_image=MotionBlurImage(_image,geometry_info.rho,
2727 geometry_info.sigma,geometry_info.xi,_exception);
2730 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2734 if (LocaleCompare("negate",option+1) == 0)
2736 (void) NegateImage(_image, plus_alt_op, _exception);
2739 if (LocaleCompare("noise",option+1) == 0)
2749 CLIWandWarnReplaced("-statistic NonPeak");
2750 CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1);
2753 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2755 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2758 value=GetImageOption(_image_info,"attenuate");
2759 if (value != (const char *) NULL)
2760 attenuate=StringToDouble(value,(char **) NULL);
2761 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2765 if (LocaleCompare("normalize",option+1) == 0)
2767 (void) NormalizeImage(_image,_exception);
2770 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2774 if (LocaleCompare("opaque",option+1) == 0)
2779 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2780 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2784 if (LocaleCompare("ordered-dither",option+1) == 0)
2786 (void) OrderedPosterizeImage(_image,arg1,_exception);
2789 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2793 if (LocaleCompare("paint",option+1) == 0)
2795 flags=ParseGeometry(arg1,&geometry_info);
2796 if ((flags & (RhoValue|SigmaValue)) == 0)
2797 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2798 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2802 if (LocaleCompare("perceptible",option+1) == 0)
2804 (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
2808 if (LocaleCompare("polaroid",option+1) == 0)
2820 random_info=AcquireRandomInfo();
2821 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2822 random_info=DestroyRandomInfo(random_info);
2825 flags=ParseGeometry(arg1,&geometry_info);
2826 if ((flags & RhoValue) == 0)
2827 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2828 angle=geometry_info.rho;
2830 caption=GetImageProperty(_image,"caption",_exception);
2831 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2832 _image->interpolate,_exception);
2835 if (LocaleCompare("posterize",option+1) == 0)
2837 flags=ParseGeometry(arg1,&geometry_info);
2838 if ((flags & RhoValue) == 0)
2839 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2840 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
2841 _quantize_info->dither_method,_exception);
2844 if (LocaleCompare("preview",option+1) == 0)
2846 /* FUTURE: should be a 'Genesis' option?
2847 Option however is also in WandSettingOptionInfo()
2850 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2852 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2854 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
2857 if (LocaleCompare("profile",option+1) == 0)
2859 /* Note: arguments do not have percent escapes expanded */
2873 { /* Remove a profile from the _image. */
2874 (void) ProfileImage(_image,arg1,(const unsigned char *)
2878 /* Associate a profile with the _image. */
2879 profile_info=CloneImageInfo(_image_info);
2880 profile=GetImageProfile(_image,"iptc");
2881 if (profile != (StringInfo *) NULL)
2882 profile_info->profile=(void *) CloneStringInfo(profile);
2883 profile_image=GetImageCache(profile_info,arg1,_exception);
2884 profile_info=DestroyImageInfo(profile_info);
2885 if (profile_image == (Image *) NULL)
2890 profile_info=CloneImageInfo(_image_info);
2891 (void) CopyMagickString(profile_info->filename,arg1,
2893 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
2894 if (profile != (StringInfo *) NULL)
2896 (void) ProfileImage(_image,profile_info->magick,
2897 GetStringInfoDatum(profile),(size_t)
2898 GetStringInfoLength(profile),_exception);
2899 profile=DestroyStringInfo(profile);
2901 profile_info=DestroyImageInfo(profile_info);
2904 ResetImageProfileIterator(profile_image);
2905 name=GetNextImageProfile(profile_image);
2906 while (name != (const char *) NULL)
2908 profile=GetImageProfile(profile_image,name);
2909 if (profile != (StringInfo *) NULL)
2910 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2911 (size_t) GetStringInfoLength(profile),_exception);
2912 name=GetNextImageProfile(profile_image);
2914 profile_image=DestroyImage(profile_image);
2917 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2921 if (LocaleCompare("radial-blur",option+1) == 0)
2923 flags=ParseGeometry(arg1,&geometry_info);
2924 if ((flags & RhoValue) == 0)
2925 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2926 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
2929 if (LocaleCompare("raise",option+1) == 0)
2931 if (IfMagickFalse(IsGeometry(arg1)))
2932 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2933 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
2934 (void) RaiseImage(_image,&geometry,normal_op,_exception);
2937 if (LocaleCompare("random-threshold",option+1) == 0)
2939 if (IfMagickFalse(IsGeometry(arg1)))
2940 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2941 (void) RandomThresholdImage(_image,arg1,_exception);
2944 if (LocaleCompare("recolor",option+1) == 0)
2946 CLIWandWarnReplaced("-color-matrix");
2947 CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL);
2949 if (LocaleCompare("remap",option+1) == 0)
2951 /* Note: arguments do not have percent escapes expanded */
2955 remap_image=GetImageCache(_image_info,arg1,_exception);
2956 if (remap_image == (Image *) NULL)
2958 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
2959 remap_image=DestroyImage(remap_image);
2962 if (LocaleCompare("repage",option+1) == 0)
2966 if (IfMagickFalse(IsGeometry(arg1)))
2967 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
2969 (void) ResetImagePage(_image,arg1);
2972 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
2975 if (LocaleCompare("resample",option+1) == 0)
2977 /* FUTURE: Roll into a resize special operation */
2978 flags=ParseGeometry(arg1,&geometry_info);
2979 if ((flags & (RhoValue|SigmaValue)) == 0)
2980 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2981 if ((flags & SigmaValue) == 0)
2982 geometry_info.sigma=geometry_info.rho;
2983 new_image=ResampleImage(_image,geometry_info.rho,
2984 geometry_info.sigma,_image->filter,_exception);
2987 if (LocaleCompare("resize",option+1) == 0)
2989 if (IfMagickFalse(IsGeometry(arg1)))
2990 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2991 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2992 new_image=ResizeImage(_image,geometry.width,geometry.height,
2993 _image->filter,_exception);
2996 if (LocaleCompare("roll",option+1) == 0)
2998 if (IfMagickFalse(IsGeometry(arg1)))
2999 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3000 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3001 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
3004 if (LocaleCompare("rotate",option+1) == 0)
3006 flags=ParseGeometry(arg1,&geometry_info);
3007 if ((flags & RhoValue) == 0)
3008 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3009 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
3011 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
3013 new_image=RotateImage(_image,geometry_info.rho,_exception);
3016 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3020 if (LocaleCompare("sample",option+1) == 0)
3022 /* FUTURE: Roll into a resize special operator */
3023 if (IfMagickFalse(IsGeometry(arg1)))
3024 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3025 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3026 new_image=SampleImage(_image,geometry.width,geometry.height,
3030 if (LocaleCompare("scale",option+1) == 0)
3032 /* FUTURE: Roll into a resize special operator */
3033 if (IfMagickFalse(IsGeometry(arg1)))
3034 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3035 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3036 new_image=ScaleImage(_image,geometry.width,geometry.height,
3040 if (LocaleCompare("segment",option+1) == 0)
3042 flags=ParseGeometry(arg1,&geometry_info);
3043 if ((flags & (RhoValue|SigmaValue)) == 0)
3044 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3045 if ((flags & SigmaValue) == 0)
3046 geometry_info.sigma=1.0;
3047 (void) SegmentImage(_image,_image->colorspace,
3048 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3052 if (LocaleCompare("selective-blur",option+1) == 0)
3054 flags=ParseGeometry(arg1,&geometry_info);
3055 if ((flags & (RhoValue|SigmaValue)) == 0)
3056 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3057 if ((flags & SigmaValue) == 0)
3058 geometry_info.sigma=1.0;
3059 if ((flags & PercentValue) != 0)
3060 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3061 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3062 geometry_info.sigma,geometry_info.xi,_exception);
3065 if (LocaleCompare("separate",option+1) == 0)
3067 /* WARNING: This can generate multiple images! */
3068 /* FUTURE - this may be replaced by a "-channel" method */
3069 new_image=SeparateImages(_image,_exception);
3072 if (LocaleCompare("sepia-tone",option+1) == 0)
3074 if (IfMagickFalse(IsGeometry(arg1)))
3075 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3076 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3077 (double) QuantumRange+1.0),_exception);
3080 if (LocaleCompare("shade",option+1) == 0)
3082 flags=ParseGeometry(arg1,&geometry_info);
3083 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3084 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3085 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3086 geometry_info.sigma,_exception);
3089 if (LocaleCompare("shadow",option+1) == 0)
3091 flags=ParseGeometry(arg1,&geometry_info);
3092 if ((flags & (RhoValue|SigmaValue)) == 0)
3093 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3094 if ((flags & SigmaValue) == 0)
3095 geometry_info.sigma=1.0;
3096 if ((flags & XiValue) == 0)
3097 geometry_info.xi=4.0;
3098 if ((flags & PsiValue) == 0)
3099 geometry_info.psi=4.0;
3100 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3101 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3102 ceil(geometry_info.psi-0.5),_exception);
3105 if (LocaleCompare("sharpen",option+1) == 0)
3107 flags=ParseGeometry(arg1,&geometry_info);
3108 if ((flags & (RhoValue|SigmaValue)) == 0)
3109 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3110 if ((flags & SigmaValue) == 0)
3111 geometry_info.sigma=1.0;
3112 if ((flags & XiValue) == 0)
3113 geometry_info.xi=0.0;
3114 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3118 if (LocaleCompare("shave",option+1) == 0)
3120 if (IfMagickFalse(IsGeometry(arg1)))
3121 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3122 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3123 new_image=ShaveImage(_image,&geometry,_exception);
3126 if (LocaleCompare("shear",option+1) == 0)
3128 flags=ParseGeometry(arg1,&geometry_info);
3129 if ((flags & RhoValue) == 0)
3130 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3131 if ((flags & SigmaValue) == 0)
3132 geometry_info.sigma=geometry_info.rho;
3133 new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
3137 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
3139 flags=ParseGeometry(arg1,&geometry_info);
3140 if ((flags & RhoValue) == 0)
3141 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3142 if ((flags & SigmaValue) == 0)
3143 geometry_info.sigma=(double) QuantumRange/2.0;
3144 if ((flags & PercentValue) != 0)
3145 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3147 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
3148 geometry_info.sigma,_exception);
3151 if (LocaleCompare("sketch",option+1) == 0)
3153 flags=ParseGeometry(arg1,&geometry_info);
3154 if ((flags & (RhoValue|SigmaValue)) == 0)
3155 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3156 if ((flags & SigmaValue) == 0)
3157 geometry_info.sigma=1.0;
3158 new_image=SketchImage(_image,geometry_info.rho,
3159 geometry_info.sigma,geometry_info.xi,_exception);
3162 if (LocaleCompare("solarize",option+1) == 0)
3164 if (IfMagickFalse(IsGeometry(arg1)))
3165 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3166 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3167 QuantumRange+1.0),_exception);
3170 if (LocaleCompare("sparse-color",option+1) == 0)
3172 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3174 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3176 new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
3180 if (LocaleCompare("splice",option+1) == 0)
3182 if (IfMagickFalse(IsGeometry(arg1)))
3183 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3184 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
3185 new_image=SpliceImage(_image,&geometry,_exception);
3188 if (LocaleCompare("spread",option+1) == 0)
3190 flags=ParseGeometry(arg1,&geometry_info);
3191 if ((flags & RhoValue) == 0)
3192 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3193 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3197 if (LocaleCompare("statistic",option+1) == 0)
3199 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3201 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
3203 flags=ParseGeometry(arg2,&geometry_info);
3204 if ((flags & RhoValue) == 0)
3205 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3206 if ((flags & SigmaValue) == 0)
3207 geometry_info.sigma=geometry_info.rho;
3208 new_image=StatisticImage(_image,(StatisticType)parse,
3209 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3213 if (LocaleCompare("strip",option+1) == 0)
3215 (void) StripImage(_image,_exception);
3218 if (LocaleCompare("swirl",option+1) == 0)
3220 flags=ParseGeometry(arg1,&geometry_info);
3221 if ((flags & RhoValue) == 0)
3222 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3223 new_image=SwirlImage(_image,geometry_info.rho,
3224 _image->interpolate,_exception);
3227 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3231 if (LocaleCompare("threshold",option+1) == 0)
3236 threshold=(double) QuantumRange/2;
3238 if (IfMagickFalse(IsGeometry(arg1)))
3239 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3240 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
3242 (void) BilevelImage(_image,threshold,_exception);
3245 if (LocaleCompare("thumbnail",option+1) == 0)
3247 if (IfMagickFalse(IsGeometry(arg1)))
3248 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3249 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3250 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3254 if (LocaleCompare("tint",option+1) == 0)
3256 if (IfMagickFalse(IsGeometry(arg1)))
3257 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3258 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
3261 if (LocaleCompare("transform",option+1) == 0)
3263 CLIWandWarnReplaced("+distort AffineProjection");
3264 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
3267 if (LocaleCompare("transparent",option+1) == 0)
3272 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3273 (void) TransparentPaintImage(_image,&target,(Quantum)
3274 TransparentAlpha,plus_alt_op,_exception);
3277 if (LocaleCompare("transpose",option+1) == 0)
3279 new_image=TransposeImage(_image,_exception);
3282 if (LocaleCompare("transverse",option+1) == 0)
3284 new_image=TransverseImage(_image,_exception);
3287 if (LocaleCompare("trim",option+1) == 0)
3289 new_image=TrimImage(_image,_exception);
3292 if (LocaleCompare("type",option+1) == 0)
3294 /* Note that "type" setting should have already been defined */
3295 (void) SetImageType(_image,_image_info->type,_exception);
3298 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3302 if (LocaleCompare("unique",option+1) == 0)
3304 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3305 Option is not documented, bt appears to be for "identify".
3306 We may need a identify specific verbose!
3309 (void) DeleteImageArtifact(_image,"identify:unique-colors");
3312 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3313 (void) SetImageArtifact(_image,"verbose","true");
3316 if (LocaleCompare("unique-colors",option+1) == 0)
3318 new_image=UniqueImageColors(_image,_exception);
3321 if (LocaleCompare("unsharp",option+1) == 0)
3323 flags=ParseGeometry(arg1,&geometry_info);
3324 if ((flags & (RhoValue|SigmaValue)) == 0)
3325 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3326 if ((flags & SigmaValue) == 0)
3327 geometry_info.sigma=1.0;
3328 if ((flags & XiValue) == 0)
3329 geometry_info.xi=1.0;
3330 if ((flags & PsiValue) == 0)
3331 geometry_info.psi=0.05;
3332 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3333 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
3336 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3340 if (LocaleCompare("verbose",option+1) == 0)
3342 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
3343 three places! ImageArtifact ImageOption _image_info->verbose
3344 Some how new images also get this artifact!
3346 (void) SetImageArtifact(_image,option+1,
3347 IfNormalOp ? "true" : "false" );
3350 if (LocaleCompare("vignette",option+1) == 0)
3352 flags=ParseGeometry(arg1,&geometry_info);
3353 if ((flags & (RhoValue|SigmaValue)) == 0)
3354 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3355 if ((flags & SigmaValue) == 0)
3356 geometry_info.sigma=1.0;
3357 if ((flags & XiValue) == 0)
3358 geometry_info.xi=0.1*_image->columns;
3359 if ((flags & PsiValue) == 0)
3360 geometry_info.psi=0.1*_image->rows;
3361 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3362 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3363 ceil(geometry_info.psi-0.5),_exception);
3366 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3370 if (LocaleCompare("wave",option+1) == 0)
3372 flags=ParseGeometry(arg1,&geometry_info);
3373 if ((flags & (RhoValue|SigmaValue)) == 0)
3374 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3375 if ((flags & SigmaValue) == 0)
3376 geometry_info.sigma=1.0;
3377 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3378 _image->interpolate,_exception);
3381 if (LocaleCompare("white-threshold",option+1) == 0)
3383 if (IfMagickFalse(IsGeometry(arg1)))
3384 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3385 (void) WhiteThresholdImage(_image,arg1,_exception);
3388 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3391 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3393 /* clean up percent escape interpreted strings */
3395 arg1=DestroyString((char *)arg1);
3397 arg2=DestroyString((char *)arg2);
3399 /* Replace current image with any image that was generated
3400 and set image point to last image (so image->next is correct) */
3401 if (new_image != (Image *) NULL)
3402 ReplaceImageInListReturnLast(&_image,new_image);
3407 #undef _quantize_info
3416 WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
3417 const char *option, const char *arg1, const char *arg2)
3419 #if !USE_WAND_METHODS
3425 assert(cli_wand != (MagickCLI *) NULL);
3426 assert(cli_wand->signature == WandSignature);
3427 assert(cli_wand->wand.signature == WandSignature);
3428 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3429 if (IfMagickTrue(cli_wand->wand.debug))
3430 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
3432 #if !USE_WAND_METHODS
3433 /* FUTURE add appropriate tracing */
3435 n=GetImageListLength(cli_wand->wand.images);
3436 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3439 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3440 if ( cli_wand->wand.images->next == (Image *) NULL )
3442 cli_wand->wand.images=cli_wand->wand.images->next;
3445 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3447 MagickResetIterator(&cli_wand->wand);
3448 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
3449 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3450 MagickResetIterator(&cli_wand->wand);
3456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3460 + C L I L i s t O p e r a t o r I m a g e s %
3464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3466 % CLIListOperatorImages() applies a single operation that is apply to the
3467 % entire image list as a whole. The result is often a complete replacment
3468 % of the image list with a completely new list, or with just a single image
3471 % The format of the MogrifyImage method is:
3473 % void CLIListOperatorImages(MagickCLI *cli_wand,
3474 % const char *option, const char *arg1, const char *arg2)
3476 % A description of each parameter follows:
3478 % o cli_wand: structure holding settings to be applied
3480 % o option: The option string for the operation
3482 % o arg1, arg2: optional argument strings to the operation
3483 % arg2 is currently not used
3486 WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
3487 const char *option,const char *arg1n, const char *arg2n)
3495 const char /* For percent escape interpretImageProperties() */
3499 #define _image_info (cli_wand->wand.image_info)
3500 #define _images (cli_wand->wand.images)
3501 #define _exception (cli_wand->wand.exception)
3502 #define _draw_info (cli_wand->draw_info)
3503 #define _quantize_info (cli_wand->quantize_info)
3504 #define _process_flags (cli_wand->process_flags)
3505 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
3506 #define IfNormalOp (*option=='-')
3507 #define IfPlusOp (*option!='-')
3508 #define normal_op IsMagickTrue(IfNormalOp)
3510 assert(cli_wand != (MagickCLI *) NULL);
3511 assert(cli_wand->signature == WandSignature);
3512 assert(cli_wand->wand.signature == WandSignature);
3513 assert(_images != (Image *) NULL); /* _images must be present */
3514 if (IfMagickTrue(cli_wand->wand.debug))
3515 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
3517 /* Interpret Percent Escapes in Arguments - using first image */
3520 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
3521 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
3522 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
3523 /* Interpret Percent escapes in argument 1 */
3524 if (arg1n != (char *) NULL) {
3525 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
3526 if (arg1 == (char *) NULL) {
3527 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3528 arg1=arg1n; /* use the given argument as is */
3531 if (arg2n != (char *) NULL) {
3532 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
3533 if (arg2 == (char *) NULL) {
3534 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
3535 arg2=arg2n; /* use the given argument as is */
3539 #undef _process_flags
3543 (void) FormatLocaleFile(stderr,
3544 "CLIListOperatorImages: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
3548 new_images=NewImageList();
3550 switch (*(option+1))
3554 if (LocaleCompare("append",option+1) == 0)
3556 new_images=AppendImages(_images,normal_op,_exception);
3559 if (LocaleCompare("average",option+1) == 0)
3561 CLIWandWarnReplaced("-evaluate-sequence Mean");
3562 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
3565 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3569 if (LocaleCompare("channel-fx",option+1) == 0)
3571 new_images=ChannelFxImage(_images,arg1,_exception);
3574 if (LocaleCompare("clut",option+1) == 0)
3579 /* FUTURE - make this a compose option, and thus can be used
3580 with layers compose or even compose last image over all other
3583 new_images=RemoveFirstImageFromList(&_images);
3584 clut_image=RemoveLastImageFromList(&_images);
3585 /* FUTURE - produce Exception, rather than silent fail */
3586 if (clut_image == (Image *) NULL)
3588 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
3589 clut_image=DestroyImage(clut_image);
3592 if (LocaleCompare("coalesce",option+1) == 0)
3594 new_images=CoalesceImages(_images,_exception);
3597 if (LocaleCompare("combine",option+1) == 0)
3599 /* FUTURE - this may be replaced by a 'channel' method */
3600 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
3601 new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
3604 if (LocaleCompare("composite",option+1) == 0)
3622 /* Compose value from "-compose" option only */
3623 value=GetImageOption(_image_info,"compose");
3624 if (value == (const char *) NULL)
3625 compose=OverCompositeOp; /* use Over not source_image->compose */
3627 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3630 /* Get "clip-to-self" expert setting (false is normal) */
3631 value=GetImageOption(_image_info,"compose:clip-to-self");
3632 if (value == (const char *) NULL)
3633 clip_to_self=MagickTrue;
3635 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3636 "compose:clip-to-self")); /* if this is true */
3637 value=GetImageOption(_image_info,"compose:outside-overlay");
3638 if (value != (const char *) NULL) { /* or this false */
3639 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
3640 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
3643 new_images=RemoveFirstImageFromList(&_images);
3644 source_image=RemoveFirstImageFromList(&_images);
3645 if (source_image == (Image *) NULL)
3646 break; /* FUTURE - produce Exception, rather than silent fail */
3648 /* FUTURE - this should not be here! - should be part of -geometry */
3649 (void) TransformImage(&source_image,(char *) NULL,
3650 source_image->geometry,_exception);
3652 SetGeometry(source_image,&geometry);
3653 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3654 GravityAdjustGeometry(new_images->columns,new_images->rows,
3655 new_images->gravity, &geometry);
3657 mask_image=RemoveFirstImageFromList(&_images);
3658 if (mask_image != (Image *) NULL)
3659 { /* handle a third write mask image */
3660 if ((compose == DisplaceCompositeOp) ||
3661 (compose == DistortCompositeOp)) {
3662 /* Merge Y displacement into X displace/distort map. */
3663 (void) CompositeImage(source_image,mask_image,
3664 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3665 mask_image=DestroyImage(mask_image);
3668 /* Set a blending mask for the composition. */
3669 (void) NegateImage(mask_image,MagickFalse,_exception);
3670 (void) SetImageMask(source_image,mask_image,_exception);
3671 mask_image=DestroyImage(mask_image);
3674 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3675 geometry.x,geometry.y,_exception);
3676 (void) SetImageMask(new_images,(Image *) NULL,_exception);
3677 source_image=DestroyImage(source_image);
3680 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3684 if (LocaleCompare("deconstruct",option+1) == 0)
3686 CLIWandWarnReplaced("-layer CompareAny");
3687 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
3690 if (LocaleCompare("delete",option+1) == 0)
3693 DeleteImages(&_images,arg1,_exception);
3695 DeleteImages(&_images,"-1",_exception);
3698 if (LocaleCompare("duplicate",option+1) == 0)
3708 if (IfMagickFalse(IsGeometry(arg1)))
3709 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3711 number_duplicates=(size_t) StringToLong(arg1);
3713 if (p == (const char *) NULL)
3714 new_images=DuplicateImages(_images,number_duplicates,"-1",
3717 new_images=DuplicateImages(_images,number_duplicates,p,
3721 new_images=DuplicateImages(_images,1,"-1",_exception);
3722 AppendImageToList(&_images, new_images);
3723 new_images=(Image *)NULL;
3726 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3730 if (LocaleCompare("evaluate-sequence",option+1) == 0)
3732 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3734 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3736 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3740 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3744 if (LocaleCompare("fft",option+1) == 0)
3746 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
3749 if (LocaleCompare("flatten",option+1) == 0)
3751 /* REDIRECTED to use -layers flatten instead */
3752 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
3755 if (LocaleCompare("fx",option+1) == 0)
3757 new_images=FxImage(_images,arg1,_exception);
3760 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3764 if (LocaleCompare("hald-clut",option+1) == 0)
3766 /* FUTURE - make this a compose option (and thus layers compose )
3767 or perhaps compose last image over all other _images.
3772 new_images=RemoveFirstImageFromList(&_images);
3773 hald_image=RemoveLastImageFromList(&_images);
3774 if (hald_image == (Image *) NULL)
3776 (void) HaldClutImage(new_images,hald_image,_exception);
3777 hald_image=DestroyImage(hald_image);
3780 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3784 if (LocaleCompare("ift",option+1) == 0)
3790 magnitude_image=RemoveFirstImageFromList(&_images);
3791 phase_image=RemoveFirstImageFromList(&_images);
3792 /* FUTURE - produce Exception, rather than silent fail */
3793 if (phase_image == (Image *) NULL)
3795 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
3796 normal_op,_exception);
3797 magnitude_image=DestroyImage(magnitude_image);
3798 phase_image=DestroyImage(phase_image);
3801 if (LocaleCompare("insert",option+1) == 0)
3810 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
3811 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3813 insert_image=RemoveLastImageFromList(&_images);
3815 index=(ssize_t) StringToLong(arg1);
3816 index_image=insert_image;
3818 PrependImageToList(&_images,insert_image);
3819 else if (index == (ssize_t) GetImageListLength(_images))
3820 AppendImageToList(&_images,insert_image);
3823 index_image=GetImageFromList(_images,index-1);
3824 if (index_image == (Image *) NULL)
3825 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
3826 InsertImageInList(&index_image,insert_image);
3828 _images=GetFirstImageInList(index_image);
3831 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3835 if (LocaleCompare("layers",option+1) == 0)
3837 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3839 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3841 switch ((LayerMethod) parse)
3845 new_images=CoalesceImages(_images,_exception);
3848 case CompareAnyLayer:
3849 case CompareClearLayer:
3850 case CompareOverlayLayer:
3853 new_images=CompareImagesLayers(_images,(LayerMethod) parse,
3860 case TrimBoundsLayer:
3862 new_images=MergeImageLayers(_images,(LayerMethod) parse,
3868 new_images=DisposeImages(_images,_exception);
3871 case OptimizeImageLayer:
3873 new_images=OptimizeImageLayers(_images,_exception);
3876 case OptimizePlusLayer:
3878 new_images=OptimizePlusImageLayers(_images,_exception);
3881 case OptimizeTransLayer:
3883 OptimizeImageTransparency(_images,_exception);
3886 case RemoveDupsLayer:
3888 RemoveDuplicateLayers(&_images,_exception);
3891 case RemoveZeroLayer:
3893 RemoveZeroDelayLayers(&_images,_exception);
3897 { /* General Purpose, GIF Animation Optimizer. */
3898 new_images=CoalesceImages(_images,_exception);
3899 if (new_images == (Image *) NULL)
3901 _images=DestroyImageList(_images);
3902 _images=OptimizeImageLayers(new_images,_exception);
3903 if (_images == (Image *) NULL)
3905 new_images=DestroyImageList(new_images);
3906 OptimizeImageTransparency(_images,_exception);
3907 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3911 case CompositeLayer:
3925 value=GetImageOption(_image_info,"compose");
3926 compose=OverCompositeOp; /* Default to Over */
3927 if (value != (const char *) NULL)
3928 compose=(CompositeOperator) ParseCommandOption(
3929 MagickComposeOptions,MagickFalse,value);
3931 /* Split image sequence at the first 'NULL:' image. */
3933 while (source != (Image *) NULL)
3935 source=GetNextImageInList(source);
3936 if ((source != (Image *) NULL) &&
3937 (LocaleCompare(source->magick,"NULL") == 0))
3940 if (source != (Image *) NULL)
3942 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3943 (GetNextImageInList(source) == (Image *) NULL))
3944 source=(Image *) NULL;
3946 { /* Separate the two lists, junk the null: image. */
3947 source=SplitImageList(source->previous);
3948 DeleteImageFromList(&source);
3951 if (source == (Image *) NULL)
3953 (void) ThrowMagickException(_exception,GetMagickModule(),
3954 OptionError,"MissingNullSeparator","layers Composite");
3957 /* Adjust offset with gravity and virtual canvas. */
3958 SetGeometry(_images,&geometry);
3959 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
3960 geometry.width=source->page.width != 0 ?
3961 source->page.width : source->columns;
3962 geometry.height=source->page.height != 0 ?
3963 source->page.height : source->rows;
3964 GravityAdjustGeometry(_images->page.width != 0 ?
3965 _images->page.width : _images->columns,
3966 _images->page.height != 0 ? _images->page.height :
3967 _images->rows,_images->gravity,&geometry);
3969 /* Compose the two image sequences together */
3970 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
3972 source=DestroyImageList(source);
3978 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3982 if (LocaleCompare("map",option+1) == 0)
3984 CLIWandWarnReplaced("+remap");
3985 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
3988 if (LocaleCompare("morph",option+1) == 0)
3993 if (IfMagickFalse(IsGeometry(arg1)))
3994 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3995 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
3997 if (morph_image == (Image *) NULL)
3999 _images=DestroyImageList(_images);
4000 _images=morph_image;
4003 if (LocaleCompare("mosaic",option+1) == 0)
4005 /* REDIRECTED to use -layers mosaic instead */
4006 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
4009 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4013 if (LocaleCompare("poly",option+1) == 0)
4021 /* convert argument string into an array of doubles */
4022 args = StringToArrayOfDoubles(arg2,&count,_exception);
4023 if (args == (double *)NULL )
4024 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
4025 new_images=PolynomialImage(_images,count >> 1,args,_exception);
4026 args=(double *) RelinquishMagickMemory(args);
4029 if (LocaleCompare("print",option+1) == 0)
4031 (void) FormatLocaleFile(stdout,"%s",arg1);
4034 if (LocaleCompare("process",option+1) == 0)
4036 /* FUTURE: better parsing using ScriptToken() from string ??? */
4044 arguments=StringToArgv(arg1,&number_arguments);
4045 if (arguments == (char **) NULL)
4047 if (strchr(arguments[1],'=') != (char *) NULL)
4068 Support old style syntax, filter="-option arg1".
4070 length=strlen(arg1);
4071 token=(char *) NULL;
4072 if (~length >= (MaxTextExtent-1))
4073 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4075 if (token == (char *) NULL)
4079 token_info=AcquireTokenInfo();
4080 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4081 "\"",'\0',&breaker,&next,"e);
4082 token_info=DestroyTokenInfo(token_info);
4088 argv=(&(arguments[next]));
4089 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4092 token=DestroyString(token);
4095 (void) SubstituteString(&arguments[1],"-","");
4096 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4097 number_arguments-2,(const char **) arguments+2,_exception);
4098 for (j=0; j < number_arguments; j++)
4099 arguments[j]=DestroyString(arguments[j]);
4100 arguments=(char **) RelinquishMagickMemory(arguments);
4103 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4107 if (LocaleCompare("remap",option+1) == 0)
4109 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4112 if (LocaleCompare("reverse",option+1) == 0)
4114 ReverseImageList(&_images);
4117 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4121 if (LocaleCompare("smush",option+1) == 0)
4123 /* FUTURE: this option needs more work to make better */
4127 if (IfMagickFalse(IsGeometry(arg1)))
4128 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4129 offset=(ssize_t) StringToLong(arg1);
4130 new_images=SmushImages(_images,normal_op,offset,_exception);
4133 if (LocaleCompare("subimage",option+1) == 0)
4151 base_image=GetImageFromList(_images,0);
4152 compare_image=GetImageFromList(_images,1);
4154 /* Comparision Metric */
4155 metric=UndefinedMetric;
4156 value=GetImageOption(_image_info,"metric");
4157 if (value != (const char *) NULL)
4158 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4161 new_images=SimilarityImage(base_image,compare_image,metric,
4162 &offset,&similarity,_exception);
4164 if ( new_images != (Image *)NULL ) {
4166 result[MaxTextExtent];
4168 (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity);
4169 (void) SetImageProperty(new_images,"subimage:similarity",result,
4171 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4173 (void) SetImageProperty(new_images,"subimage:x",result,
4175 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4177 (void) SetImageProperty(new_images,"subimage:y",result,
4179 (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld",
4180 (unsigned long) offset.width,(unsigned long) offset.height,
4181 (long) offset.x,(long) offset.y);
4182 (void) SetImageProperty(new_images,"subimage:offset",result,
4187 if (LocaleCompare("swap",option+1) == 0) {
4207 flags=ParseGeometry(arg1,&geometry_info);
4208 if ((flags & RhoValue) != 0)
4209 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4210 index=(ssize_t) geometry_info.rho;
4211 if ((flags & SigmaValue) != 0)
4212 swap_index=(ssize_t) geometry_info.sigma;
4214 p=GetImageFromList(_images,index);
4215 q=GetImageFromList(_images,swap_index);
4216 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4218 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4220 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4223 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
4224 swap=CloneImage(p,0,0,MagickTrue,_exception);
4225 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4226 ReplaceImageInList(&q,swap);
4227 _images=GetFirstImageInList(q);
4230 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4233 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4236 /* clean up percent escape interpreted strings */
4238 arg1=DestroyString((char *)arg1);
4240 arg2=DestroyString((char *)arg2);
4242 /* if new image list generated, replace existing image list */
4243 if (new_images == (Image *) NULL)
4245 _images=DestroyImageList(_images);
4246 _images=GetFirstImageInList(new_images);
4253 #undef _quantize_info
4260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4264 + C L I N o I m a g e O p e r a t i o n s %
4268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4270 % CLINoImageOperator() Applies operations that may not actually need images
4273 % The classic operators of this type is "-read", which actually creates
4274 % images even when no images are present. Or image stack operators, which
4275 % can be applied (push or pop) to an empty image list.
4277 % Note that these operators may involve other special 'option' prefix
4278 % characters other than '-' or '+', namely parenthesis and braces.
4280 % The format of the CLINoImageOption method is:
4282 % void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4283 % const char *arg1, const char *arg2)
4285 % A description of each parameter follows:
4287 % o cli_wand: the main CLI Wand to use. (sometimes not required)
4289 % o option: The special option (with any switch char) to process
4291 % o arg1 & arg2: Argument for option, if required
4292 % Currently arg2 is not used.
4295 WandExport void CLINoImageOperator(MagickCLI *cli_wand,
4296 const char *option, const char *arg1, const char *arg2)
4299 const char /* For percent escape interpretImageProperties() */
4304 #define _image_info (cli_wand->wand.image_info)
4305 #define _images (cli_wand->wand.images)
4306 #define _exception (cli_wand->wand.exception)
4307 #define IfNormalOp (*option=='-')
4308 #define IfPlusOp (*option!='-')
4310 assert(cli_wand != (MagickCLI *) NULL);
4311 assert(cli_wand->signature == WandSignature);
4312 assert(cli_wand->wand.signature == WandSignature);
4313 if (IfMagickTrue(cli_wand->wand.debug))
4314 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4317 Not able to be used as their may not be any images!
4318 Also the only option that may have arguments that can be percent escaped is
4321 #define _process_flags (cli_wand->process_flags)
4322 #define _option_type ((CommandOptionFlags) cli_wand->command->flags)
4323 /* Interpret Percent Escapes in Arguments - using first image */
4326 if ( (((_process_flags & ProcessInterpretProperities) != 0 )
4327 || ((_option_type & AlwaysInterpretArgsFlag) != 0)
4328 ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
4329 /* Interpret Percent escapes in argument 1 */
4330 if (arg1n != (char *) NULL) {
4331 arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
4332 if (arg1 == (char *) NULL) {
4333 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4334 arg1=arg1n; /* use the given argument as is */
4337 if (arg2n != (char *) NULL) {
4338 arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
4339 if (arg2 == (char *) NULL) {
4340 CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
4341 arg2=arg2n; /* use the given argument as is */
4345 #undef _process_flags
4349 do { /* break to exit code */
4351 No-op options (ignore these)
4353 if (LocaleCompare("noop",option+1) == 0) /* zero argument */
4355 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4357 if (LocaleCompare("sans0",option+1) == 0) /* zero argument */
4359 if (LocaleCompare("sans1",option+1) == 0) /* one argument */
4361 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4366 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4367 ( LocaleCompare("--",option) == 0 ) ) {
4368 /* Do Glob filename Expansion for 'arg1' then read all images.
4370 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4371 * (but attaching to the filenames in the generated argument list) any
4372 * [...] read modifiers that may be present.
4374 * For example: It will expand '*.gif[20x20]' into a list such as
4375 * 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4377 * NOTE: In IMv6 this was done globally across all images. This
4378 * meant you could include IM options in '@filename' lists, but you
4379 * could not include comments. Doing it only for image read makes
4380 * it far more secure.
4382 * Note: arguments do not have percent escapes expanded for security
4390 argv = (char **) &arg1;
4392 /* Expand 'glob' expressions in the given filename.
4393 Expansion handles any 'coder:' prefix, or read modifiers attached
4394 to the filename, including them in the resulting expanded list.
4396 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4397 CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
4398 option,GetExceptionMessage(errno));
4400 /* loop over expanded filename list, and read then all in */
4401 for (i=0; i<argc; i++) {
4404 if (IfMagickTrue(_image_info->ping))
4405 new_images=PingImages(_image_info,argv[i],_exception);
4407 new_images=ReadImages(_image_info,argv[i],_exception);
4408 AppendImageToList(&_images, new_images);
4410 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4415 Note: Writing a empty image list is valid in specific cases
4417 if (LocaleCompare("write",option+1) == 0) {
4418 /* Note: arguments do not have percent escapes expanded */
4428 /* Need images, unless a "null:" output coder is used */
4429 if ( cli_wand->wand.images == (Image *) NULL ) {
4430 if ( LocaleCompare(arg1,"null:") == 0 )
4432 CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
4435 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4436 (void) DeleteImageRegistry(key);
4437 write_images=_images;
4439 write_images=CloneImageList(_images,_exception);
4440 write_info=CloneImageInfo(_image_info);
4441 (void) WriteImages(write_info,write_images,arg1,_exception);
4442 write_info=DestroyImageInfo(write_info);
4444 write_images=DestroyImageList(write_images);
4448 Parenthesis and Brace operations
4450 if (LocaleCompare("(",option) == 0) {
4451 /* stack 'push' images */
4459 node=cli_wand->image_list_stack;
4460 for ( ; node != (Stack *)NULL; node=node->next)
4462 if ( size >= MAX_STACK_DEPTH )
4463 CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
4464 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4465 if (node == (Stack *) NULL)
4466 CLIWandExceptionBreak(ResourceLimitFatalError,
4467 "MemoryAllocationFailed",option);
4468 node->data = (void *)cli_wand->wand.images;
4469 cli_wand->wand.images = NewImageList();
4470 node->next = cli_wand->image_list_stack;
4471 cli_wand->image_list_stack = node;
4473 /* handle respect-parenthesis */
4474 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4475 "respect-parenthesis"))))
4476 option="{"; /* fall-thru so as to push image settings too */
4479 /* fall thru to next if */
4481 if (LocaleCompare("{",option) == 0) {
4482 /* stack 'push' of image_info settings */
4490 node=cli_wand->image_info_stack;
4491 for ( ; node != (Stack *)NULL; node=node->next)
4493 if ( size >= MAX_STACK_DEPTH )
4494 CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
4495 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4496 if (node == (Stack *) NULL)
4497 CLIWandExceptionBreak(ResourceLimitFatalError,
4498 "MemoryAllocationFailed",option);
4500 node->data = (void *)cli_wand->wand.image_info;
4501 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4502 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4503 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4505 cli_wand->wand.image_info = (ImageInfo *)node->data;
4506 node = (Stack *)RelinquishMagickMemory(node);
4510 node->next = cli_wand->image_info_stack;
4511 cli_wand->image_info_stack = node;
4515 if (LocaleCompare(")",option) == 0) {
4516 /* pop images from stack */
4520 node = (Stack *)cli_wand->image_list_stack;
4521 if ( node == (Stack *)NULL)
4522 CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
4523 cli_wand->image_list_stack = node->next;
4525 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4526 cli_wand->wand.images= (Image *)node->data;
4527 node = (Stack *)RelinquishMagickMemory(node);
4529 /* handle respect-parenthesis - of the previous 'pushed' settings */
4530 node = cli_wand->image_info_stack;
4531 if ( node != (Stack *)NULL)
4533 if (IfMagickTrue(IsStringTrue(GetImageOption(
4534 cli_wand->wand.image_info,"respect-parenthesis"))))
4535 option="}"; /* fall-thru so as to pop image settings too */
4541 /* fall thru to next if */
4543 if (LocaleCompare("}",option) == 0) {
4544 /* pop image_info settings from stack */
4548 node = (Stack *)cli_wand->image_info_stack;
4549 if ( node == (Stack *)NULL)
4550 CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
4551 cli_wand->image_info_stack = node->next;
4553 (void) DestroyImageInfo(cli_wand->wand.image_info);
4554 cli_wand->wand.image_info = (ImageInfo *)node->data;
4555 node = (Stack *)RelinquishMagickMemory(node);
4557 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4558 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4559 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4563 if (LocaleCompare("set",option+1) == 0)
4565 /* Note: arguments are not percent escapes expanded yet */
4566 /* Some settings are applied to each image in memory in turn.
4567 While others only need to be applied once globally.
4572 if (LocaleNCompare(arg1,"registry:",9) == 0)
4576 (void) DeleteImageRegistry(arg1+9);
4579 value=InterpretImageProperties(_image_info,_images,arg2,_exception);
4580 if (value == (char *) NULL)
4581 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4583 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
4584 value=DestroyString(value);
4587 if (LocaleNCompare(arg1,"option:",7) == 0)
4589 /* delete equivelent artifact from all images (if any) */
4590 MagickResetIterator(&cli_wand->wand);
4591 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4592 (void) DeleteImageArtifact(_images,arg1+7);
4593 MagickResetIterator(&cli_wand->wand);
4594 /* now set/delete the global option as needed */
4596 (void) DeleteImageOption(_image_info,arg1+7);
4599 value=InterpretImageProperties(_image_info,_images,arg2,_exception);
4600 if (value == (char *) NULL)
4601 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4603 (void) SetImageOption(_image_info,arg1+7,value);
4604 value=DestroyString(value);
4607 if ( cli_wand->wand.images == (Image *) NULL )
4608 CLIWandExceptArgBreak(OptionError,"NoImagesFound",option,arg1);
4609 MagickResetIterator(&cli_wand->wand);
4610 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
4616 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4617 (void) DeleteImageArtifact(_images,arg1+9);
4618 else if (LocaleNCompare(arg1,"property:",9) == 0)
4619 (void) DeleteImageProperty(_images,arg1+9);
4621 (void) DeleteImageProperty(_images,arg1);
4625 for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
4627 value=InterpretImageProperties(_image_info,next,arg2,_exception);
4628 if (value == (char *) NULL)
4629 CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
4631 if (LocaleNCompare(arg1,"artifact:",9) == 0)
4632 (void) SetImageArtifact(next,arg1+9,value);
4634 if (LocaleNCompare(arg1,"property:",9) == 0)
4635 (void) SetImageProperty(next,arg1+9,value,_exception);
4637 (void) SetImageProperty(next,arg1,value,_exception);
4638 value=DestroyString(value);
4642 MagickResetIterator(&cli_wand->wand);
4645 if (LocaleCompare("clone",option+1) == 0) {
4651 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4652 CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
4653 if ( cli_wand->image_list_stack == (Stack *)NULL)
4654 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4655 new_images = (Image *)cli_wand->image_list_stack->data;
4656 if (new_images == (Image *) NULL)
4657 CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
4658 new_images=CloneImages(new_images,arg1,_exception);
4659 if (new_images == (Image *) NULL)
4660 CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
4661 AppendImageToList(&_images,new_images);
4665 Informational Operations.
4667 Note that these do not require either a cli-wand or images!
4668 Though currently a cli-wand much be provided regardless.
4670 if (LocaleCompare("version",option+1) == 0)
4672 ListMagickVersion(stdout);
4675 if (LocaleCompare("list",option+1) == 0) {
4677 FUTURE: This 'switch' should really be part of MagickCore
4682 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4684 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4689 case MagickCoderOptions:
4691 (void) ListCoderInfo((FILE *) NULL,_exception);
4694 case MagickColorOptions:
4696 (void) ListColorInfo((FILE *) NULL,_exception);
4699 case MagickConfigureOptions:
4701 (void) ListConfigureInfo((FILE *) NULL,_exception);
4704 case MagickDelegateOptions:
4706 (void) ListDelegateInfo((FILE *) NULL,_exception);
4709 case MagickFontOptions:
4711 (void) ListTypeInfo((FILE *) NULL,_exception);
4714 case MagickFormatOptions:
4715 (void) ListMagickInfo((FILE *) NULL,_exception);
4717 case MagickLocaleOptions:
4718 (void) ListLocaleInfo((FILE *) NULL,_exception);
4720 case MagickLogOptions:
4721 (void) ListLogInfo((FILE *) NULL,_exception);
4723 case MagickMagicOptions:
4724 (void) ListMagicInfo((FILE *) NULL,_exception);
4726 case MagickMimeOptions:
4727 (void) ListMimeInfo((FILE *) NULL,_exception);
4729 case MagickModuleOptions:
4730 (void) ListModuleInfo((FILE *) NULL,_exception);
4732 case MagickPolicyOptions:
4733 (void) ListPolicyInfo((FILE *) NULL,_exception);
4735 case MagickResourceOptions:
4736 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4738 case MagickThresholdOptions:
4739 (void) ListThresholdMaps((FILE *) NULL,_exception);
4742 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4749 CLIWandException(OptionError,"UnrecognizedOption",option);
4751 } while (0); /* break to exit code. */
4754 /* clean up percent escape interpreted strings */
4756 arg1=DestroyString((char *)arg1);
4758 arg2=DestroyString((char *)arg2);
4769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4773 + C L I O p t i o n %
4777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4779 % CLIOption() Processes the given option using the given CLI Magick Wand.
4780 % The option arguments can be variable in number, though at this time no more
4781 % that two is actually used by any option (this may change). Excess options
4782 % are simply ignored.
4784 % If the cli_wand->command pointer is non-null, then it is assumed that the
4785 % option has already been search for up from the CommandOptions[] table in
4786 % "MagickCore/options.c" using GetCommandOptionInfo(). If not set this
4787 % routine will do the lookup instead. The pointer is reset afterward.
4789 % This action allows the caller to lookup and pre-handle any 'special'
4790 % options, (such as implicit reads) before calling this general option
4791 % handler to deal with 'standard' command line options.
4793 % The format of the CLIOption method is:
4795 % void CLIOption(MagickCLI *cli_wand,const char *option, ...)
4797 % A description of each parameter follows:
4799 % o cli_wand: the main CLI Wand to use.
4801 % o option: The special option (with any switch char) to process
4803 % o args: any required arguments for an option (variable number)
4807 % CLIoption(cli_wand,"-read","rose:");
4808 % CLIoption(cli_wand,"-virtual-pixel","transparent");
4809 % CLIoption(cli_wand,"-distort","SRT:","30");
4810 % CLIoption(cli_wand,"-write","rotated_rose.png");
4813 WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
4822 assert(cli_wand != (MagickCLI *) NULL);
4823 assert(cli_wand->signature == WandSignature);
4824 assert(cli_wand->wand.signature == WandSignature);
4825 if (IfMagickTrue(cli_wand->wand.debug))
4826 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4828 do { /* Break Code Block for error handling */
4830 /* get information about option */
4831 if ( cli_wand->command == (const OptionInfo *) NULL )
4832 cli_wand->command = GetCommandOptionInfo(option);
4834 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
4835 option, cli_wand->command->mnemonic );
4837 option_type=(CommandOptionFlags) cli_wand->command->flags;
4839 if ( option_type == UndefinedOptionFlag )
4840 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
4842 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
4844 /* depreciated options */
4845 if ( (option_type & DeprecateOptionFlag) != 0 )
4846 CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
4848 /* options that this module does not handle */
4849 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
4850 CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
4852 /* Get argument strings from VarArgs
4853 How can you determine arguments is enough was supplied? */
4855 count = cli_wand->command->type;
4860 va_start(operands,option);
4864 arg1=(const char *) va_arg(operands, const char *);
4866 arg2=(const char *) va_arg(operands, const char *);
4871 (void) FormatLocaleFile(stderr,
4872 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
4873 option,(long) count,option_type,arg1,arg2);
4878 Call the appropriate option handler
4881 /* FUTURE: this is temporary - get 'settings' to handle distribution of
4882 settings to images attributes,proprieties,artifacts */
4883 if ( cli_wand->wand.images != (Image *)NULL )
4884 SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
4885 cli_wand->wand.exception);
4887 if ( (option_type & SettingOptionFlags) != 0 ) {
4888 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
4889 // FUTURE: Sync Specific Settings into Image Properities (not global)
4892 /* Operators that do not need images - read, write, stack, clone */
4893 if ( (option_type & NoImageOperatorFlag) != 0)
4894 CLINoImageOperator(cli_wand, option, arg1, arg2);
4896 /* FUTURE: The not a setting part below is a temporary hack due to
4897 * some options being both a Setting and a Simple operator.
4898 * Specifically -monitor, -depth, and -colorspace */
4899 if ( cli_wand->wand.images == (Image *)NULL )
4900 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
4901 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
4902 CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
4904 /* Operators work on single images, and needs a loop over the images */
4905 if ( (option_type & SimpleOperatorFlag) != 0)
4906 CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
4908 /* Operators that work on the image list as a whole */
4909 if ( (option_type & ListOperatorFlag) != 0 )
4910 CLIListOperatorImages(cli_wand, option, arg1, arg2);
4912 } while (0); /* end Break code block */
4914 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */