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-2012 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"
64 #define USE_WAND_METHODS 0
65 #define MAX_STACK_DEPTH 32
66 #define UNDEFINED_COMPRESSION_QUALITY 0UL
68 /* FUTURE: why is this default so specific? */
69 #define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
72 Constant declaration. (temporary exports)
75 BackgroundColor[] = "#fff", /* white */
76 BorderColor[] = "#dfdfdf", /* sRGB gray */
77 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
79 /* For Debugging Geometry Input */
80 #define ReportGeometry(flags,info) \
81 (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
82 flags, info.rho, info.sigma, info.xi, info.psi )
85 ** Function to report on the progress of image operations
87 static MagickBooleanType MonitorProgress(const char *text,
88 const MagickOffsetType offset,const MagickSizeType extent,
89 void *wand_unused(cli_wandent_data))
92 message[MaxTextExtent],
103 (void) CopyMagickMemory(tag,text,MaxTextExtent);
105 if (p != (char *) NULL)
107 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
108 locale_message=GetLocaleMessage(message);
109 if (locale_message == message)
111 if (p == (char *) NULL)
112 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
113 locale_message,(long) offset,(unsigned long) extent,(long)
114 (100L*offset/(extent-1)));
116 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
117 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
118 (100L*offset/(extent-1)));
119 if (offset == (MagickOffsetType) (extent-1))
120 (void) FormatLocaleFile(stderr,"\n");
121 (void) fflush(stderr);
126 ** GetImageCache() will read an image into a image cache if not already
127 ** present then return the image that is in the cache under that filename.
129 static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
130 ExceptionInfo *exception)
144 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
145 sans_exception=AcquireExceptionInfo();
146 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
147 sans_exception=DestroyExceptionInfo(sans_exception);
148 if (image != (Image *) NULL)
150 read_info=CloneImageInfo(image_info);
151 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
152 image=ReadImage(read_info,exception);
153 read_info=DestroyImageInfo(read_info);
154 if (image != (Image *) NULL)
155 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
160 SparseColorOption() parse the complex -sparse-color argument into an
161 an array of floating point values than call SparseColorImage().
162 Argument is a complex mix of floating-point pixel coodinates, and color
163 specifications (or direct floating point numbers). The number of floats
164 needed to represent a color varies depending on teh current channel
167 This really should be in MagickCore, so that other API's can make use of it.
169 static Image *SparseColorOption(const Image *image,
170 const SparseColorMethod method,const char *arguments,
171 ExceptionInfo *exception)
174 token[MaxTextExtent];
198 assert(image != (Image *) NULL);
199 assert(image->signature == MagickSignature);
200 if (IfMagickTrue(image->debug))
201 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
202 assert(exception != (ExceptionInfo *) NULL);
203 assert(exception->signature == MagickSignature);
205 Limit channels according to image
206 add up number of values needed per color.
209 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
211 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
213 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
215 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
216 (image->colorspace == CMYKColorspace))
218 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
219 IfMagickTrue(image->matte))
223 Read string, to determine number of arguments needed,
229 GetMagickToken(p,&p,token);
230 if ( token[0] == ',' ) continue;
231 if ( isalpha((int) token[0]) || token[0] == '#' )
232 x += number_colors; /* color argument found */
234 x++; /* floating point argument */
236 /* control points and color values */
237 error = IsMagickTrue( x % (2+number_colors) );
239 if ( IfMagickTrue(error) ) {
240 (void) ThrowMagickException(exception,GetMagickModule(),
241 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
242 "Invalid number of Arguments");
243 return( (Image *)NULL);
246 /* Allocate and fill in the floating point arguments */
247 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
248 sizeof(*sparse_arguments));
249 if (sparse_arguments == (double *) NULL) {
250 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
251 "MemoryAllocationFailed","%s","SparseColorOption");
252 return( (Image *)NULL);
254 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
255 sizeof(*sparse_arguments));
258 while( *p != '\0' && x < number_arguments ) {
260 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
261 if ( token[0] == '\0' ) break;
262 if ( isalpha((int) token[0]) || token[0] == '#' ) {
263 (void) ThrowMagickException(exception,GetMagickModule(),
264 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
265 "Color found, instead of X-coord");
269 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
271 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
272 if ( token[0] == '\0' ) break;
273 if ( isalpha((int) token[0]) || token[0] == '#' ) {
274 (void) ThrowMagickException(exception,GetMagickModule(),
275 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
276 "Color found, instead of Y-coord");
280 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
281 /* color name or function given in string argument */
282 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
283 if ( token[0] == '\0' ) break;
284 if ( isalpha((int) token[0]) || token[0] == '#' ) {
285 /* Color string given */
286 (void) QueryColorCompliance(token,AllCompliance,&color,
288 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
289 sparse_arguments[x++] = QuantumScale*color.red;
290 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
291 sparse_arguments[x++] = QuantumScale*color.green;
292 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
293 sparse_arguments[x++] = QuantumScale*color.blue;
294 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
295 (image->colorspace == CMYKColorspace))
296 sparse_arguments[x++] = QuantumScale*color.black;
297 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
298 IfMagickTrue(image->matte))
299 sparse_arguments[x++] = QuantumScale*color.alpha;
302 /* Colors given as a set of floating point values - experimental */
303 /* NB: token contains the first floating point value to use! */
304 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
306 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
307 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
309 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
310 token[0] = ','; /* used this token - get another */
312 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
314 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
315 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
317 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
318 token[0] = ','; /* used this token - get another */
320 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
322 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
323 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
325 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
326 token[0] = ','; /* used this token - get another */
328 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
329 (image->colorspace == CMYKColorspace))
331 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
332 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
334 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
335 token[0] = ','; /* used this token - get another */
337 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
338 IfMagickTrue(image->matte))
340 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
341 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
343 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
344 token[0] = ','; /* used this token - get another */
348 if ( number_arguments != x && !error ) {
349 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
350 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
351 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
352 return( (Image *)NULL);
355 return( (Image *)NULL);
357 /* Call the Sparse Color Interpolation function with the parsed arguments */
358 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
360 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
361 return( sparse_image );
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 % C L I S e t t i n g O p t i o n I n f o %
373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 % CLISettingOptionInfo() applies a single settings option into a CLI wand
376 % holding the image_info, draw_info, quantize_info structures that will be
377 % used when processing the images.
379 % These options do no require images to be present in the CLI wand for them
380 % to be able to be set, in which case they will generally be applied to image
381 % that are read in later
383 % Options handled by this function are listed in CommandOptions[] of
384 % "option.c" that is one of "SettingOptionFlags" option flags.
386 % The format of the CLISettingOptionInfo method is:
388 % void CLISettingOptionInfo(MagickCLI *cli_wand,
389 % const char *option, const char *arg1, const char *arg2)
391 % A description of each parameter follows:
393 % o cli_wand: structure holding settings to be applied
395 % o option: The option string to be set
397 % o arg1, arg2: optional argument strings to the operation
398 % arg2 is currently only used by "-limit"
401 WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
402 const char *option,const char *arg1, const char *arg2)
405 parse; /* option argument parsing (string to value table lookup) */
407 assert(cli_wand != (MagickCLI *) NULL);
408 assert(cli_wand->signature == WandSignature);
409 assert(cli_wand->wand.signature == WandSignature);
410 if (IfMagickTrue(cli_wand->wand.debug))
411 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
413 #define _image_info (cli_wand->wand.image_info)
414 #define _exception (cli_wand->wand.exception)
415 #define _draw_info (cli_wand->draw_info)
416 #define _quantize_info (cli_wand->quantize_info)
417 #define IfSetOption (*option=='-')
418 #define ArgBoolean IsMagickTrue(IfSetOption)
419 #define ArgBooleanNot IsMagickFalse(IfSetOption)
420 #define ArgBooleanString (IfSetOption?"true":"false")
421 #define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
427 if (LocaleCompare("adjoin",option+1) == 0)
429 _image_info->adjoin = ArgBoolean;
432 if (LocaleCompare("affine",option+1) == 0)
434 CLIWandWarnReplaced("-draw 'affine ...'");
436 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
438 GetAffineMatrix(&_draw_info->affine);
441 if (LocaleCompare("antialias",option+1) == 0)
443 _image_info->antialias =
444 _draw_info->stroke_antialias =
445 _draw_info->text_antialias = ArgBoolean;
448 if (LocaleCompare("attenuate",option+1) == 0)
450 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
451 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
452 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
455 if (LocaleCompare("authenticate",option+1) == 0)
457 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
460 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
464 if (LocaleCompare("background",option+1) == 0)
466 /* FUTURE: both _image_info attribute & ImageOption in use!
467 _image_info only used directly for generating new images.
468 SyncImageSettings() used to set per-image attribute.
470 FUTURE: if _image_info->background_color is not set then
471 we should fall back to per-image background_color
473 At this time -background will 'wipe out' the per-image
476 Better error handling of QueryColorCompliance() needed.
478 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
479 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
480 &_image_info->background_color,_exception);
483 if (LocaleCompare("bias",option+1) == 0)
485 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
486 as it is actually rarely used except in direct convolve operations
487 Usage outside a direct convolve operation is actally non-sensible!
489 SyncImageSettings() used to set per-image attribute.
491 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
492 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
493 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
496 if (LocaleCompare("black-point-compensation",option+1) == 0)
498 /* Used as a image chromaticity setting
499 SyncImageSettings() used to set per-image attribute.
501 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
504 if (LocaleCompare("blue-primary",option+1) == 0)
506 /* Image chromaticity X,Y NB: Y=X if Y not defined
507 Used by many coders including PNG
508 SyncImageSettings() used to set per-image attribute.
510 arg1=ArgOption("0.0");
511 if (IfMagickFalse(IsGeometry(arg1)))
512 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
513 (void) SetImageOption(_image_info,option+1,arg1);
516 if (LocaleCompare("bordercolor",option+1) == 0)
518 /* FUTURE: both _image_info attribute & ImageOption in use!
519 SyncImageSettings() used to set per-image attribute.
520 Better error checking of QueryColorCompliance().
524 (void) SetImageOption(_image_info,option+1,arg1);
525 (void) QueryColorCompliance(arg1,AllCompliance,
526 &_image_info->border_color,_exception);
527 (void) QueryColorCompliance(arg1,AllCompliance,
528 &_draw_info->border_color,_exception);
531 (void) DeleteImageOption(_image_info,option+1);
532 (void) QueryColorCompliance(BorderColor,AllCompliance,
533 &_image_info->border_color,_exception);
534 (void) QueryColorCompliance(BorderColor,AllCompliance,
535 &_draw_info->border_color,_exception);
538 if (LocaleCompare("box",option+1) == 0)
540 CLIWandWarnReplaced("-undercolor");
541 CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
544 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
548 if (LocaleCompare("cache",option+1) == 0)
553 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
554 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
555 limit=MagickResourceInfinity;
556 if (LocaleCompare("unlimited",arg1) != 0)
557 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
558 (void) SetMagickResourceLimit(MemoryResource,limit);
559 (void) SetMagickResourceLimit(MapResource,2*limit);
562 if (LocaleCompare("caption",option+1) == 0)
564 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
567 if (LocaleCompare("channel",option+1) == 0)
569 arg1=ArgOption("default");
570 parse=ParseChannelOption(arg1);
572 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
574 _image_info->channel=(ChannelType) parse;
575 (void) SetImageOption(_image_info,option+1,arg1);
578 if (LocaleCompare("colorspace",option+1) == 0)
580 /* Setting used for new images via AquireImage()
581 But also used as a SimpleImageOperator
582 Undefined colorspace means don't modify images on
583 read or as a operation */
584 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
585 ArgOption("undefined"));
587 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
589 _image_info->colorspace=(ColorspaceType) parse;
592 if (LocaleCompare("comment",option+1) == 0)
594 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
597 if (LocaleCompare("compose",option+1) == 0)
599 /* FUTURE: _image_info should be used,
600 SyncImageSettings() used to set per-image attribute. - REMOVE
602 This setting should NOT be used to set image 'compose'
603 "-layer" operators shoud use _image_info if defined otherwise
604 they should use a per-image compose setting.
606 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
607 ArgOption("undefined"));
609 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
611 _image_info->compose=(CompositeOperator) parse;
612 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
615 if (LocaleCompare("compress",option+1) == 0)
617 /* FUTURE: What should be used? _image_info or ImageOption ???
618 The former is more efficent, but Crisy prefers the latter!
619 SyncImageSettings() used to set per-image attribute.
621 The coders appears to use _image_info, not Image_Option
622 however the image attribute (for save) is set from the
625 Note that "undefined" is a different setting to "none".
627 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
628 ArgOption("undefined"));
630 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
632 _image_info->compression=(CompressionType) parse;
633 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
636 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
640 if (LocaleCompare("debug",option+1) == 0)
642 /* SyncImageSettings() used to set per-image attribute. */
643 arg1=ArgOption("none");
644 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
646 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
648 (void) SetLogEventMask(arg1);
649 _image_info->debug=IsEventLogging(); /* extract logging*/
650 cli_wand->wand.debug=IsEventLogging();
653 if (LocaleCompare("define",option+1) == 0)
655 if (LocaleNCompare(arg1,"registry:",9) == 0)
658 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
660 (void) DeleteImageRegistry(arg1+9);
663 /* DefineImageOption() equals SetImageOption() but with '=' */
665 (void) DefineImageOption(_image_info,arg1);
666 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
667 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
670 if (LocaleCompare("delay",option+1) == 0)
672 /* Only used for new images via AcquireImage()
673 FUTURE: Option should also be used for "-morph" (color morphing)
676 if (IfMagickFalse(IsGeometry(arg1)))
677 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
678 (void) SetImageOption(_image_info,option+1,arg1);
681 if (LocaleCompare("density",option+1) == 0)
683 /* FUTURE: strings used in _image_info attr and _draw_info!
684 Basically as density can be in a XxY form!
686 SyncImageSettings() used to set per-image attribute.
688 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
689 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
690 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
691 (void) CloneString(&_image_info->density,ArgOption(NULL));
692 (void) CloneString(&_draw_info->density,_image_info->density);
695 if (LocaleCompare("depth",option+1) == 0)
697 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
698 SyncImageSettings() used to set per-image attribute.
700 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
701 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
702 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
703 :MAGICKCORE_QUANTUM_DEPTH;
706 if (LocaleCompare("direction",option+1) == 0)
708 /* Image Option is only used to set _draw_info */
709 arg1=ArgOption("undefined");
710 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
712 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
714 _draw_info->direction=(DirectionType) parse;
715 (void) SetImageOption(_image_info,option+1,arg1);
718 if (LocaleCompare("display",option+1) == 0)
720 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
721 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
724 if (LocaleCompare("dispose",option+1) == 0)
726 /* only used in setting new images */
727 arg1=ArgOption("undefined");
728 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
730 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
732 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
735 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
737 /* FUTURE: this is only used by CompareImages() which is used
738 only by the "compare" CLI program at this time. */
739 arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
740 if (IfMagickFalse(IsGeometry(arg1)))
741 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
742 (void) SetImageOption(_image_info,option+1,arg1);
745 if (LocaleCompare("dither",option+1) == 0)
747 /* _image_info attr (on/off), _quantize_info attr (on/off)
748 but also ImageInfo and _quantize_info method!
749 FUTURE: merge the duality of the dithering options
751 _image_info->dither = _quantize_info->dither = ArgBoolean;
752 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
753 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
754 MagickDitherOptions,MagickFalse,ArgOption("none"));
755 if (_quantize_info->dither_method == NoDitherMethod)
756 _image_info->dither = _quantize_info->dither = MagickFalse;
759 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
763 if (LocaleCompare("encoding",option+1) == 0)
765 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
766 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
769 if (LocaleCompare("endian",option+1) == 0)
771 /* Both _image_info attr and ImageInfo */
772 arg1 = ArgOption("undefined");
773 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
775 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
777 /* FUTURE: check alloc/free of endian string! - remove? */
778 _image_info->endian=(EndianType) (*arg1);
779 (void) SetImageOption(_image_info,option+1,arg1);
782 if (LocaleCompare("extract",option+1) == 0)
784 (void) CloneString(&_image_info->extract,ArgOption(NULL));
787 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
791 if (LocaleCompare("family",option+1) == 0)
793 (void) CloneString(&_draw_info->family,ArgOption(NULL));
796 if (LocaleCompare("fill",option+1) == 0)
798 /* Set "fill" OR "fill-pattern" in _draw_info
799 The original fill color is preserved if a fill-pattern is given.
800 That way it does not effect other operations that directly using
801 the fill color and, can be retored using "+tile".
812 arg1 = ArgOption("none"); /* +fill turns it off! */
813 (void) SetImageOption(_image_info,option+1,arg1);
814 if (_draw_info->fill_pattern != (Image *) NULL)
815 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
817 /* is it a color or a image? -- ignore exceptions */
818 sans=AcquireExceptionInfo();
819 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
820 sans=DestroyExceptionInfo(sans);
822 if (IfMagickFalse(status))
823 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
825 _draw_info->fill=color;
828 if (LocaleCompare("filter",option+1) == 0)
830 /* SyncImageSettings() used to set per-image attribute. */
831 arg1 = ArgOption("undefined");
832 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
834 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
836 (void) SetImageOption(_image_info,option+1,arg1);
839 if (LocaleCompare("font",option+1) == 0)
841 (void) CloneString(&_draw_info->font,ArgOption(NULL));
842 (void) CloneString(&_image_info->font,_draw_info->font);
845 if (LocaleCompare("format",option+1) == 0)
847 /* FUTURE: why the ping test, you could set ping after this! */
852 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
853 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
854 _image_info->ping=MagickFalse;
856 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
859 if (LocaleCompare("fuzz",option+1) == 0)
861 /* Option used to set image fuzz! unless blank canvas (from color)
862 Image attribute used for color compare operations
863 SyncImageSettings() used to set per-image attribute.
865 FUTURE: Can't find anything else using _image_info->fuzz directly!
866 remove direct sttribute from image_info
869 if (IfMagickFalse(IsGeometry(arg1)))
870 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
871 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
873 (void) SetImageOption(_image_info,option+1,arg1);
876 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
880 if (LocaleCompare("gravity",option+1) == 0)
882 /* SyncImageSettings() used to set per-image attribute. */
883 arg1 = ArgOption("none");
884 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
886 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
888 _draw_info->gravity=(GravityType) parse;
889 (void) SetImageOption(_image_info,option+1,arg1);
892 if (LocaleCompare("green-primary",option+1) == 0)
894 /* Image chromaticity X,Y NB: Y=X if Y not defined
895 SyncImageSettings() used to set per-image attribute.
896 Used directly by many coders
898 arg1=ArgOption("0.0");
899 if (IfMagickFalse(IsGeometry(arg1)))
900 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
901 (void) SetImageOption(_image_info,option+1,arg1);
904 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
908 if (LocaleCompare("highlight-color",option+1) == 0)
910 /* FUTURE: this is only used by CompareImages() which is used
911 only by the "compare" CLI program at this time. */
912 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
915 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
919 if (LocaleCompare("intent",option+1) == 0)
921 /* Only used by coders: MIFF, MPC, BMP, PNG
922 and for image profile call to AcquireTransformThreadSet()
923 SyncImageSettings() used to set per-image attribute.
925 arg1 = ArgOption("indefined");
926 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
928 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
930 (void) SetImageOption(_image_info,option+1,arg1);
933 if (LocaleCompare("interlace",option+1) == 0)
935 /* _image_info is directly used by coders (so why an image setting?)
936 SyncImageSettings() used to set per-image attribute.
938 arg1 = ArgOption("undefined");
939 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
941 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
943 _image_info->interlace=(InterlaceType) parse;
944 (void) SetImageOption(_image_info,option+1,arg1);
947 if (LocaleCompare("interline-spacing",option+1) == 0)
949 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
950 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
951 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
952 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
956 if (LocaleCompare("interpolate",option+1) == 0)
958 /* SyncImageSettings() used to set per-image attribute. */
959 arg1 = ArgOption("undefined");
960 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
962 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
964 (void) SetImageOption(_image_info,option+1,arg1);
967 if (LocaleCompare("interword-spacing",option+1) == 0)
969 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
970 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
971 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
972 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
975 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
979 if (LocaleCompare("kerning",option+1) == 0)
981 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
982 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
983 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
984 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
987 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
991 if (LocaleCompare("label",option+1) == 0)
993 /* only used for new images - not in SyncImageOptions() */
994 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
997 if (LocaleCompare("limit",option+1) == 0)
1002 limit=MagickResourceInfinity;
1003 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
1005 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
1007 if (LocaleCompare("unlimited",arg2) != 0)
1008 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
1009 (void) SetMagickResourceLimit((ResourceType)parse,limit);
1012 if (LocaleCompare("log",option+1) == 0)
1015 if ((strchr(arg1,'%') == (char *) NULL))
1016 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1017 (void) SetLogFormat(arg1);
1021 if (LocaleCompare("lowlight-color",option+1) == 0)
1023 /* FUTURE: this is only used by CompareImages() which is used
1024 only by the "compare" CLI program at this time. */
1025 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1028 if (LocaleCompare("loop",option+1) == 0)
1030 /* SyncImageSettings() used to set per-image attribute. */
1031 arg1=ArgOption("0");
1032 if (IfMagickFalse(IsGeometry(arg1)))
1033 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1034 (void) SetImageOption(_image_info,option+1,arg1);
1037 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1041 if (LocaleCompare("mattecolor",option+1) == 0)
1043 /* SyncImageSettings() used to set per-image attribute. */
1044 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1045 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
1046 &_image_info->matte_color,_exception);
1049 if (LocaleCompare("metric",option+1) == 0)
1051 /* FUTURE: this is only used by CompareImages() which is used
1052 only by the "compare" CLI program at this time. */
1053 parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
1055 CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
1057 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1060 if (LocaleCompare("monitor",option+1) == 0)
1062 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
1063 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
1066 if (LocaleCompare("monochrome",option+1) == 0)
1068 /* Setting (used by some input coders!) -- why?
1069 Warning: This is also Special '-type' SimpleOperator
1071 _image_info->monochrome= ArgBoolean;
1074 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1078 if (LocaleCompare("orient",option+1) == 0)
1080 /* Is not used when defining for new images.
1081 This makes it more of a 'operation' than a setting
1082 FUTURE: make set meta-data operator instead.
1083 SyncImageSettings() used to set per-image attribute.
1085 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1086 ArgOption("undefined"));
1088 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1090 _image_info->orientation=(OrientationType)parse;
1091 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1094 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1098 if (LocaleCompare("page",option+1) == 0)
1100 /* Only used for new images and image generators.
1101 SyncImageSettings() used to set per-image attribute. ?????
1102 That last is WRONG!!!!
1103 FUTURE: adjust named 'page' sizes according density
1107 page[MaxTextExtent];
1120 (void) DeleteImageOption(_image_info,option+1);
1121 (void) CloneString(&_image_info->page,(char *) NULL);
1124 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1125 image_option=GetImageOption(_image_info,"page");
1126 if (image_option != (const char *) NULL)
1127 flags=ParseAbsoluteGeometry(image_option,&geometry);
1128 canonical_page=GetPageGeometry(arg1);
1129 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1130 canonical_page=DestroyString(canonical_page);
1131 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1132 (unsigned long) geometry.width,(unsigned long) geometry.height);
1133 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1134 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1135 (unsigned long) geometry.width,(unsigned long) geometry.height,
1136 (long) geometry.x,(long) geometry.y);
1137 (void) SetImageOption(_image_info,option+1,page);
1138 (void) CloneString(&_image_info->page,page);
1141 if (LocaleCompare("ping",option+1) == 0)
1143 _image_info->ping = ArgBoolean;
1146 if (LocaleCompare("pointsize",option+1) == 0)
1149 if (IfMagickFalse(IsGeometry(arg1)))
1150 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1151 _image_info->pointsize =
1152 _draw_info->pointsize =
1153 StringToDouble(arg1,(char **) NULL);
1156 _image_info->pointsize=0.0; /* unset pointsize */
1157 _draw_info->pointsize=12.0;
1161 if (LocaleCompare("precision",option+1) == 0)
1163 arg1=ArgOption("-1");
1164 if (IfMagickFalse(IsGeometry(arg1)))
1165 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1166 (void) SetMagickPrecision(StringToInteger(arg1));
1169 /* FUTURE: Only the 'preview' coder appears to use this
1170 * DEPRECIATE the coder? Leaving only the 'preview' operator.
1171 if (LocaleCompare("preview",option+1) == 0)
1173 _image_info->preview_type=UndefinedPreview;
1175 _image_info->preview_type=(PreviewType) ParseCommandOption(
1176 MagickPreviewOptions,MagickFalse,arg1);
1180 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1184 if (LocaleCompare("quality",option+1) == 0)
1186 if (IfMagickFalse(IsGeometry(arg1)))
1187 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1188 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1189 : UNDEFINED_COMPRESSION_QUALITY;
1190 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1193 if (LocaleCompare("quantize",option+1) == 0)
1195 /* Just a set direct in _quantize_info */
1196 arg1=ArgOption("undefined");
1197 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1199 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1201 _quantize_info->colorspace=(ColorspaceType)parse;
1204 if (LocaleCompare("quiet",option+1) == 0)
1206 /* FUTURE: if two -quiet is performed you can not do +quiet!
1207 This needs to be checked over thoughly.
1209 static WarningHandler
1210 warning_handler = (WarningHandler) NULL;
1213 tmp = SetWarningHandler((WarningHandler) NULL);
1215 if ( tmp != (WarningHandler) NULL)
1216 warning_handler = tmp; /* remember the old handler */
1217 if (!IfSetOption) /* set the old handler */
1218 warning_handler=SetWarningHandler(warning_handler);
1221 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1225 if (LocaleCompare("red-primary",option+1) == 0)
1227 /* Image chromaticity X,Y NB: Y=X if Y not defined
1229 SyncImageSettings() used to set per-image attribute.
1231 arg1=ArgOption("0.0");
1232 if (IfMagickFalse(IsGeometry(arg1)))
1233 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1234 (void) SetImageOption(_image_info,option+1,arg1);
1237 if (LocaleCompare("regard-warnings",option+1) == 0)
1238 /* FUTURE: to be replaced by a 'fatal-level' type setting */
1240 if (LocaleCompare("render",option+1) == 0)
1242 /* _draw_info only setting */
1243 _draw_info->render= ArgBooleanNot;
1246 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1248 /* link image and setting stacks - option is itself saved on stack! */
1249 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1252 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1256 if (LocaleCompare("sampling-factor",option+1) == 0)
1258 /* FUTURE: should be converted to jpeg:sampling_factor */
1259 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1260 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1261 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
1264 if (LocaleCompare("scene",option+1) == 0)
1266 /* SyncImageSettings() used to set this as a per-image attribute.
1269 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1270 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1271 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1272 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
1275 if (LocaleCompare("seed",option+1) == 0)
1277 if (IfMagickFalse(IsGeometry(arg1)))
1278 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1280 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
1281 : (size_t) time((time_t *) NULL) );
1284 if (LocaleCompare("size",option+1) == 0)
1286 /* FUTURE: string in _image_info -- convert to Option ???
1287 Look at the special handling for "size" in SetImageOption()
1289 (void) CloneString(&_image_info->size,ArgOption(NULL));
1292 if (LocaleCompare("stretch",option+1) == 0)
1294 arg1=ArgOption("undefined");
1295 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1297 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1299 _draw_info->stretch=(StretchType) parse;
1302 if (LocaleCompare("stroke",option+1) == 0)
1304 /* set stroke color OR stroke-pattern
1305 UPDATE: ensure stroke color is not destroyed is a pattern
1306 is given. Just in case the color is also used for other purposes.
1317 arg1 = ArgOption("none"); /* +fill turns it off! */
1318 (void) SetImageOption(_image_info,option+1,arg1);
1319 if (_draw_info->stroke_pattern != (Image *) NULL)
1320 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
1322 /* is it a color or a image? -- ignore exceptions */
1323 sans=AcquireExceptionInfo();
1324 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
1325 sans=DestroyExceptionInfo(sans);
1327 if (IfMagickFalse(status))
1328 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
1330 _draw_info->stroke=color;
1333 if (LocaleCompare("strokewidth",option+1) == 0)
1335 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1336 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1337 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1338 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1342 if (LocaleCompare("style",option+1) == 0)
1344 arg1=ArgOption("undefined");
1345 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1347 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1349 _draw_info->style=(StyleType) parse;
1353 if (LocaleCompare("subimage-search",option+1) == 0)
1355 /* FUTURE: this is only used by CompareImages() which is used
1356 only by the "compare" CLI program at this time. */
1357 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1361 if (LocaleCompare("synchronize",option+1) == 0)
1363 /* FUTURE: syncronize to storage - but what does that mean? */
1364 _image_info->synchronize = ArgBoolean;
1367 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1371 if (LocaleCompare("taint",option+1) == 0)
1373 /* SyncImageSettings() used to set per-image attribute. */
1374 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1377 if (LocaleCompare("texture",option+1) == 0)
1379 /* FUTURE: move _image_info string to option splay-tree
1380 Other than "montage" what uses "texture" ????
1382 (void) CloneString(&_image_info->texture,ArgOption(NULL));
1385 if (LocaleCompare("tile",option+1) == 0)
1387 _draw_info->fill_pattern=IfSetOption
1388 ?GetImageCache(_image_info,arg1,_exception)
1389 :DestroyImage(_draw_info->fill_pattern);
1392 if (LocaleCompare("tile-offset",option+1) == 0)
1394 /* SyncImageSettings() used to set per-image attribute. ??? */
1395 arg1=ArgOption("0");
1396 if (IfMagickFalse(IsGeometry(arg1)))
1397 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1398 (void) SetImageOption(_image_info,option+1,arg1);
1401 if (LocaleCompare("transparent-color",option+1) == 0)
1403 /* FUTURE: both _image_info attribute & ImageOption in use!
1404 _image_info only used for generating new images.
1405 SyncImageSettings() used to set per-image attribute.
1407 Note that +transparent-color, means fall-back to image
1408 attribute so ImageOption is deleted, not set to a default.
1410 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1411 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1412 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1413 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1414 &_image_info->transparent_color,_exception);
1417 if (LocaleCompare("treedepth",option+1) == 0)
1419 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1420 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1423 if (LocaleCompare("type",option+1) == 0)
1425 /* SyncImageSettings() used to set per-image attribute. */
1426 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1427 ArgOption("undefined"));
1429 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1431 _image_info->type=(ImageType) parse;
1432 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1435 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1439 if (LocaleCompare("undercolor",option+1) == 0)
1441 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1442 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1443 &_draw_info->undercolor,_exception);
1446 if (LocaleCompare("units",option+1) == 0)
1448 /* SyncImageSettings() used to set per-image attribute.
1449 Should this effect _draw_info X and Y resolution?
1450 FUTURE: this probably should be part of the density setting
1452 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1453 ArgOption("undefined"));
1455 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1457 _image_info->units=(ResolutionType) parse;
1458 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1461 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1465 if (LocaleCompare("verbose",option+1) == 0)
1467 /* FUTURE: Remember all options become image artifacts
1468 _image_info->verbose is only used by coders.
1470 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1471 _image_info->verbose= ArgBoolean;
1472 _image_info->ping=MagickFalse; /* verbose can't be a ping */
1475 if (LocaleCompare("view",option+1) == 0)
1477 /* FUTURE: Convert from _image_info to ImageOption
1478 Only used by coder FPX
1479 And it only tests existance, not its content!
1481 (void) CloneString(&_image_info->view,ArgOption(NULL));
1484 if (LocaleCompare("virtual-pixel",option+1) == 0)
1486 /* SyncImageSettings() used to set per-image attribute.
1487 This is VERY deep in the image caching structure.
1489 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1490 ArgOption("undefined"));
1492 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1494 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1497 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1501 if (LocaleCompare("weight",option+1) == 0)
1503 /* Just what does using a font 'weight' do ???
1504 There is no "-list weight" output (reference manual says there is)
1506 arg1=ArgOption("all");
1507 _draw_info->weight=StringToUnsignedLong(arg1);
1508 if (LocaleCompare(arg1,"all") == 0)
1509 _draw_info->weight=0;
1510 if (LocaleCompare(arg1,"bold") == 0)
1511 _draw_info->weight=700;
1512 if (LocaleCompare(arg1,"bolder") == 0)
1513 if (_draw_info->weight <= 800)
1514 _draw_info->weight+=100;
1515 if (LocaleCompare(arg1,"lighter") == 0)
1516 if (_draw_info->weight >= 100)
1517 _draw_info->weight-=100;
1518 if (LocaleCompare(arg1,"normal") == 0)
1519 _draw_info->weight=400;
1522 if (LocaleCompare("white-point",option+1) == 0)
1524 /* Used as a image chromaticity setting
1525 SyncImageSettings() used to set per-image attribute.
1527 arg1=ArgOption("0.0");
1528 if (IfMagickFalse(IsGeometry(arg1)))
1529 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1530 (void) SetImageOption(_image_info,option+1,arg1);
1533 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1536 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1542 #undef _quantize_info
1545 #undef ArgBooleanNot
1546 #undef ArgBooleanString
1553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1557 + C L I S i m p l e O p e r a t o r I m a g e s %
1561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1563 % WandSimpleOperatorImages() applys one simple image operation given to all
1564 % the images in the CLI wand, with the settings that was previously saved in
1567 % It is assumed that any per-image settings are up-to-date with respect to
1568 % extra settings that were already saved in the wand.
1570 % The format of the WandSimpleOperatorImage method is:
1572 % void CLISimpleOperatorImages(MagickCLI *cli_wand,
1573 % const char *option, const char *arg1, const char *arg2)
1575 % A description of each parameter follows:
1577 % o cli_wand: structure holding settings and images to be operated on
1579 % o option: The option string for the operation
1581 % o arg1, arg2: optional argument strings to the operation
1586 Internal subrountine to apply one simple image operation to the current
1587 image pointed to by the CLI wand.
1589 The image in the list may be modified in three different ways...
1590 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1591 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1592 * one image replace by a list of images (-separate and -crop only!)
1594 In each case the result replaces the single original image in the list, as
1595 well as the pointer to the modified image (last image added if replaced by a
1596 list of images) is returned.
1598 As the image pointed to may be replaced, the first image in the list may
1599 also change. GetFirstImageInList() should be used by caller if they wish
1600 return the Image pointer to the first image in list.
1602 static void CLISimpleOperatorImage(MagickCLI *cli_wand,
1603 const char *option, const char *arg1, const char *arg2)
1620 #define _image_info (cli_wand->wand.image_info)
1621 #define _image (cli_wand->wand.images)
1622 #define _exception (cli_wand->wand.exception)
1623 #define _draw_info (cli_wand->draw_info)
1624 #define _quantize_info (cli_wand->quantize_info)
1625 #define IfNormalOp (*option=='-')
1626 #define IfPlusOp (*option!='-')
1627 #define normal_op IsMagickTrue(IfNormalOp)
1628 #define plus_alt_op IsMagickFalse(IfNormalOp)
1630 assert(cli_wand != (MagickCLI *) NULL);
1631 assert(cli_wand->signature == WandSignature);
1632 assert(cli_wand->wand.signature == WandSignature);
1633 assert(_image != (Image *) NULL); /* an image must be present */
1634 if (IfMagickTrue(cli_wand->wand.debug))
1635 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
1637 SetGeometryInfo(&geometry_info);
1639 new_image = (Image *)NULL; /* the replacement image, if not null at end */
1641 /* FUTURE: We may need somthing a little more optimized than this!
1642 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1644 switch (*(option+1))
1648 if (LocaleCompare("adaptive-blur",option+1) == 0)
1650 flags=ParseGeometry(arg1,&geometry_info);
1651 if ((flags & (RhoValue|SigmaValue)) == 0)
1652 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1653 if ((flags & SigmaValue) == 0)
1654 geometry_info.sigma=1.0;
1655 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1656 geometry_info.sigma,_exception);
1659 if (LocaleCompare("adaptive-resize",option+1) == 0)
1661 /* FUTURE: Roll into a resize special operator */
1662 if (IfMagickFalse(IsGeometry(arg1)))
1663 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1664 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1665 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1669 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
1671 flags=ParseGeometry(arg1,&geometry_info);
1672 if ((flags & (RhoValue|SigmaValue)) == 0)
1673 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1674 if ((flags & SigmaValue) == 0)
1675 geometry_info.sigma=1.0;
1676 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1677 geometry_info.sigma,_exception);
1680 if (LocaleCompare("alpha",option+1) == 0)
1682 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1684 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1686 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1690 if (LocaleCompare("annotate",option+1) == 0)
1694 geometry[MaxTextExtent];
1696 SetGeometryInfo(&geometry_info);
1697 flags=ParseGeometry(arg1,&geometry_info);
1698 if ((flags & RhoValue) == 0)
1699 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1700 if ((flags & SigmaValue) == 0)
1701 geometry_info.sigma=geometry_info.rho;
1702 text=InterpretImageProperties(_image_info,_image,arg2,
1704 if (text == (char *) NULL)
1706 (void) CloneString(&_draw_info->text,text);
1707 text=DestroyString(text);
1708 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1709 geometry_info.xi,geometry_info.psi);
1710 (void) CloneString(&_draw_info->geometry,geometry);
1711 _draw_info->affine.sx=cos(DegreesToRadians(
1712 fmod(geometry_info.rho,360.0)));
1713 _draw_info->affine.rx=sin(DegreesToRadians(
1714 fmod(geometry_info.rho,360.0)));
1715 _draw_info->affine.ry=(-sin(DegreesToRadians(
1716 fmod(geometry_info.sigma,360.0))));
1717 _draw_info->affine.sy=cos(DegreesToRadians(
1718 fmod(geometry_info.sigma,360.0)));
1719 (void) AnnotateImage(_image,_draw_info,_exception);
1720 GetAffineMatrix(&_draw_info->affine);
1723 if (LocaleCompare("auto-gamma",option+1) == 0)
1725 (void) AutoGammaImage(_image,_exception);
1728 if (LocaleCompare("auto-level",option+1) == 0)
1730 (void) AutoLevelImage(_image,_exception);
1733 if (LocaleCompare("auto-orient",option+1) == 0)
1735 /* This should probably be a MagickCore function */
1736 switch (_image->orientation)
1738 case TopRightOrientation:
1740 new_image=FlopImage(_image,_exception);
1743 case BottomRightOrientation:
1745 new_image=RotateImage(_image,180.0,_exception);
1748 case BottomLeftOrientation:
1750 new_image=FlipImage(_image,_exception);
1753 case LeftTopOrientation:
1755 new_image=TransposeImage(_image,_exception);
1758 case RightTopOrientation:
1760 new_image=RotateImage(_image,90.0,_exception);
1763 case RightBottomOrientation:
1765 new_image=TransverseImage(_image,_exception);
1768 case LeftBottomOrientation:
1770 new_image=RotateImage(_image,270.0,_exception);
1776 if (new_image != (Image *) NULL)
1777 new_image->orientation=TopLeftOrientation;
1780 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1784 if (LocaleCompare("black-threshold",option+1) == 0)
1786 if (IfMagickFalse(IsGeometry(arg1)))
1787 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1788 (void) BlackThresholdImage(_image,arg1,_exception);
1791 if (LocaleCompare("blue-shift",option+1) == 0)
1793 geometry_info.rho=1.5;
1795 flags=ParseGeometry(arg1,&geometry_info);
1796 if ((flags & RhoValue) == 0)
1797 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1799 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
1802 if (LocaleCompare("blur",option+1) == 0)
1804 flags=ParseGeometry(arg1,&geometry_info);
1805 if ((flags & (RhoValue|SigmaValue)) == 0)
1806 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1807 if ((flags & SigmaValue) == 0)
1808 geometry_info.sigma=1.0;
1809 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1813 if (LocaleCompare("border",option+1) == 0)
1821 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
1822 if ((flags & RhoValue) == 0)
1823 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1824 if ((flags & SigmaValue) == 0)
1825 geometry.height=geometry.width;
1827 value=GetImageOption(_image_info,"compose");
1828 if (value != (const char *) NULL)
1829 compose=(CompositeOperator) ParseCommandOption(
1830 MagickComposeOptions,MagickFalse,value);
1832 compose=OverCompositeOp; /* use Over not _image->compose */
1834 new_image=BorderImage(_image,&geometry,compose,_exception);
1837 if (LocaleCompare("brightness-contrast",option+1) == 0)
1849 flags=ParseGeometry(arg1,&geometry_info);
1850 if ((flags & RhoValue) == 0)
1851 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1852 brightness=geometry_info.rho;
1854 if ((flags & SigmaValue) != 0)
1855 contrast=geometry_info.sigma;
1856 (void) BrightnessContrastImage(_image,brightness,contrast,
1860 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1864 if (LocaleCompare("cdl",option+1) == 0)
1867 *color_correction_collection;
1870 Color correct with a color decision list.
1872 color_correction_collection=FileToString(arg1,~0,_exception);
1873 if (color_correction_collection == (char *) NULL)
1875 (void) ColorDecisionListImage(_image,color_correction_collection,
1879 if (LocaleCompare("charcoal",option+1) == 0)
1881 flags=ParseGeometry(arg1,&geometry_info);
1882 if ((flags & (RhoValue|SigmaValue)) == 0)
1883 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1884 if ((flags & SigmaValue) == 0)
1885 geometry_info.sigma=1.0;
1886 if ((flags & XiValue) == 0)
1887 geometry_info.xi=1.0;
1888 new_image=CharcoalImage(_image,geometry_info.rho,
1889 geometry_info.sigma,_exception);
1892 if (LocaleCompare("chop",option+1) == 0)
1894 if (IfMagickFalse(IsGeometry(arg1)))
1895 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1896 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1897 new_image=ChopImage(_image,&geometry,_exception);
1900 if (LocaleCompare("clamp",option+1) == 0)
1902 (void) ClampImage(_image,_exception);
1905 if (LocaleCompare("clip",option+1) == 0)
1908 (void) ClipImage(_image,_exception);
1909 else /* "+mask" remove the write mask */
1910 (void) SetImageMask(_image,(Image *) NULL,_exception);
1913 if (LocaleCompare("clip-mask",option+1) == 0)
1931 /* "+clip-mask" Remove the write mask */
1932 (void) SetImageMask(_image,(Image *) NULL,_exception);
1935 mask_image=GetImageCache(_image_info,arg1,_exception);
1936 if (mask_image == (Image *) NULL)
1938 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
1940 /* Create a write mask from cli_wand mask image */
1941 /* FUTURE: use Alpha operations instead and create a Grey Image */
1942 mask_view=AcquireAuthenticCacheView(mask_image,_exception);
1943 for (y=0; y < (ssize_t) mask_image->rows; y++)
1945 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1947 if (q == (Quantum *) NULL)
1949 for (x=0; x < (ssize_t) mask_image->columns; x++)
1951 if (IfMagickFalse(mask_image->matte))
1952 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1953 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1954 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1955 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1956 q+=GetPixelChannels(mask_image);
1958 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
1961 /* clean up and set the write mask */
1962 mask_view=DestroyCacheView(mask_view);
1963 mask_image->matte=MagickTrue;
1964 (void) SetImageMask(_image,mask_image,_exception);
1965 mask_image=DestroyImage(mask_image);
1968 if (LocaleCompare("clip-path",option+1) == 0)
1970 (void) ClipImagePath(_image,arg1,normal_op,_exception);
1973 if (LocaleCompare("colorize",option+1) == 0)
1975 if (IfMagickFalse(IsGeometry(arg1)))
1976 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1977 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
1980 if (LocaleCompare("color-matrix",option+1) == 0)
1985 kernel=AcquireKernelInfo(arg1);
1986 if (kernel == (KernelInfo *) NULL)
1987 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1988 new_image=ColorMatrixImage(_image,kernel,_exception);
1989 kernel=DestroyKernelInfo(kernel);
1992 if (LocaleCompare("colors",option+1) == 0)
1994 /* Reduce the number of colors in the image.
1995 FUTURE: also provide 'plus version with image 'color counts'
1997 _quantize_info->number_colors=StringToUnsignedLong(arg1);
1998 if (_quantize_info->number_colors == 0)
1999 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2000 if ((_image->storage_class == DirectClass) ||
2001 _image->colors > _quantize_info->number_colors)
2002 (void) QuantizeImage(_quantize_info,_image,_exception);
2004 (void) CompressImageColormap(_image,_exception);
2007 if (LocaleCompare("colorspace",option+1) == 0)
2009 /* WARNING: this is both a image_info setting (already done)
2010 and a operator to change image colorspace.
2012 FUTURE: default colorspace should be sRGB!
2013 Unless some type of 'linear colorspace' mode is set.
2015 Note that +colorspace sets "undefined" or no effect on
2016 new images, but forces images already in memory back to RGB!
2017 That seems to be a little strange!
2019 (void) TransformImageColorspace(_image,
2020 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2024 if (LocaleCompare("contrast",option+1) == 0)
2026 CLIWandWarnReplaced(normal_op?"-level":"+level");
2027 (void) ContrastImage(_image,normal_op,_exception);
2030 if (LocaleCompare("contrast-stretch",option+1) == 0)
2039 flags=ParseGeometry(arg1,&geometry_info);
2040 if ((flags & RhoValue) == 0)
2041 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2042 black_point=geometry_info.rho;
2043 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2045 if ((flags & PercentValue) != 0) {
2046 black_point*=(double) _image->columns*_image->rows/100.0;
2047 white_point*=(double) _image->columns*_image->rows/100.0;
2049 white_point=(MagickRealType) _image->columns*_image->rows-
2051 (void) ContrastStretchImage(_image,black_point,white_point,
2055 if (LocaleCompare("convolve",option+1) == 0)
2060 kernel_info=AcquireKernelInfo(arg1);
2061 if (kernel_info == (KernelInfo *) NULL)
2062 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2063 new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
2065 kernel_info=DestroyKernelInfo(kernel_info);
2068 if (LocaleCompare("crop",option+1) == 0)
2070 /* WARNING: This can generate multiple images! */
2071 if (IfMagickFalse(IsGeometry(arg1)))
2072 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2073 new_image=CropImageToTiles(_image,arg1,_exception);
2076 if (LocaleCompare("cycle",option+1) == 0)
2078 if (IfMagickFalse(IsGeometry(arg1)))
2079 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2080 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2084 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2088 if (LocaleCompare("decipher",option+1) == 0)
2093 passkey=FileToStringInfo(arg1,~0,_exception);
2094 if (passkey == (StringInfo *) NULL)
2095 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2097 (void) PasskeyDecipherImage(_image,passkey,_exception);
2098 passkey=DestroyStringInfo(passkey);
2101 if (LocaleCompare("depth",option+1) == 0)
2103 /* The _image_info->depth setting has already been set
2104 We just need to apply it to all images in current sequence
2106 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2107 That is it really is an operation, not a setting! Arrgghhh
2109 FUTURE: this should not be an operator!!!
2111 (void) SetImageDepth(_image,_image_info->depth,_exception);
2114 if (LocaleCompare("deskew",option+1) == 0)
2120 if (IfMagickFalse(IsGeometry(arg1)))
2121 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2122 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
2125 threshold=40.0*QuantumRange/100.0;
2126 new_image=DeskewImage(_image,threshold,_exception);
2129 if (LocaleCompare("despeckle",option+1) == 0)
2131 new_image=DespeckleImage(_image,_exception);
2134 if (LocaleCompare("distort",option+1) == 0)
2145 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2147 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2149 if ((DistortImageMethod) parse == ResizeDistortion)
2153 /* Special Case - Argument is actually a resize geometry!
2154 ** Convert that to an appropriate distortion argument array.
2155 ** FUTURE: make a separate special resize operator
2156 Roll into a resize special operator */
2157 if (IfMagickFalse(IsGeometry(arg2)))
2158 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2160 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
2161 resize_args[0]=(double) geometry.width;
2162 resize_args[1]=(double) geometry.height;
2163 new_image=DistortImage(_image,(DistortImageMethod) parse,
2164 (size_t)2,resize_args,MagickTrue,_exception);
2167 /* allow percent escapes in argument string */
2168 arg=InterpretImageProperties(_image_info,_image,arg2,_exception);
2169 if (arg == (char *) NULL)
2171 /* convert argument string into an array of doubles */
2172 args = StringToArrayOfDoubles(arg,&count,_exception);
2173 arg=DestroyString(arg);
2174 if (args == (double *)NULL )
2175 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2177 new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
2178 plus_alt_op,_exception);
2179 args=(double *) RelinquishMagickMemory(args);
2182 if (LocaleCompare("draw",option+1) == 0)
2184 (void) CloneString(&_draw_info->primitive,arg1);
2185 (void) DrawImage(_image,_draw_info,_exception);
2186 (void) CloneString(&_draw_info->primitive,(char *)NULL);
2189 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2193 if (LocaleCompare("edge",option+1) == 0)
2195 flags=ParseGeometry(arg1,&geometry_info);
2196 if ((flags & (RhoValue|SigmaValue)) == 0)
2197 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2198 if ((flags & SigmaValue) == 0)
2199 geometry_info.sigma=1.0;
2200 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2204 if (LocaleCompare("emboss",option+1) == 0)
2206 flags=ParseGeometry(arg1,&geometry_info);
2207 if ((flags & (RhoValue|SigmaValue)) == 0)
2208 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2209 if ((flags & SigmaValue) == 0)
2210 geometry_info.sigma=1.0;
2211 new_image=EmbossImage(_image,geometry_info.rho,
2212 geometry_info.sigma,_exception);
2215 if (LocaleCompare("encipher",option+1) == 0)
2220 passkey=FileToStringInfo(arg1,~0,_exception);
2221 if (passkey != (StringInfo *) NULL)
2223 (void) PasskeyEncipherImage(_image,passkey,_exception);
2224 passkey=DestroyStringInfo(passkey);
2228 if (LocaleCompare("enhance",option+1) == 0)
2230 new_image=EnhanceImage(_image,_exception);
2233 if (LocaleCompare("equalize",option+1) == 0)
2235 (void) EqualizeImage(_image,_exception);
2238 if (LocaleCompare("evaluate",option+1) == 0)
2243 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2245 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2247 if (IfMagickFalse(IsGeometry(arg2)))
2248 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
2249 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
2250 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2254 if (LocaleCompare("extent",option+1) == 0)
2256 if (IfMagickFalse(IsGeometry(arg1)))
2257 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2258 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
2259 if (geometry.width == 0)
2260 geometry.width=_image->columns;
2261 if (geometry.height == 0)
2262 geometry.height=_image->rows;
2263 new_image=ExtentImage(_image,&geometry,_exception);
2266 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2270 if (LocaleCompare("features",option+1) == 0)
2272 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
2274 (void) DeleteImageArtifact(_image,"identify:features");
2277 (void) SetImageArtifact(_image,"identify:features","true");
2278 (void) SetImageArtifact(_image,"verbose","true");
2281 if (LocaleCompare("flip",option+1) == 0)
2283 new_image=FlipImage(_image,_exception);
2286 if (LocaleCompare("flop",option+1) == 0)
2288 new_image=FlopImage(_image,_exception);
2291 if (LocaleCompare("floodfill",option+1) == 0)
2296 if (IfMagickFalse(IsGeometry(arg1)))
2297 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2298 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2299 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2300 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2301 geometry.y,plus_alt_op,_exception);
2304 if (LocaleCompare("frame",option+1) == 0)
2315 value=GetImageOption(_image_info,"compose");
2316 if (value != (const char *) NULL)
2317 compose=(CompositeOperator) ParseCommandOption(
2318 MagickComposeOptions,MagickFalse,value);
2320 compose=OverCompositeOp; /* use Over not _image->compose */
2322 if (IfMagickFalse(IsGeometry(arg1)))
2323 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2324 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
2325 frame_info.width=geometry.width;
2326 frame_info.height=geometry.height;
2327 if ((flags & HeightValue) == 0)
2328 frame_info.height=geometry.width;
2329 frame_info.outer_bevel=geometry.x;
2330 frame_info.inner_bevel=geometry.y;
2331 frame_info.x=(ssize_t) frame_info.width;
2332 frame_info.y=(ssize_t) frame_info.height;
2333 frame_info.width=_image->columns+2*frame_info.width;
2334 frame_info.height=_image->rows+2*frame_info.height;
2335 new_image=FrameImage(_image,&frame_info,compose,_exception);
2338 if (LocaleCompare("function",option+1) == 0)
2349 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2351 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2353 /* allow percent escapes in argument string */
2354 arg=InterpretImageProperties(_image_info,_image,arg2,_exception);
2355 if (arg == (char *) NULL)
2357 /* convert argument string into an array of doubles */
2358 args = StringToArrayOfDoubles(arg,&count,_exception);
2359 arg=DestroyString(arg);
2360 if (args == (double *)NULL )
2361 CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
2363 (void) FunctionImage(_image,(MagickFunction)parse,count,args,
2365 args=(double *) RelinquishMagickMemory(args);
2368 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2372 if (LocaleCompare("gamma",option+1) == 0)
2374 if (IfMagickFalse(IsGeometry(arg1)))
2375 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2377 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2380 _image->gamma=StringToDouble(arg1,(char **) NULL);
2383 if (LocaleCompare("gaussian-blur",option+1) == 0)
2385 flags=ParseGeometry(arg1,&geometry_info);
2386 if ((flags & (RhoValue|SigmaValue)) == 0)
2387 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2388 if ((flags & SigmaValue) == 0)
2389 geometry_info.sigma=1.0;
2390 new_image=GaussianBlurImage(_image,geometry_info.rho,
2391 geometry_info.sigma,_exception);
2394 if (LocaleCompare("gaussian",option+1) == 0)
2396 CLIWandWarnReplaced("-gaussian-blur");
2397 CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL);
2399 if (LocaleCompare("geometry",option+1) == 0)
2402 Record Image offset for composition. (A Setting)
2403 Resize last _image. (ListOperator) -- DEPRECIATE
2404 FUTURE: Why if no 'offset' does this resize ALL images?
2405 Also why is the setting recorded in the IMAGE non-sense!
2408 { /* remove the previous composition geometry offset! */
2409 if (_image->geometry != (char *) NULL)
2410 _image->geometry=DestroyString(_image->geometry);
2413 if (IfMagickFalse(IsGeometry(arg1)))
2414 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2415 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
2416 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2417 (void) CloneString(&_image->geometry,arg1);
2419 new_image=ResizeImage(_image,geometry.width,geometry.height,
2420 _image->filter,_exception);
2423 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2427 if (LocaleCompare("identify",option+1) == 0)
2433 format=GetImageOption(_image_info,"format");
2434 if (format == (char *) NULL)
2436 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2440 text=InterpretImageProperties(_image_info,_image,format,_exception);
2441 if (text == (char *) NULL)
2443 (void) fputs(text,stdout);
2444 (void) fputc('\n',stdout);
2445 text=DestroyString((char *)text);
2448 if (LocaleCompare("implode",option+1) == 0)
2450 flags=ParseGeometry(arg1,&geometry_info);
2451 if ((flags & RhoValue) == 0)
2452 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2453 new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
2457 if (LocaleCompare("interpolative-resize",option+1) == 0)
2459 /* FUTURE: New to IMv7
2460 Roll into a resize special operator */
2461 if (IfMagickFalse(IsGeometry(arg1)))
2462 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2463 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2464 new_image=InterpolativeResizeImage(_image,geometry.width,
2465 geometry.height,_image->interpolate,_exception);
2468 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2472 if (LocaleCompare("lat",option+1) == 0)
2474 flags=ParseGeometry(arg1,&geometry_info);
2475 if ((flags & (RhoValue|SigmaValue)) == 0)
2476 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2477 if ((flags & PercentValue) != 0)
2478 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2479 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
2480 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2484 if (LocaleCompare("level",option+1) == 0)
2494 flags=ParseGeometry(arg1,&geometry_info);
2495 if ((flags & RhoValue) == 0)
2496 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2497 black_point=geometry_info.rho;
2498 white_point=(MagickRealType) QuantumRange;
2499 if ((flags & SigmaValue) != 0)
2500 white_point=geometry_info.sigma;
2502 if ((flags & XiValue) != 0)
2503 gamma=geometry_info.xi;
2504 if ((flags & PercentValue) != 0)
2506 black_point*=(MagickRealType) (QuantumRange/100.0);
2507 white_point*=(MagickRealType) (QuantumRange/100.0);
2509 if ((flags & SigmaValue) == 0)
2510 white_point=(MagickRealType) QuantumRange-black_point;
2511 if (IfPlusOp || ((flags & AspectValue) != 0))
2512 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
2514 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
2517 if (LocaleCompare("level-colors",option+1) == 0)
2520 token[MaxTextExtent];
2529 p=(const char *) arg1;
2530 GetMagickToken(p,&p,token); /* get black point color */
2531 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2532 (void) QueryColorCompliance(token,AllCompliance,
2533 &black_point,_exception);
2535 (void) QueryColorCompliance("#000000",AllCompliance,
2536 &black_point,_exception);
2537 if (isalpha((int) token[0]) || (token[0] == '#'))
2538 GetMagickToken(p,&p,token);
2540 white_point=black_point; /* set everything to that color */
2543 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2544 GetMagickToken(p,&p,token); /* Get white point color. */
2545 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2546 (void) QueryColorCompliance(token,AllCompliance,
2547 &white_point,_exception);
2549 (void) QueryColorCompliance("#ffffff",AllCompliance,
2550 &white_point,_exception);
2552 (void) LevelImageColors(_image,&black_point,&white_point,
2553 plus_alt_op,_exception);
2556 if (LocaleCompare("linear-stretch",option+1) == 0)
2565 flags=ParseGeometry(arg1,&geometry_info);
2566 if ((flags & RhoValue) == 0)
2567 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2568 black_point=geometry_info.rho;
2569 white_point=(MagickRealType) _image->columns*_image->rows;
2570 if ((flags & SigmaValue) != 0)
2571 white_point=geometry_info.sigma;
2572 if ((flags & PercentValue) != 0)
2574 black_point*=(double) _image->columns*_image->rows/100.0;
2575 white_point*=(double) _image->columns*_image->rows/100.0;
2577 if ((flags & SigmaValue) == 0)
2578 white_point=(MagickRealType) _image->columns*_image->rows-
2580 (void) LinearStretchImage(_image,black_point,white_point,_exception);
2583 if (LocaleCompare("liquid-rescale",option+1) == 0)
2585 /* FUTURE: Roll into a resize special operator */
2586 if (IfMagickFalse(IsGeometry(arg1)))
2587 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2588 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
2589 if ((flags & XValue) == 0)
2591 if ((flags & YValue) == 0)
2593 new_image=LiquidRescaleImage(_image,geometry.width,
2594 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
2597 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2601 if (LocaleCompare("map",option+1) == 0)
2603 CLIWandWarnReplaced("-remap");
2604 CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL);
2607 if (LocaleCompare("mask",option+1) == 0)
2613 { /* Remove a mask. */
2614 (void) SetImageMask(_image,(Image *) NULL,_exception);
2617 /* Set the image mask. */
2618 mask=GetImageCache(_image_info,arg1,_exception);
2619 if (mask == (Image *) NULL)
2621 (void) SetImageMask(_image,mask,_exception);
2622 mask=DestroyImage(mask);
2625 if (LocaleCompare("matte",option+1) == 0)
2627 CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
2628 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2629 DeactivateAlphaChannel, _exception);
2632 if (LocaleCompare("median",option+1) == 0)
2634 CLIWandWarnReplaced("-statistic Median");
2635 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2638 if (LocaleCompare("mode",option+1) == 0)
2640 /* FUTURE: note this is also a special "montage" option */
2641 CLIWandWarnReplaced("-statistic Mode");
2642 CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1);
2645 if (LocaleCompare("modulate",option+1) == 0)
2647 if (IfMagickFalse(IsGeometry(arg1)))
2648 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2649 (void) ModulateImage(_image,arg1,_exception);
2652 if (LocaleCompare("monitor",option+1) == 0)
2654 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
2655 (MagickProgressMonitor) NULL,(void *) NULL);
2658 if (LocaleCompare("monochrome",option+1) == 0)
2660 (void) SetImageType(_image,BilevelType,_exception);
2663 if (LocaleCompare("morphology",option+1) == 0)
2666 token[MaxTextExtent];
2678 GetMagickToken(p,&p,token);
2679 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2681 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2684 GetMagickToken(p,&p,token);
2685 if ((*p == ':') || (*p == ','))
2686 GetMagickToken(p,&p,token);
2688 iterations=(ssize_t) StringToLong(p);
2689 kernel=AcquireKernelInfo(arg2);
2690 if (kernel == (KernelInfo *) NULL)
2691 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2693 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2694 iterations,kernel,_exception);
2695 kernel=DestroyKernelInfo(kernel);
2698 if (LocaleCompare("motion-blur",option+1) == 0)
2700 flags=ParseGeometry(arg1,&geometry_info);
2701 if ((flags & (RhoValue|SigmaValue)) == 0)
2702 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2703 if ((flags & SigmaValue) == 0)
2704 geometry_info.sigma=1.0;
2705 new_image=MotionBlurImage(_image,geometry_info.rho,
2706 geometry_info.sigma,geometry_info.xi,_exception);
2709 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2713 if (LocaleCompare("negate",option+1) == 0)
2715 (void) NegateImage(_image, plus_alt_op, _exception);
2718 if (LocaleCompare("noise",option+1) == 0)
2728 CLIWandWarnReplaced("-statistic NonPeak");
2729 CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1);
2732 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2734 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2737 value=GetImageOption(_image_info,"attenuate");
2738 if (value != (const char *) NULL)
2739 attenuate=StringToDouble(value,(char **) NULL);
2740 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2744 if (LocaleCompare("normalize",option+1) == 0)
2746 (void) NormalizeImage(_image,_exception);
2749 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2753 if (LocaleCompare("opaque",option+1) == 0)
2758 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2759 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2763 if (LocaleCompare("ordered-dither",option+1) == 0)
2765 (void) OrderedPosterizeImage(_image,arg1,_exception);
2768 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2772 if (LocaleCompare("paint",option+1) == 0)
2774 flags=ParseGeometry(arg1,&geometry_info);
2775 if ((flags & (RhoValue|SigmaValue)) == 0)
2776 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2777 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2781 if (LocaleCompare("polaroid",option+1) == 0)
2793 random_info=AcquireRandomInfo();
2794 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2795 random_info=DestroyRandomInfo(random_info);
2798 flags=ParseGeometry(arg1,&geometry_info);
2799 if ((flags & RhoValue) == 0)
2800 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2801 angle=geometry_info.rho;
2803 caption=GetImageProperty(_image,"caption",_exception);
2804 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2805 _image->interpolate,_exception);
2808 if (LocaleCompare("posterize",option+1) == 0)
2810 flags=ParseGeometry(arg1,&geometry_info);
2811 if ((flags & RhoValue) == 0)
2812 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2813 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
2814 _quantize_info->dither,_exception);
2817 if (LocaleCompare("preview",option+1) == 0)
2819 /* FUTURE: should be a 'Genesis' option?
2820 Option however is also in WandSettingOptionInfo()
2823 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
2825 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
2827 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
2830 if (LocaleCompare("profile",option+1) == 0)
2845 { /* Remove a profile from the _image. */
2846 (void) ProfileImage(_image,arg1,(const unsigned char *)
2850 /* Associate a profile with the _image. */
2851 profile_info=CloneImageInfo(_image_info);
2852 profile=GetImageProfile(_image,"iptc");
2853 if (profile != (StringInfo *) NULL)
2854 profile_info->profile=(void *) CloneStringInfo(profile);
2855 profile_image=GetImageCache(profile_info,arg1,_exception);
2856 profile_info=DestroyImageInfo(profile_info);
2857 if (profile_image == (Image *) NULL)
2862 profile_info=CloneImageInfo(_image_info);
2863 (void) CopyMagickString(profile_info->filename,arg1,
2865 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
2866 if (profile != (StringInfo *) NULL)
2868 (void) ProfileImage(_image,profile_info->magick,
2869 GetStringInfoDatum(profile),(size_t)
2870 GetStringInfoLength(profile),_exception);
2871 profile=DestroyStringInfo(profile);
2873 profile_info=DestroyImageInfo(profile_info);
2876 ResetImageProfileIterator(profile_image);
2877 name=GetNextImageProfile(profile_image);
2878 while (name != (const char *) NULL)
2880 profile=GetImageProfile(profile_image,name);
2881 if (profile != (StringInfo *) NULL)
2882 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2883 (size_t) GetStringInfoLength(profile),_exception);
2884 name=GetNextImageProfile(profile_image);
2886 profile_image=DestroyImage(profile_image);
2889 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2893 if (LocaleCompare("radial-blur",option+1) == 0)
2895 flags=ParseGeometry(arg1,&geometry_info);
2896 if ((flags & RhoValue) == 0)
2897 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2898 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
2901 if (LocaleCompare("raise",option+1) == 0)
2903 if (IfMagickFalse(IsGeometry(arg1)))
2904 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2905 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
2906 if ((flags & SigmaValue) == 0)
2907 geometry.height=geometry.width;
2908 (void) RaiseImage(_image,&geometry,normal_op,_exception);
2911 if (LocaleCompare("random-threshold",option+1) == 0)
2913 if (IfMagickFalse(IsGeometry(arg1)))
2914 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2915 (void) RandomThresholdImage(_image,arg1,_exception);
2918 if (LocaleCompare("recolor",option+1) == 0)
2920 CLIWandWarnReplaced("-color-matrix");
2921 CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL);
2923 if (LocaleCompare("remap",option+1) == 0)
2928 remap_image=GetImageCache(_image_info,arg1,_exception);
2929 if (remap_image == (Image *) NULL)
2931 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
2932 remap_image=DestroyImage(remap_image);
2935 if (LocaleCompare("repage",option+1) == 0)
2939 if (IfMagickFalse(IsGeometry(arg1)))
2940 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
2942 (void) ResetImagePage(_image,arg1);
2945 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
2948 if (LocaleCompare("resample",option+1) == 0)
2950 /* FUTURE: Roll into a resize special operation */
2951 flags=ParseGeometry(arg1,&geometry_info);
2952 if ((flags & (RhoValue|SigmaValue)) == 0)
2953 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2954 if ((flags & SigmaValue) == 0)
2955 geometry_info.sigma=geometry_info.rho;
2956 new_image=ResampleImage(_image,geometry_info.rho,
2957 geometry_info.sigma,_image->filter,_exception);
2960 if (LocaleCompare("resize",option+1) == 0)
2962 if (IfMagickFalse(IsGeometry(arg1)))
2963 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2964 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2965 new_image=ResizeImage(_image,geometry.width,geometry.height,
2966 _image->filter,_exception);
2969 if (LocaleCompare("roll",option+1) == 0)
2971 if (IfMagickFalse(IsGeometry(arg1)))
2972 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2973 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2974 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
2977 if (LocaleCompare("rotate",option+1) == 0)
2979 flags=ParseGeometry(arg1,&geometry_info);
2980 if ((flags & RhoValue) == 0)
2981 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2982 if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
2984 if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
2986 new_image=RotateImage(_image,geometry_info.rho,_exception);
2989 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2993 if (LocaleCompare("sample",option+1) == 0)
2995 /* FUTURE: Roll into a resize special operator */
2996 if (IfMagickFalse(IsGeometry(arg1)))
2997 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2998 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2999 new_image=SampleImage(_image,geometry.width,geometry.height,
3003 if (LocaleCompare("scale",option+1) == 0)
3005 /* FUTURE: Roll into a resize special operator */
3006 if (IfMagickFalse(IsGeometry(arg1)))
3007 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3008 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3009 new_image=ScaleImage(_image,geometry.width,geometry.height,
3013 if (LocaleCompare("segment",option+1) == 0)
3015 flags=ParseGeometry(arg1,&geometry_info);
3016 if ((flags & (RhoValue|SigmaValue)) == 0)
3017 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3018 if ((flags & SigmaValue) == 0)
3019 geometry_info.sigma=1.0;
3020 (void) SegmentImage(_image,_image->colorspace,
3021 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3025 if (LocaleCompare("selective-blur",option+1) == 0)
3027 flags=ParseGeometry(arg1,&geometry_info);
3028 if ((flags & (RhoValue|SigmaValue)) == 0)
3029 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3030 if ((flags & SigmaValue) == 0)
3031 geometry_info.sigma=1.0;
3032 if ((flags & PercentValue) != 0)
3033 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3034 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3035 geometry_info.sigma,geometry_info.xi,_exception);
3038 if (LocaleCompare("separate",option+1) == 0)
3040 /* WARNING: This can generate multiple images! */
3041 /* FUTURE - this may be replaced by a "-channel" method */
3042 new_image=SeparateImages(_image,_exception);
3045 if (LocaleCompare("sepia-tone",option+1) == 0)
3047 if (IfMagickFalse(IsGeometry(arg1)))
3048 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3049 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3050 (double) QuantumRange+1.0),_exception);
3053 if (LocaleCompare("set",option+1) == 0)
3059 if (LocaleNCompare(arg1,"registry:",9) == 0)
3060 (void) DeleteImageRegistry(arg1+9);
3062 if (LocaleNCompare(arg1,"option:",7) == 0)
3064 (void) DeleteImageOption(_image_info,arg1+7);
3065 (void) DeleteImageArtifact(_image,arg1+7);
3068 (void) DeleteImageProperty(_image,arg1);
3071 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
3072 if (value == (char *) NULL)
3074 if (LocaleNCompare(arg1,"registry:",9) == 0)
3075 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
3077 if (LocaleNCompare(arg1,"option:",7) == 0)
3079 (void) SetImageOption(_image_info,arg1+7,value);
3080 (void) SetImageArtifact(_image,arg1+7,value);
3083 (void) SetImageProperty(_image,arg1,value,_exception);
3084 value=DestroyString(value);
3087 if (LocaleCompare("shade",option+1) == 0)
3089 flags=ParseGeometry(arg1,&geometry_info);
3090 if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
3091 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3092 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3093 geometry_info.sigma,_exception);
3096 if (LocaleCompare("shadow",option+1) == 0)
3098 flags=ParseGeometry(arg1,&geometry_info);
3099 if ((flags & (RhoValue|SigmaValue)) == 0)
3100 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3101 if ((flags & SigmaValue) == 0)
3102 geometry_info.sigma=1.0;
3103 if ((flags & XiValue) == 0)
3104 geometry_info.xi=4.0;
3105 if ((flags & PsiValue) == 0)
3106 geometry_info.psi=4.0;
3107 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3108 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3109 ceil(geometry_info.psi-0.5),_exception);
3112 if (LocaleCompare("sharpen",option+1) == 0)
3114 flags=ParseGeometry(arg1,&geometry_info);
3115 if ((flags & (RhoValue|SigmaValue)) == 0)
3116 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3117 if ((flags & SigmaValue) == 0)
3118 geometry_info.sigma=1.0;
3119 if ((flags & XiValue) == 0)
3120 geometry_info.xi=0.0;
3121 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3125 if (LocaleCompare("shave",option+1) == 0)
3127 if (IfMagickFalse(IsGeometry(arg1)))
3128 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3129 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3130 new_image=ShaveImage(_image,&geometry,_exception);
3133 if (LocaleCompare("shear",option+1) == 0)
3135 flags=ParseGeometry(arg1,&geometry_info);
3136 if ((flags & RhoValue) == 0)
3137 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3138 if ((flags & SigmaValue) == 0)
3139 geometry_info.sigma=geometry_info.rho;
3140 new_image=ShearImage(_image,geometry_info.rho,
3141 geometry_info.sigma,_exception);
3144 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
3146 flags=ParseGeometry(arg1,&geometry_info);
3147 if ((flags & RhoValue) == 0)
3148 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3149 if ((flags & SigmaValue) == 0)
3150 geometry_info.sigma=(double) QuantumRange/2.0;
3151 if ((flags & PercentValue) != 0)
3152 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3154 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
3155 geometry_info.sigma,_exception);
3158 if (LocaleCompare("sketch",option+1) == 0)
3160 flags=ParseGeometry(arg1,&geometry_info);
3161 if ((flags & (RhoValue|SigmaValue)) == 0)
3162 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3163 if ((flags & SigmaValue) == 0)
3164 geometry_info.sigma=1.0;
3165 new_image=SketchImage(_image,geometry_info.rho,
3166 geometry_info.sigma,geometry_info.xi,_exception);
3169 if (LocaleCompare("solarize",option+1) == 0)
3171 if (IfMagickFalse(IsGeometry(arg1)))
3172 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3173 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3174 QuantumRange+1.0),_exception);
3177 if (LocaleCompare("sparse-color",option+1) == 0)
3182 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3184 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3186 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
3187 if (arguments == (char *) NULL)
3188 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3189 new_image=SparseColorOption(_image,(SparseColorMethod)parse,
3190 arguments,_exception);
3191 arguments=DestroyString(arguments);
3194 if (LocaleCompare("splice",option+1) == 0)
3196 if (IfMagickFalse(IsGeometry(arg1)))
3197 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3198 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
3199 new_image=SpliceImage(_image,&geometry,_exception);
3202 if (LocaleCompare("spread",option+1) == 0)
3204 flags=ParseGeometry(arg1,&geometry_info);
3205 if ((flags & RhoValue) == 0)
3206 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3207 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3211 if (LocaleCompare("statistic",option+1) == 0)
3213 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3215 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
3217 flags=ParseGeometry(arg2,&geometry_info);
3218 if ((flags & RhoValue) == 0)
3219 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3220 if ((flags & SigmaValue) == 0)
3221 geometry_info.sigma=geometry_info.rho;
3222 new_image=StatisticImage(_image,(StatisticType)parse,
3223 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3227 if (LocaleCompare("strip",option+1) == 0)
3229 (void) StripImage(_image,_exception);
3232 if (LocaleCompare("swirl",option+1) == 0)
3234 flags=ParseGeometry(arg2,&geometry_info);
3235 if ((flags & RhoValue) == 0)
3236 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3237 new_image=SwirlImage(_image,geometry_info.rho,
3238 _image->interpolate,_exception);
3241 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3245 if (LocaleCompare("threshold",option+1) == 0)
3250 threshold=(double) QuantumRange/2;
3252 if (IfMagickFalse(IsGeometry(arg1)))
3253 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3254 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
3256 (void) BilevelImage(_image,threshold,_exception);
3259 if (LocaleCompare("thumbnail",option+1) == 0)
3261 if (IfMagickFalse(IsGeometry(arg1)))
3262 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3263 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3264 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3268 if (LocaleCompare("tint",option+1) == 0)
3270 if (IfMagickFalse(IsGeometry(arg1)))
3271 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3272 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
3275 if (LocaleCompare("transform",option+1) == 0)
3277 CLIWandWarnReplaced("+distort AffineProjection");
3278 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
3281 if (LocaleCompare("transparent",option+1) == 0)
3286 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3287 (void) TransparentPaintImage(_image,&target,(Quantum)
3288 TransparentAlpha,plus_alt_op,_exception);
3291 if (LocaleCompare("transpose",option+1) == 0)
3293 new_image=TransposeImage(_image,_exception);
3296 if (LocaleCompare("transverse",option+1) == 0)
3298 new_image=TransverseImage(_image,_exception);
3301 if (LocaleCompare("trim",option+1) == 0)
3303 new_image=TrimImage(_image,_exception);
3306 if (LocaleCompare("type",option+1) == 0)
3308 /* Note that "type" setting should have already been defined */
3309 (void) SetImageType(_image,_image_info->type,_exception);
3312 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3316 if (LocaleCompare("unique",option+1) == 0)
3318 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3319 Option is not documented, bt appears to be for "identify".
3320 We may need a identify specific verbose!
3323 (void) DeleteImageArtifact(_image,"identify:unique-colors");
3326 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3327 (void) SetImageArtifact(_image,"verbose","true");
3330 if (LocaleCompare("unique-colors",option+1) == 0)
3332 new_image=UniqueImageColors(_image,_exception);
3335 if (LocaleCompare("unsharp",option+1) == 0)
3337 flags=ParseGeometry(arg1,&geometry_info);
3338 if ((flags & (RhoValue|SigmaValue)) == 0)
3339 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3340 if ((flags & SigmaValue) == 0)
3341 geometry_info.sigma=1.0;
3342 if ((flags & XiValue) == 0)
3343 geometry_info.xi=1.0;
3344 if ((flags & PsiValue) == 0)
3345 geometry_info.psi=0.05;
3346 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3347 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
3350 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3354 if (LocaleCompare("verbose",option+1) == 0)
3356 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
3357 three places! ImageArtifact ImageOption _image_info->verbose
3358 Some how new images also get this artifact!
3360 (void) SetImageArtifact(_image,option+1,
3361 IfNormalOp ? "true" : "false" );
3364 if (LocaleCompare("vignette",option+1) == 0)
3366 flags=ParseGeometry(arg1,&geometry_info);
3367 if ((flags & (RhoValue|SigmaValue)) == 0)
3368 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3369 if ((flags & SigmaValue) == 0)
3370 geometry_info.sigma=1.0;
3371 if ((flags & XiValue) == 0)
3372 geometry_info.xi=0.1*_image->columns;
3373 if ((flags & PsiValue) == 0)
3374 geometry_info.psi=0.1*_image->rows;
3375 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3376 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3377 ceil(geometry_info.psi-0.5),_exception);
3380 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3384 if (LocaleCompare("wave",option+1) == 0)
3386 flags=ParseGeometry(arg1,&geometry_info);
3387 if ((flags & (RhoValue|SigmaValue)) == 0)
3388 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3389 if ((flags & SigmaValue) == 0)
3390 geometry_info.sigma=1.0;
3391 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3392 _image->interpolate,_exception);
3395 if (LocaleCompare("white-threshold",option+1) == 0)
3397 if (IfMagickFalse(IsGeometry(arg1)))
3398 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3399 (void) WhiteThresholdImage(_image,arg1,_exception);
3402 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3405 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3408 Replace current image with any image that was generated
3409 and set image point to last image (so image->next is correct)
3411 if (new_image != (Image *) NULL)
3412 ReplaceImageInListReturnLast(&_image,new_image);
3417 #undef _quantize_info
3426 WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
3427 const char *option, const char *arg1, const char *arg2)
3433 assert(cli_wand != (MagickCLI *) NULL);
3434 assert(cli_wand->signature == WandSignature);
3435 assert(cli_wand->wand.signature == WandSignature);
3436 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3437 if (IfMagickTrue(cli_wand->wand.debug))
3438 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
3440 #if !USE_WAND_METHODS
3441 /* FUTURE add appropriate tracing */
3443 n=GetImageListLength(cli_wand->wand.images);
3444 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3447 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3448 if ( cli_wand->wand.images->next == (Image *) NULL )
3450 cli_wand->wand.images=cli_wand->wand.images->next;
3453 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3455 MagickResetIterator(&cli_wand->wand);
3456 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
3457 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3458 MagickResetIterator(&cli_wand->wand);
3464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3468 + C L I L i s t O p e r a t o r I m a g e s %
3472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3474 % CLIListOperatorImages() applies a single operation that is apply to the
3475 % entire image list as a whole. The result is often a complete replacment
3476 % of the image list with a completely new list, or just a single image.
3478 % The format of the MogrifyImage method is:
3480 % void CLIListOperatorImages(MagickCLI *cli_wand,
3481 % const char *option, const char *arg1, const char *arg2)
3483 % A description of each parameter follows:
3485 % o cli_wand: structure holding settings to be applied
3487 % o option: The option string for the operation
3489 % o arg1, arg2: optional argument strings to the operation
3490 % arg2 is currently not used
3493 WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
3494 const char *option,const char *arg1, const char *magick_unused(arg2))
3502 #define _image_info (cli_wand->wand.image_info)
3503 #define _images (cli_wand->wand.images)
3504 #define _exception (cli_wand->wand.exception)
3505 #define _draw_info (cli_wand->draw_info)
3506 #define _quantize_info (cli_wand->quantize_info)
3507 #define IfNormalOp (*option=='-')
3508 #define IfPlusOp (*option!='-')
3509 #define normal_op IsMagickTrue(IfNormalOp)
3511 assert(cli_wand != (MagickCLI *) NULL);
3512 assert(cli_wand->signature == WandSignature);
3513 assert(cli_wand->wand.signature == WandSignature);
3514 assert(_images != (Image *) NULL); /* _images must be present */
3515 if (IfMagickTrue(cli_wand->wand.debug))
3516 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
3518 new_images=NewImageList();
3520 switch (*(option+1))
3524 if (LocaleCompare("append",option+1) == 0)
3526 new_images=AppendImages(_images,normal_op,_exception);
3529 if (LocaleCompare("average",option+1) == 0)
3531 CLIWandWarnReplaced("-evaluate-sequence Mean");
3532 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
3535 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3539 if (LocaleCompare("channel-fx",option+1) == 0)
3541 new_images=ChannelFxImage(_images,arg1,_exception);
3544 if (LocaleCompare("clut",option+1) == 0)
3549 /* FUTURE - make this a compose option, and thus can be used
3550 with layers compose or even compose last image over all other
3553 new_images=RemoveFirstImageFromList(&_images);
3554 clut_image=RemoveLastImageFromList(&_images);
3555 /* FUTURE - produce Exception, rather than silent fail */
3556 if (clut_image == (Image *) NULL)
3558 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
3559 clut_image=DestroyImage(clut_image);
3562 if (LocaleCompare("coalesce",option+1) == 0)
3564 new_images=CoalesceImages(_images,_exception);
3567 if (LocaleCompare("combine",option+1) == 0)
3569 /* FUTURE - this may be replaced by a 'channel' method */
3570 new_images=CombineImages(_images,_exception);
3573 if (LocaleCompare("composite",option+1) == 0)
3591 /* Compose value from "-compose" option only */
3592 value=GetImageOption(_image_info,"compose");
3593 if (value == (const char *) NULL)
3594 compose=OverCompositeOp; /* use Over not source_image->compose */
3596 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3599 /* Get "clip-to-self" expert setting (false is normal) */
3600 value=GetImageOption(_image_info,"compose:clip-to-self");
3601 if (value == (const char *) NULL)
3602 clip_to_self=MagickTrue;
3604 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3605 "compose:clip-to-self")); /* if this is true */
3606 value=GetImageOption(_image_info,"compose:outside-overlay");
3607 if (value != (const char *) NULL) { /* or this false */
3608 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
3609 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
3612 new_images=RemoveFirstImageFromList(&_images);
3613 source_image=RemoveFirstImageFromList(&_images);
3614 if (source_image == (Image *) NULL)
3615 break; /* FUTURE - produce Exception, rather than silent fail */
3617 /* FUTURE - this should not be here! - should be part of -geometry */
3618 (void) TransformImage(&source_image,(char *) NULL,
3619 source_image->geometry,_exception);
3621 SetGeometry(source_image,&geometry);
3622 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3623 GravityAdjustGeometry(new_images->columns,new_images->rows,
3624 new_images->gravity, &geometry);
3626 mask_image=RemoveFirstImageFromList(&_images);
3627 if (mask_image != (Image *) NULL)
3628 { /* handle a third write mask image */
3629 if ((compose == DisplaceCompositeOp) ||
3630 (compose == DistortCompositeOp)) {
3631 /* Merge Y displacement into X displace/distort map. */
3632 (void) CompositeImage(source_image,mask_image,
3633 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3634 mask_image=DestroyImage(mask_image);
3637 /* Set a blending mask for the composition. */
3638 (void) NegateImage(mask_image,MagickFalse,_exception);
3639 (void) SetImageMask(new_images,mask_image,_exception);
3640 mask_image=DestroyImage(mask_image);
3643 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3644 geometry.x,geometry.y,_exception);
3645 (void) SetImageMask(new_images,(Image *) NULL,_exception);
3646 source_image=DestroyImage(source_image);
3649 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3653 if (LocaleCompare("deconstruct",option+1) == 0)
3655 CLIWandWarnReplaced("-layer CompareAny");
3656 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
3659 if (LocaleCompare("delete",option+1) == 0)
3662 DeleteImages(&_images,arg1,_exception);
3664 DeleteImages(&_images,"-1",_exception);
3667 if (LocaleCompare("duplicate",option+1) == 0)
3677 if (IfMagickFalse(IsGeometry(arg1)))
3678 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3680 number_duplicates=(size_t) StringToLong(arg1);
3682 if (p == (const char *) NULL)
3683 new_images=DuplicateImages(_images,number_duplicates,"-1",
3686 new_images=DuplicateImages(_images,number_duplicates,p,
3690 new_images=DuplicateImages(_images,1,"-1",_exception);
3691 AppendImageToList(&_images, new_images);
3692 new_images=(Image *)NULL;
3695 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3699 if (LocaleCompare("evaluate-sequence",option+1) == 0)
3701 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3703 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3705 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3709 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3713 if (LocaleCompare("fft",option+1) == 0)
3715 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
3718 if (LocaleCompare("flatten",option+1) == 0)
3720 /* REDIRECTED to use -layers flatten instead */
3721 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
3724 if (LocaleCompare("fx",option+1) == 0)
3726 new_images=FxImage(_images,arg1,_exception);
3729 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3733 if (LocaleCompare("hald-clut",option+1) == 0)
3735 /* FUTURE - make this a compose option (and thus layers compose )
3736 or perhaps compose last image over all other _images.
3741 new_images=RemoveFirstImageFromList(&_images);
3742 hald_image=RemoveLastImageFromList(&_images);
3743 if (hald_image == (Image *) NULL)
3745 (void) HaldClutImage(new_images,hald_image,_exception);
3746 hald_image=DestroyImage(hald_image);
3749 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3753 if (LocaleCompare("ift",option+1) == 0)
3759 magnitude_image=RemoveFirstImageFromList(&_images);
3760 phase_image=RemoveFirstImageFromList(&_images);
3761 /* FUTURE - produce Exception, rather than silent fail */
3762 if (phase_image == (Image *) NULL)
3764 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
3765 normal_op,_exception);
3766 magnitude_image=DestroyImage(magnitude_image);
3767 phase_image=DestroyImage(phase_image);
3770 if (LocaleCompare("insert",option+1) == 0)
3779 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
3780 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3782 insert_image=RemoveLastImageFromList(&_images);
3784 index=(ssize_t) StringToLong(arg1);
3785 index_image=insert_image;
3787 PrependImageToList(&_images,insert_image);
3788 else if (index == (ssize_t) GetImageListLength(_images))
3789 AppendImageToList(&_images,insert_image);
3792 index_image=GetImageFromList(_images,index-1);
3793 if (index_image == (Image *) NULL)
3794 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
3795 InsertImageInList(&index_image,insert_image);
3797 _images=GetFirstImageInList(index_image);
3800 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3804 if (LocaleCompare("layers",option+1) == 0)
3806 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
3808 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
3810 switch ((ImageLayerMethod) parse)
3814 new_images=CoalesceImages(_images,_exception);
3817 case CompareAnyLayer:
3818 case CompareClearLayer:
3819 case CompareOverlayLayer:
3822 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
3829 case TrimBoundsLayer:
3831 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
3837 new_images=DisposeImages(_images,_exception);
3840 case OptimizeImageLayer:
3842 new_images=OptimizeImageLayers(_images,_exception);
3845 case OptimizePlusLayer:
3847 new_images=OptimizePlusImageLayers(_images,_exception);
3850 case OptimizeTransLayer:
3852 OptimizeImageTransparency(_images,_exception);
3855 case RemoveDupsLayer:
3857 RemoveDuplicateLayers(&_images,_exception);
3860 case RemoveZeroLayer:
3862 RemoveZeroDelayLayers(&_images,_exception);
3866 { /* General Purpose, GIF Animation Optimizer. */
3867 new_images=CoalesceImages(_images,_exception);
3868 if (new_images == (Image *) NULL)
3870 _images=DestroyImageList(_images);
3871 _images=OptimizeImageLayers(new_images,_exception);
3872 if (_images == (Image *) NULL)
3874 new_images=DestroyImageList(new_images);
3875 OptimizeImageTransparency(_images,_exception);
3876 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3880 case CompositeLayer:
3894 value=GetImageOption(_image_info,"compose");
3895 compose=OverCompositeOp; /* Default to Over */
3896 if (value != (const char *) NULL)
3897 compose=(CompositeOperator) ParseCommandOption(
3898 MagickComposeOptions,MagickFalse,value);
3900 /* Split image sequence at the first 'NULL:' image. */
3902 while (source != (Image *) NULL)
3904 source=GetNextImageInList(source);
3905 if ((source != (Image *) NULL) &&
3906 (LocaleCompare(source->magick,"NULL") == 0))
3909 if (source != (Image *) NULL)
3911 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3912 (GetNextImageInList(source) == (Image *) NULL))
3913 source=(Image *) NULL;
3915 { /* Separate the two lists, junk the null: image. */
3916 source=SplitImageList(source->previous);
3917 DeleteImageFromList(&source);
3920 if (source == (Image *) NULL)
3922 (void) ThrowMagickException(_exception,GetMagickModule(),
3923 OptionError,"MissingNullSeparator","layers Composite");
3926 /* Adjust offset with gravity and virtual canvas. */
3927 SetGeometry(_images,&geometry);
3928 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
3929 geometry.width=source->page.width != 0 ?
3930 source->page.width : source->columns;
3931 geometry.height=source->page.height != 0 ?
3932 source->page.height : source->rows;
3933 GravityAdjustGeometry(_images->page.width != 0 ?
3934 _images->page.width : _images->columns,
3935 _images->page.height != 0 ? _images->page.height :
3936 _images->rows,_images->gravity,&geometry);
3938 /* Compose the two image sequences together */
3939 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
3941 source=DestroyImageList(source);
3947 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3951 if (LocaleCompare("map",option+1) == 0)
3953 CLIWandWarnReplaced("+remap");
3954 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
3957 if (LocaleCompare("morph",option+1) == 0)
3962 if (IfMagickFalse(IsGeometry(arg1)))
3963 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3964 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
3966 if (morph_image == (Image *) NULL)
3968 _images=DestroyImageList(_images);
3969 _images=morph_image;
3972 if (LocaleCompare("mosaic",option+1) == 0)
3974 /* REDIRECTED to use -layers mosaic instead */
3975 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
3978 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3982 if (LocaleCompare("print",option+1) == 0)
3987 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
3988 if (string == (char *) NULL)
3990 (void) FormatLocaleFile(stdout,"%s",string);
3991 string=DestroyString(string);
3994 if (LocaleCompare("process",option+1) == 0)
3996 /* FUTURE: better parsing using ScriptToken() from string ??? */
4004 arguments=StringToArgv(arg1,&number_arguments);
4005 if (arguments == (char **) NULL)
4007 if (strchr(arguments[1],'=') != (char *) NULL)
4028 Support old style syntax, filter="-option arg1".
4030 length=strlen(arg1);
4031 token=(char *) NULL;
4032 if (~length >= (MaxTextExtent-1))
4033 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4035 if (token == (char *) NULL)
4039 token_info=AcquireTokenInfo();
4040 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4041 "\"",'\0',&breaker,&next,"e);
4042 token_info=DestroyTokenInfo(token_info);
4048 argv=(&(arguments[next]));
4049 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4052 token=DestroyString(token);
4055 (void) SubstituteString(&arguments[1],"-","");
4056 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4057 number_arguments-2,(const char **) arguments+2,_exception);
4058 for (j=0; j < number_arguments; j++)
4059 arguments[j]=DestroyString(arguments[j]);
4060 arguments=(char **) RelinquishMagickMemory(arguments);
4063 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4067 if (LocaleCompare("remap",option+1) == 0)
4069 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4072 if (LocaleCompare("reverse",option+1) == 0)
4074 ReverseImageList(&_images);
4077 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4081 if (LocaleCompare("smush",option+1) == 0)
4083 /* FUTURE: this option needs more work to make better */
4087 if (IfMagickFalse(IsGeometry(arg1)))
4088 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4089 offset=(ssize_t) StringToLong(arg1);
4090 new_images=SmushImages(_images,normal_op,offset,_exception);
4093 if (LocaleCompare("subimage",option+1) == 0)
4111 base_image=GetImageFromList(_images,0);
4112 compare_image=GetImageFromList(_images,1);
4114 /* Comparision Metric */
4115 metric=UndefinedMetric;
4116 value=GetImageOption(_image_info,"metric");
4117 if (value != (const char *) NULL)
4118 metric=(MetricType) ParseCommandOption(MagickMetricOptions,
4121 new_images=SimilarityImage(base_image,compare_image,metric,
4122 &offset,&similarity,_exception);
4124 if ( new_images != (Image *)NULL ) {
4126 result[MaxTextExtent];
4128 (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity);
4129 (void) SetImageProperty(new_images,"subimage:similarity",result,
4131 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4133 (void) SetImageProperty(new_images,"subimage:x",result,
4135 (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
4137 (void) SetImageProperty(new_images,"subimage:y",result,
4139 (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld",
4140 (unsigned long) offset.width,(unsigned long) offset.height,
4141 (long) offset.x,(long) offset.y);
4142 (void) SetImageProperty(new_images,"subimage:offset",result,
4147 if (LocaleCompare("swap",option+1) == 0) {
4167 flags=ParseGeometry(arg1,&geometry_info);
4168 if ((flags & RhoValue) != 0)
4169 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4170 index=(ssize_t) geometry_info.rho;
4171 if ((flags & SigmaValue) != 0)
4172 swap_index=(ssize_t) geometry_info.sigma;
4174 p=GetImageFromList(_images,index);
4175 q=GetImageFromList(_images,swap_index);
4176 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4178 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4180 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4183 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
4184 swap=CloneImage(p,0,0,MagickTrue,_exception);
4185 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4186 ReplaceImageInList(&q,swap);
4187 _images=GetFirstImageInList(q);
4190 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4193 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4195 if (new_images == (Image *) NULL)
4198 if (_images != (Image *) NULL)
4199 _images=DestroyImageList(_images);
4200 _images=GetFirstImageInList(new_images);
4207 #undef _quantize_info
4214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4218 + C L I S p e c i a l O p e r a t i o n s %
4222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4224 % CLINoImageOperator() Applies operations that may not actually need images
4225 % in an image list wen it is applied.
4227 % The classic operators of this type is -read, which actually creates images
4228 % even when no images are present. Or image stack operators, which can be
4229 % applied to empty image lists.
4231 % Note: unlike other Operators, these may involve other special 'option'
4232 % character prefixes, other than simply '-' or '+'.
4234 % The format of the CLINoImageOption method is:
4236 % void CLINoImageOption(MagickCLI *cli_wand,const char *option,
4237 % const char *arg1, const char *arg2)
4239 % A description of each parameter follows:
4241 % o cli_wand: the main CLI Wand to use.
4243 % o option: The special option (with any switch char) to process
4245 % o arg1 & arg2: Argument for option, if required
4246 % Currently arg2 is not used.
4249 WandExport void CLINoImageOperator(MagickCLI *cli_wand,
4250 const char *option, const char *arg1, const char *magick_unused(arg2))
4252 #define _image_info (cli_wand->wand.image_info)
4253 #define _images (cli_wand->wand.images)
4254 #define _exception (cli_wand->wand.exception)
4255 #define IfNormalOp (*option=='-')
4256 #define IfPlusOp (*option!='-')
4258 assert(cli_wand != (MagickCLI *) NULL);
4259 assert(cli_wand->signature == WandSignature);
4260 assert(cli_wand->wand.signature == WandSignature);
4261 if (IfMagickTrue(cli_wand->wand.debug))
4262 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4265 No-op options (ignore these)
4267 if (LocaleCompare("noop",option+1) == 0) /* no argument */
4269 if (LocaleCompare("sans",option+1) == 0) /* one argument */
4271 if (LocaleCompare("sans0",option+1) == 0) /* no argument */
4273 if (LocaleCompare("sans2",option+1) == 0) /* two arguments */
4278 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4279 ( LocaleCompare("--",option) == 0 ) ) {
4281 /* Directly read 'arg1' without filename expansion handling (see below).
4283 # if !USE_WAND_METHODS
4286 if (IfMagickTrue(_image_info->ping))
4287 new_images=PingImages(_image_info,arg1,_exception);
4289 new_images=ReadImages(_image_info,arg1,_exception);
4290 AppendImageToList(&_images, new_images);
4292 /* read images using MagickWand method - no ping */
4293 /* This is not working! - it locks up in a CPU loop! */
4294 MagickSetLastIterator(&cli_wand->wand);
4295 MagickReadImage(&cli_wand->wand,arg1);
4296 MagickSetFirstIterator(&cli_wand->wand);
4299 /* Do Filename Expansion for 'arg1' then read all images.
4301 * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
4302 * (but attaching to generated argument list) any [...] read modifiers
4303 * that may be present.
4305 * For example: correctly expand '*.gif[20x20]' into a list such as
4306 * 'abc.gif[20x20', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
4308 * NOTE: In IMv6 this was done globally across all images. This
4309 * meant you could include IM options in '@filename' lists, but you
4310 * could not include comments. Doing it only for image read makes
4311 * it far more secure.
4318 argv = (char **) &arg1;
4320 /* Expand 'glob' expressions in the given filename.
4321 Expansion handles any 'coder:' prefix, or read modifiers attached
4322 to the filename, including them in the resulting expanded list.
4324 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
4325 CLIWandExceptArgReturn(ResourceLimitError,"MemoryAllocationFailed",
4326 option,GetExceptionMessage(errno));
4328 /* loop over expanded filename list, and read then all in */
4329 for (i=0; i<argc; i++) {
4333 fprintf(stderr, "DEBUG: Reading image: \"%s\"\n", argv[i]);
4335 if (IfMagickTrue(_image_info->ping))
4336 new_images=PingImages(_image_info,argv[i],_exception);
4338 new_images=ReadImages(_image_info,argv[i],_exception);
4339 AppendImageToList(&_images, new_images);
4341 argv=DestroyStringList(argv); /* Destroy the Expanded Filename list */
4347 Note: Writing a empty image list is valid in specific cases
4349 if (LocaleCompare("write",option+1) == 0) {
4359 /* Need images, unless a "null:" output coder is used */
4360 if ( cli_wand->wand.images == (Image *) NULL ) {
4361 if ( LocaleCompare(arg1,"null:") == 0 )
4363 CLIWandExceptArgReturn(OptionError,"NoImagesForWrite",option,arg1);
4366 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4367 (void) DeleteImageRegistry(key);
4368 write_images=_images;
4370 write_images=CloneImageList(_images,_exception);
4371 write_info=CloneImageInfo(_image_info);
4372 (void) WriteImages(write_info,write_images,arg1,_exception);
4373 write_info=DestroyImageInfo(write_info);
4375 write_images=DestroyImageList(write_images);
4379 Parenthesis and Brace operations
4381 if (LocaleCompare("(",option) == 0) {
4382 /* stack 'push' images */
4390 node=cli_wand->image_list_stack;
4391 for ( ; node != (Stack *)NULL; node=node->next)
4393 if ( size >= MAX_STACK_DEPTH )
4394 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
4395 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4396 if (node == (Stack *) NULL)
4397 CLIWandExceptionReturn(ResourceLimitFatalError,
4398 "MemoryAllocationFailed",option);
4399 node->data = (void *)cli_wand->wand.images;
4400 cli_wand->wand.images = NewImageList();
4401 node->next = cli_wand->image_list_stack;
4402 cli_wand->image_list_stack = node;
4404 /* handle respect-parenthesis */
4405 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4406 "respect-parenthesis"))))
4407 option="{"; /* fall-thru so as to push image settings too */
4411 if (LocaleCompare("{",option) == 0) {
4412 /* stack 'push' of image_info settings */
4420 node=cli_wand->image_info_stack;
4421 for ( ; node != (Stack *)NULL; node=node->next)
4423 if ( size >= MAX_STACK_DEPTH )
4424 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
4425 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4426 if (node == (Stack *) NULL)
4427 CLIWandExceptionReturn(ResourceLimitFatalError,
4428 "MemoryAllocationFailed",option);
4430 node->data = (void *)cli_wand->wand.image_info;
4431 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4432 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4433 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4435 cli_wand->wand.image_info = (ImageInfo *)node->data;
4436 node = (Stack *)RelinquishMagickMemory(node);
4440 node->next = cli_wand->image_info_stack;
4441 cli_wand->image_info_stack = node;
4445 if (LocaleCompare(")",option) == 0) {
4446 /* pop images from stack */
4450 node = (Stack *)cli_wand->image_list_stack;
4451 if ( node == (Stack *)NULL)
4452 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
4453 cli_wand->image_list_stack = node->next;
4455 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4456 cli_wand->wand.images= (Image *)node->data;
4457 node = (Stack *)RelinquishMagickMemory(node);
4459 /* handle respect-parenthesis - of the previous 'pushed' settings */
4460 node = cli_wand->image_info_stack;
4461 if ( node != (Stack *)NULL)
4463 if (IfMagickTrue(IsStringTrue(GetImageOption(
4464 cli_wand->wand.image_info,"respect-parenthesis"))))
4465 option="}"; /* fall-thru so as to pop image settings too */
4472 if (LocaleCompare("}",option) == 0) {
4473 /* pop image_info settings from stack */
4477 node = (Stack *)cli_wand->image_info_stack;
4478 if ( node == (Stack *)NULL)
4479 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
4480 cli_wand->image_info_stack = node->next;
4482 (void) DestroyImageInfo(cli_wand->wand.image_info);
4483 cli_wand->wand.image_info = (ImageInfo *)node->data;
4484 node = (Stack *)RelinquishMagickMemory(node);
4486 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4487 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4488 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4492 if (LocaleCompare("clone",option+1) == 0) {
4498 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4499 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
4500 if ( cli_wand->image_list_stack == (Stack *)NULL)
4501 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4502 new_images = (Image *)cli_wand->image_list_stack->data;
4503 if (new_images == (Image *) NULL)
4504 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4505 new_images=CloneImages(new_images,arg1,_exception);
4506 if (new_images == (Image *) NULL)
4507 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
4508 AppendImageToList(&_images,new_images);
4512 Informational Operations
4514 if (LocaleCompare("version",option+1) == 0) {
4515 (void) FormatLocaleFile(stdout,"Version: %s\n",
4516 GetMagickVersion((size_t *) NULL));
4517 (void) FormatLocaleFile(stdout,"Copyright: %s\n",
4518 GetMagickCopyright());
4519 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
4520 GetMagickFeatures());
4523 if (LocaleCompare("list",option+1) == 0) {
4524 /* FUTURE: This should really be built into the MagickCore
4525 It does not actually require a cli-wand or and images!
4530 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4532 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4537 case MagickCoderOptions:
4539 (void) ListCoderInfo((FILE *) NULL,_exception);
4542 case MagickColorOptions:
4544 (void) ListColorInfo((FILE *) NULL,_exception);
4547 case MagickConfigureOptions:
4549 (void) ListConfigureInfo((FILE *) NULL,_exception);
4552 case MagickDelegateOptions:
4554 (void) ListDelegateInfo((FILE *) NULL,_exception);
4557 case MagickFontOptions:
4559 (void) ListTypeInfo((FILE *) NULL,_exception);
4562 case MagickFormatOptions:
4563 (void) ListMagickInfo((FILE *) NULL,_exception);
4565 case MagickLocaleOptions:
4566 (void) ListLocaleInfo((FILE *) NULL,_exception);
4568 case MagickLogOptions:
4569 (void) ListLogInfo((FILE *) NULL,_exception);
4571 case MagickMagicOptions:
4572 (void) ListMagicInfo((FILE *) NULL,_exception);
4574 case MagickMimeOptions:
4575 (void) ListMimeInfo((FILE *) NULL,_exception);
4577 case MagickModuleOptions:
4578 (void) ListModuleInfo((FILE *) NULL,_exception);
4580 case MagickPolicyOptions:
4581 (void) ListPolicyInfo((FILE *) NULL,_exception);
4583 case MagickResourceOptions:
4584 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4586 case MagickThresholdOptions:
4587 (void) ListThresholdMaps((FILE *) NULL,_exception);
4590 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4598 // Other 'special' options this should handle
4599 // "region" "reset" "arg"
4600 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
4602 CLIWandException(OptionError,"UnrecognizedOption",option);
4612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4616 + C L I O p t i o n O p e r a t i o n s %
4620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4622 % CLIOption() Processes the given option using the given CLI Magick Wand.
4624 % If the cli_wand->command pointer is non-null, then it is assumed that the
4625 % option has already been search for up from the CommandOptions[] table in
4626 % "MagickCore/options.c" using GetCommandOptionInfo(), so that any command
4627 % specific options (such as "magick" scripting options, or "display" settings)
4628 % can be handled separatally.
4630 % The format of the CLIOption method is:
4632 % void CLIOption(MagickCLI *cli_wand,const char *option, ...)
4634 % A description of each parameter follows:
4636 % o cli_wand: the main CLI Wand to use.
4638 % o option: The special option (with any switch char) to process
4640 % o args: any required arguments for an option
4644 % CLIoption(cli_wand,"-read","rose:");
4645 % CLIoption(cli_wand,"-virtual-pixel","transparent");
4646 % CLIoption(cli_wand,"-distort","SRT:","30");
4647 % CLIoption(cli_wand,"-write","rotated_rose.png");
4650 WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
4659 assert(cli_wand != (MagickCLI *) NULL);
4660 assert(cli_wand->signature == WandSignature);
4661 assert(cli_wand->wand.signature == WandSignature);
4662 if (IfMagickTrue(cli_wand->wand.debug))
4663 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4665 if ( cli_wand->command == (const OptionInfo *) NULL )
4666 cli_wand->command = GetCommandOptionInfo(option);
4668 (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
4669 option, cli_wand->command->mnemonic );
4672 option_type=(CommandOptionFlags) cli_wand->command->flags;
4674 if ( option_type == UndefinedOptionFlag )
4675 CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
4677 assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
4679 if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
4680 CLIWandExceptionReturn(OptionFatalError,"InvalidUseOfOption",option);
4682 if ( (option_type & DeprecateOptionFlag) != 0 )
4683 CLIWandExceptionReturn(OptionError,"DeprecatedOptionNoCode",option);
4685 if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
4690 count = cli_wand->command->type;
4695 va_start(operands,option);
4699 arg1=(const char *) va_arg(operands, const char *);
4701 arg2=(const char *) va_arg(operands, const char *);
4706 (void) FormatLocaleFile(stderr,
4707 "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n",
4708 option,(long) count,option_type,arg1,arg2);
4712 cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
4716 Call the appropriate option handler
4719 /* FUTURE: this is temporary - get 'settings' to handle
4720 distribution of settings to images attributes,proprieties,artifacts */
4721 if ( cli_wand->wand.images != (Image *)NULL )
4722 SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
4723 cli_wand->wand.exception);
4725 if ( (option_type & SettingOptionFlags) != 0 ) {
4726 CLISettingOptionInfo(cli_wand, option, arg1, arg2);
4727 // FUTURE: Sync Specific Settings into Image Properities (not global)
4730 if ( (option_type & NoImageOperatorFlag) != 0)
4731 CLINoImageOperator(cli_wand, option, arg1, arg2);
4733 /* FUTURE: The not a setting part below is a temporary hack due to
4734 * some options being both a Setting and a Simple operator.
4735 * Specifically -monitor, -depth, and -colorspace */
4736 if ( cli_wand->wand.images == (Image *)NULL ) {
4737 if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
4738 ((option_type & SettingOptionFlags) == 0 )) /* temp hack */
4739 CLIWandException(OptionError,"NoImagesFound",option);
4740 return; /* on its own this is not an error */
4743 if ( (option_type & SimpleOperatorFlag) != 0)
4744 CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
4746 if ( (option_type & ListOperatorFlag) != 0 )
4747 CLIListOperatorImages(cli_wand, option, arg1, arg2);