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/operation.h"
54 #include "MagickWand/operation-private.h"
55 #include "MagickWand/wand.h"
56 #include "MagickCore/monitor-private.h"
57 #include "MagickCore/thread-private.h"
58 #include "MagickCore/string-private.h"
63 #define USE_WAND_METHODS 0
64 #define MAX_STACK_DEPTH 32
65 #define UNDEFINED_COMPRESSION_QUALITY 0UL
68 Constant declaration. (temporary exports)
71 BackgroundColor[] = "#fff", /* white */
72 BorderColor[] = "#dfdfdf", /* sRGB gray */
73 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
76 ** Function to report on the progress of image operations
78 static MagickBooleanType MonitorProgress(const char *text,
79 const MagickOffsetType offset,const MagickSizeType extent,
80 void *wand_unused(cli_wandent_data))
83 message[MaxTextExtent],
94 (void) CopyMagickMemory(tag,text,MaxTextExtent);
96 if (p != (char *) NULL)
98 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
99 locale_message=GetLocaleMessage(message);
100 if (locale_message == message)
102 if (p == (char *) NULL)
103 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
104 locale_message,(long) offset,(unsigned long) extent,(long)
105 (100L*offset/(extent-1)));
107 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
108 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
109 (100L*offset/(extent-1)));
110 if (offset == (MagickOffsetType) (extent-1))
111 (void) FormatLocaleFile(stderr,"\n");
112 (void) fflush(stderr);
117 ** GetImageCache() will read an image into a image cache if not already
118 ** present then return the image that is in the cache under that filename.
120 static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
121 ExceptionInfo *exception)
135 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
136 sans_exception=AcquireExceptionInfo();
137 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
138 sans_exception=DestroyExceptionInfo(sans_exception);
139 if (image != (Image *) NULL)
141 read_info=CloneImageInfo(image_info);
142 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
143 image=ReadImage(read_info,exception);
144 read_info=DestroyImageInfo(read_info);
145 if (image != (Image *) NULL)
146 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
151 SparseColorOption() parse the complex -sparse-color argument into an
152 an array of floating point values than call SparseColorImage().
153 Argument is a complex mix of floating-point pixel coodinates, and color
154 specifications (or direct floating point numbers). The number of floats
155 needed to represent a color varies depending on teh current channel
158 This really should be in MagickCore, so that other API's can make use of it.
160 static Image *SparseColorOption(const Image *image,
161 const SparseColorMethod method,const char *arguments,
162 ExceptionInfo *exception)
165 token[MaxTextExtent];
189 assert(image != (Image *) NULL);
190 assert(image->signature == MagickSignature);
191 if (IfMagickTrue(image->debug))
192 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
193 assert(exception != (ExceptionInfo *) NULL);
194 assert(exception->signature == MagickSignature);
196 Limit channels according to image - and add up number of color channel.
199 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
201 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
203 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
205 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
206 (image->colorspace == CMYKColorspace))
208 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
209 IfMagickTrue(image->matte))
213 Read string, to determine number of arguments needed,
219 GetMagickToken(p,&p,token);
220 if ( token[0] == ',' ) continue;
221 if ( isalpha((int) token[0]) || token[0] == '#' )
222 x += number_colors; /* color argument found */
224 x++; /* floating point argument */
226 /* control points and color values */
227 error = IsMagickTrue( x % (2+number_colors) );
229 if ( IfMagickTrue(error) ) {
230 (void) ThrowMagickException(exception,GetMagickModule(),
231 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
232 "Invalid number of Arguments");
233 return( (Image *)NULL);
236 /* Allocate and fill in the floating point arguments */
237 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
238 sizeof(*sparse_arguments));
239 if (sparse_arguments == (double *) NULL) {
240 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
241 "MemoryAllocationFailed","%s","SparseColorOption");
242 return( (Image *)NULL);
244 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
245 sizeof(*sparse_arguments));
248 while( *p != '\0' && x < number_arguments ) {
250 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
251 if ( token[0] == '\0' ) break;
252 if ( isalpha((int) token[0]) || token[0] == '#' ) {
253 (void) ThrowMagickException(exception,GetMagickModule(),
254 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
255 "Color found, instead of X-coord");
259 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
261 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
262 if ( token[0] == '\0' ) break;
263 if ( isalpha((int) token[0]) || token[0] == '#' ) {
264 (void) ThrowMagickException(exception,GetMagickModule(),
265 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
266 "Color found, instead of Y-coord");
270 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
271 /* color name or function given in string argument */
272 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
273 if ( token[0] == '\0' ) break;
274 if ( isalpha((int) token[0]) || token[0] == '#' ) {
275 /* Color string given */
276 (void) QueryColorCompliance(token,AllCompliance,&color,
278 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
279 sparse_arguments[x++] = QuantumScale*color.red;
280 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
281 sparse_arguments[x++] = QuantumScale*color.green;
282 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
283 sparse_arguments[x++] = QuantumScale*color.blue;
284 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
285 (image->colorspace == CMYKColorspace))
286 sparse_arguments[x++] = QuantumScale*color.black;
287 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
288 IfMagickTrue(image->matte))
289 sparse_arguments[x++] = QuantumScale*color.alpha;
292 /* Colors given as a set of floating point values - experimental */
293 /* NB: token contains the first floating point value to use! */
294 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
296 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
297 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
299 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
300 token[0] = ','; /* used this token - get another */
302 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
304 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
305 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
307 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
308 token[0] = ','; /* used this token - get another */
310 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
312 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
313 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
315 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
316 token[0] = ','; /* used this token - get another */
318 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
319 (image->colorspace == CMYKColorspace))
321 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
322 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
324 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
325 token[0] = ','; /* used this token - get another */
327 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
328 IfMagickTrue(image->matte))
330 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
331 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
333 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
334 token[0] = ','; /* used this token - get another */
338 if ( number_arguments != x && !error ) {
339 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
340 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
341 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
342 return( (Image *)NULL);
345 return( (Image *)NULL);
347 /* Call the Sparse Color Interpolation function with the parsed arguments */
348 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
350 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
351 return( sparse_image );
355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359 + A c q u i r e W a n d C L I %
363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365 % AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
366 % Wand). The given image_info and exception is included as is if provided.
368 % Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
371 % The format of the NewMagickWand method is:
373 % MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
374 % ExceptionInfo *exception)
377 WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
378 ExceptionInfo *exception)
383 /* precaution - as per NewMagickWand() */
385 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
386 const char *quantum = GetMagickQuantumDepth(&depth);
387 if (depth != MAGICKCORE_QUANTUM_DEPTH)
388 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
391 /* allocate memory for MgaickCLI */
392 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
393 if (cli_wand == (MagickCLI *) NULL)
395 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
396 GetExceptionMessage(errno));
397 return((MagickCLI *)NULL);
400 /* Initialize Wand Part of MagickCLI
401 FUTURE: this is a repeat of code from NewMagickWand()
402 However some parts may be given fro man external source!
404 cli_wand->wand.id=AcquireWandId();
405 (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
406 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
407 cli_wand->wand.images=NewImageList();
408 if ( image_info == (ImageInfo *)NULL)
409 cli_wand->wand.image_info=AcquireImageInfo();
411 cli_wand->wand.image_info=image_info;
412 if ( exception == (ExceptionInfo *)NULL)
413 cli_wand->wand.exception=AcquireExceptionInfo();
415 cli_wand->wand.exception=exception;
416 cli_wand->wand.debug=IsEventLogging();
417 cli_wand->wand.signature=WandSignature;
419 /* Initialize CLI Part of MagickCLI */
420 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
421 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
422 cli_wand->image_list_stack=(Stack *)NULL;
423 cli_wand->image_info_stack=(Stack *)NULL;
424 cli_wand->location="'%s'"; /* option location not known by default */
425 cli_wand->location2="'%s' '%s'";
426 cli_wand->filename=cli_wand->wand.name;
429 cli_wand->signature=WandSignature;
431 if (IfMagickTrue(cli_wand->wand.debug))
432 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441 + D e s t r o y W a n d C L I %
445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447 % DestroyMagickCLI() destorys everything in a CLI wand, including image_info
448 % and any exceptions, if still present in the wand.
450 % The format of the NewMagickWand method is:
452 % MagickWand *DestroyMagickCLI()
453 % Exception *exception)
456 WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
461 assert(cli_wand != (MagickCLI *) NULL);
462 assert(cli_wand->signature == WandSignature);
463 assert(cli_wand->wand.signature == WandSignature);
464 if (IfMagickTrue(cli_wand->wand.debug))
465 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
467 /* Destroy CLI part of MagickCLI */
468 if (cli_wand->draw_info != (DrawInfo *) NULL )
469 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
470 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
471 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
472 while(cli_wand->image_list_stack != (Stack *)NULL)
474 node=cli_wand->image_list_stack;
475 cli_wand->image_list_stack=node->next;
476 (void) DestroyImageList((Image *)node->data);
477 (void) RelinquishMagickMemory(node);
479 while(cli_wand->image_info_stack != (Stack *)NULL)
481 node=cli_wand->image_info_stack;
482 cli_wand->image_info_stack=node->next;
483 (void) DestroyImageInfo((ImageInfo *)node->data);
484 (void) RelinquishMagickMemory(node);
486 cli_wand->signature=(~WandSignature);
488 /* Destroy Wand part MagickCLI */
489 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
490 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
491 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
492 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
493 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
494 RelinquishWandId(cli_wand->wand.id);
495 cli_wand->wand.signature=(~WandSignature);
497 return((MagickCLI *)NULL);
501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505 + C L I C a t c h E x c e p t i o n %
509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511 % CLICatchException() will report exceptions, either just non-fatal warnings
512 % only, or all errors, according to 'all_execeptions' boolean argument.
514 % The function returns true is errors are fatal, in which case the caller
515 % should abort and re-call with an 'all_exceptions' argument of true before
518 % The cut-off level between fatal and non-fatal may be controlled by options
519 % (FUTURE), but defaults to 'Error' exceptions.
521 % The format of the CLICatchException method is:
523 % MagickBooleanType CLICatchException(MagickCLI *cli_wand,
524 % const MagickBooleanType all_exceptions );
527 WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
528 const MagickBooleanType all_exceptions )
532 assert(cli_wand != (MagickCLI *) NULL);
533 assert(cli_wand->signature == WandSignature);
534 assert(cli_wand->wand.signature == WandSignature);
535 if (IfMagickTrue(cli_wand->wand.debug))
536 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
538 // FUTURE: '-regard_warning' should make this more sensitive.
539 // Note pipelined options may like more control over this level
541 status = IsMagickTrue(cli_wand->wand.exception->severity > ErrorException);
543 if ( IfMagickFalse(status) || IfMagickTrue(all_exceptions) )
544 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554 + C L I S e t t i n g O p t i o n I n f o %
558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
560 % CLISettingOptionInfo() applies a single settings option into a CLI wand
561 % holding the image_info, draw_info, quantize_info structures that will be
562 % used when processing the images.
564 % These options do no require images to be present in the CLI wand for them
565 % to be able to be set, in which case they will generally be applied to image
566 % that are read in later
568 % Options handled by this function are listed in CommandOptions[] of
569 % "option.c" that is one of "SettingOptionFlags" option flags.
571 % The format of the CLISettingOptionInfo method is:
573 % void CLISettingOptionInfo(MagickCLI *cli_wand,
574 % const char *option, const char *arg1)
576 % A description of each parameter follows:
578 % o cli_wand: structure holding settings to be applied
580 % o option: The option string to be set
582 % o arg1: The single argument used to set this option.
586 % CLISettingOptionInfo(cli_wand, "-background", "Red"); // set value
587 % CLISettingOptionInfo(cli_wand, "-adjoin", NULL); // set boolean
588 % CLISettingOptionInfo(cli_wand, "+adjoin", NULL); // unset
590 % Or for handling command line arguments EG: +/-option ["arg1"]
595 % option_info = GetCommandOptionInfo(argv[i]);
596 % count=option_info->type;
597 % option_type=option_info->flags;
599 % if ( (option_type & SettingOperatorOptionFlags) != 0 )
600 % CLISettingOptionInfo(cli_wand, argv[i],
601 % (count>0) ? argv[i+1] : (char *)NULL);
605 WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
606 const char *option,const char *arg1)
609 parse; /* option argument parsing (string to value table lookup) */
611 assert(cli_wand != (MagickCLI *) NULL);
612 assert(cli_wand->signature == WandSignature);
613 assert(cli_wand->wand.signature == WandSignature);
614 if (IfMagickTrue(cli_wand->wand.debug))
615 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
617 #define _image_info (cli_wand->wand.image_info)
618 #define _exception (cli_wand->wand.exception)
619 #define _draw_info (cli_wand->draw_info)
620 #define _quantize_info (cli_wand->quantize_info)
621 #define IfSetOption (*option=='-')
622 #define ArgBoolean IsMagickTrue(IfSetOption)
623 #define ArgBooleanNot IsMagickFalse(IfSetOption)
624 #define ArgBooleanString (IfSetOption?"true":"false")
625 #define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
631 if (LocaleCompare("adjoin",option+1) == 0)
633 _image_info->adjoin = ArgBoolean;
636 if (LocaleCompare("affine",option+1) == 0)
638 /* DEPRECIATED: _draw_info setting only: for -draw and -transform */
640 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
642 GetAffineMatrix(&_draw_info->affine);
645 if (LocaleCompare("antialias",option+1) == 0)
647 _image_info->antialias =
648 _draw_info->stroke_antialias =
649 _draw_info->text_antialias = ArgBoolean;
652 if (LocaleCompare("attenuate",option+1) == 0)
654 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
655 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
656 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
659 if (LocaleCompare("authenticate",option+1) == 0)
661 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
664 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
668 if (LocaleCompare("background",option+1) == 0)
670 /* FUTURE: both _image_info attribute & ImageOption in use!
671 _image_info only used directly for generating new images.
672 SyncImageSettings() used to set per-image attribute.
674 FUTURE: if _image_info->background_color is not set then
675 we should fall back to per-image background_color
677 At this time -background will 'wipe out' the per-image
680 Better error handling of QueryColorCompliance() needed.
682 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
683 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
684 &_image_info->background_color,_exception);
687 if (LocaleCompare("bias",option+1) == 0)
689 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
690 as it is actually rarely used except in direct convolve operations
691 Usage outside a direct convolve operation is actally non-sensible!
693 SyncImageSettings() used to set per-image attribute.
695 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
696 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
697 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
700 if (LocaleCompare("black-point-compensation",option+1) == 0)
702 /* Used as a image chromaticity setting
703 SyncImageSettings() used to set per-image attribute.
705 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
708 if (LocaleCompare("blue-primary",option+1) == 0)
710 /* Image chromaticity X,Y NB: Y=X if Y not defined
711 Used by many coders including PNG
712 SyncImageSettings() used to set per-image attribute.
714 arg1=ArgOption("0.0");
715 if (IfMagickFalse(IsGeometry(arg1)))
716 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
717 (void) SetImageOption(_image_info,option+1,arg1);
720 if (LocaleCompare("bordercolor",option+1) == 0)
722 /* FUTURE: both _image_info attribute & ImageOption in use!
723 SyncImageSettings() used to set per-image attribute.
724 Better error checking of QueryColorCompliance().
728 (void) SetImageOption(_image_info,option+1,arg1);
729 (void) QueryColorCompliance(arg1,AllCompliance,
730 &_image_info->border_color,_exception);
731 (void) QueryColorCompliance(arg1,AllCompliance,
732 &_draw_info->border_color,_exception);
735 (void) DeleteImageOption(_image_info,option+1);
736 (void) QueryColorCompliance(BorderColor,AllCompliance,
737 &_image_info->border_color,_exception);
738 (void) QueryColorCompliance(BorderColor,AllCompliance,
739 &_draw_info->border_color,_exception);
742 if (LocaleCompare("box",option+1) == 0)
744 /* DEPRECIATED - now "undercolor" */
745 CLISettingOptionInfo(cli_wand,"undercolor",arg1);
748 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
752 if (LocaleCompare("cache",option+1) == 0)
757 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
758 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
759 limit=MagickResourceInfinity;
760 if (LocaleCompare("unlimited",arg1) != 0)
761 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
762 (void) SetMagickResourceLimit(MemoryResource,limit);
763 (void) SetMagickResourceLimit(MapResource,2*limit);
766 if (LocaleCompare("caption",option+1) == 0)
768 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
771 if (LocaleCompare("channel",option+1) == 0)
773 arg1=ArgOption("default");
774 parse=ParseChannelOption(arg1);
776 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
778 _image_info->channel=(ChannelType) parse;
779 (void) SetImageOption(_image_info,option+1,arg1);
782 if (LocaleCompare("colorspace",option+1) == 0)
784 /* Setting used for new images via AquireImage()
785 But also used as a SimpleImageOperator
786 Undefined colorspace means don't modify images on
787 read or as a operation */
788 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
789 ArgOption("undefined"));
791 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
793 _image_info->colorspace=(ColorspaceType) parse;
796 if (LocaleCompare("comment",option+1) == 0)
798 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
801 if (LocaleCompare("compose",option+1) == 0)
803 /* FUTURE: _image_info should be used,
804 SyncImageSettings() used to set per-image attribute. - REMOVE
806 This setting should NOT be used to set image 'compose'
807 "-layer" operators shoud use _image_info if defined otherwise
808 they should use a per-image compose setting.
810 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
811 ArgOption("undefined"));
813 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
815 _image_info->compose=(CompositeOperator) parse;
816 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
819 if (LocaleCompare("compress",option+1) == 0)
821 /* FUTURE: What should be used? _image_info or ImageOption ???
822 The former is more efficent, but Crisy prefers the latter!
823 SyncImageSettings() used to set per-image attribute.
825 The coders appears to use _image_info, not Image_Option
826 however the image attribute (for save) is set from the
829 Note that "undefined" is a different setting to "none".
831 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
832 ArgOption("undefined"));
834 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
836 _image_info->compression=(CompressionType) parse;
837 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
840 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
844 if (LocaleCompare("debug",option+1) == 0)
846 /* SyncImageSettings() used to set per-image attribute. */
847 arg1=ArgOption("none");
848 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
850 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
852 (void) SetLogEventMask(arg1);
853 _image_info->debug=IsEventLogging(); /* extract logging*/
854 cli_wand->wand.debug=IsEventLogging();
857 if (LocaleCompare("define",option+1) == 0)
859 if (LocaleNCompare(arg1,"registry:",9) == 0)
862 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
864 (void) DeleteImageRegistry(arg1+9);
867 /* DefineImageOption() equals SetImageOption() but with '=' */
869 (void) DefineImageOption(_image_info,arg1);
870 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
871 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
874 if (LocaleCompare("delay",option+1) == 0)
876 /* Only used for new images via AcquireImage()
877 FUTURE: Option should also be used for "-morph" (color morphing)
880 if (IfMagickFalse(IsGeometry(arg1)))
881 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
882 (void) SetImageOption(_image_info,option+1,arg1);
885 if (LocaleCompare("density",option+1) == 0)
887 /* FUTURE: strings used in _image_info attr and _draw_info!
888 Basically as density can be in a XxY form!
890 SyncImageSettings() used to set per-image attribute.
892 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
893 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
894 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
895 (void) CloneString(&_image_info->density,ArgOption(NULL));
896 (void) CloneString(&_draw_info->density,_image_info->density);
899 if (LocaleCompare("depth",option+1) == 0)
901 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
902 SyncImageSettings() used to set per-image attribute.
904 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
905 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
906 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
907 :MAGICKCORE_QUANTUM_DEPTH;
910 if (LocaleCompare("direction",option+1) == 0)
912 /* Image Option is only used to set _draw_info */
913 arg1=ArgOption("undefined");
914 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
916 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
918 _draw_info->direction=(DirectionType) parse;
919 (void) SetImageOption(_image_info,option+1,arg1);
922 if (LocaleCompare("display",option+1) == 0)
924 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
925 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
928 if (LocaleCompare("dispose",option+1) == 0)
930 /* only used in setting new images */
931 arg1=ArgOption("undefined");
932 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
934 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
936 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
939 if (LocaleCompare("dither",option+1) == 0)
941 /* _image_info attr (on/off), _quantize_info attr (on/off)
942 but also ImageInfo and _quantize_info method!
943 FUTURE: merge the duality of the dithering options
945 _image_info->dither = _quantize_info->dither = ArgBoolean;
946 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
947 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
948 MagickDitherOptions,MagickFalse,ArgOption("none"));
949 if (_quantize_info->dither_method == NoDitherMethod)
950 _image_info->dither = _quantize_info->dither = MagickFalse;
953 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
957 if (LocaleCompare("encoding",option+1) == 0)
959 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
960 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
963 if (LocaleCompare("endian",option+1) == 0)
965 /* Both _image_info attr and ImageInfo */
966 arg1 = ArgOption("undefined");
967 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
969 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
971 /* FUTURE: check alloc/free of endian string! - remove? */
972 _image_info->endian=(EndianType) (*arg1);
973 (void) SetImageOption(_image_info,option+1,arg1);
976 if (LocaleCompare("extract",option+1) == 0)
978 (void) CloneString(&_image_info->extract,ArgOption(NULL));
981 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
985 if (LocaleCompare("family",option+1) == 0)
987 (void) CloneString(&_draw_info->family,ArgOption(NULL));
990 if (LocaleCompare("fill",option+1) == 0)
992 /* Set "fill" OR "fill-pattern" in _draw_info
993 The original fill color is preserved if a fill-pattern is given.
994 That way it does not effect other operations that directly using
995 the fill color and, can be retored using "+tile".
1006 arg1 = ArgOption("none"); /* +fill turns it off! */
1007 (void) SetImageOption(_image_info,option+1,arg1);
1008 if (_draw_info->fill_pattern != (Image *) NULL)
1009 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
1011 /* is it a color or a image? -- ignore exceptions */
1012 sans=AcquireExceptionInfo();
1013 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
1014 sans=DestroyExceptionInfo(sans);
1016 if (IfMagickFalse(status))
1017 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
1019 _draw_info->fill=color;
1022 if (LocaleCompare("filter",option+1) == 0)
1024 /* SyncImageSettings() used to set per-image attribute. */
1025 arg1 = ArgOption("undefined");
1026 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
1028 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
1030 (void) SetImageOption(_image_info,option+1,arg1);
1033 if (LocaleCompare("font",option+1) == 0)
1035 (void) CloneString(&_draw_info->font,ArgOption(NULL));
1036 (void) CloneString(&_image_info->font,_draw_info->font);
1039 if (LocaleCompare("format",option+1) == 0)
1041 /* FUTURE: why the ping test, you could set ping after this! */
1046 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
1047 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
1048 _image_info->ping=MagickFalse;
1050 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1053 if (LocaleCompare("fuzz",option+1) == 0)
1055 /* Option used to set image fuzz! unless blank canvas (from color)
1056 Image attribute used for color compare operations
1057 SyncImageSettings() used to set per-image attribute.
1059 FUTURE: Can't find anything else using _image_info->fuzz directly!
1060 remove direct sttribute from image_info
1062 arg1=ArgOption("0");
1063 if (IfMagickFalse(IsGeometry(arg1)))
1064 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1065 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
1067 (void) SetImageOption(_image_info,option+1,arg1);
1070 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1074 if (LocaleCompare("gravity",option+1) == 0)
1076 /* SyncImageSettings() used to set per-image attribute. */
1077 arg1 = ArgOption("none");
1078 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
1080 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
1082 _draw_info->gravity=(GravityType) parse;
1083 (void) SetImageOption(_image_info,option+1,arg1);
1086 if (LocaleCompare("green-primary",option+1) == 0)
1088 /* Image chromaticity X,Y NB: Y=X if Y not defined
1089 SyncImageSettings() used to set per-image attribute.
1090 Used directly by many coders
1092 arg1=ArgOption("0.0");
1093 if (IfMagickFalse(IsGeometry(arg1)))
1094 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1095 (void) SetImageOption(_image_info,option+1,arg1);
1098 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1102 if (LocaleCompare("intent",option+1) == 0)
1104 /* Only used by coders: MIFF, MPC, BMP, PNG
1105 and for image profile call to AcquireTransformThreadSet()
1106 SyncImageSettings() used to set per-image attribute.
1108 arg1 = ArgOption("indefined");
1109 parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
1111 CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
1113 (void) SetImageOption(_image_info,option+1,arg1);
1116 if (LocaleCompare("interlace",option+1) == 0)
1118 /* _image_info is directly used by coders (so why an image setting?)
1119 SyncImageSettings() used to set per-image attribute.
1121 arg1 = ArgOption("undefined");
1122 parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
1124 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
1126 _image_info->interlace=(InterlaceType) parse;
1127 (void) SetImageOption(_image_info,option+1,arg1);
1130 if (LocaleCompare("interline-spacing",option+1) == 0)
1132 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1133 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1134 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1135 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
1139 if (LocaleCompare("interpolate",option+1) == 0)
1141 /* SyncImageSettings() used to set per-image attribute. */
1142 arg1 = ArgOption("undefined");
1143 parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
1145 CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
1147 (void) SetImageOption(_image_info,option+1,arg1);
1150 if (LocaleCompare("interword-spacing",option+1) == 0)
1152 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1153 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1154 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1155 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
1158 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1162 if (LocaleCompare("kerning",option+1) == 0)
1164 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1165 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1166 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1167 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
1170 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1174 if (LocaleCompare("label",option+1) == 0)
1176 /* only used for new images - not in SyncImageOptions() */
1177 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1180 if (LocaleCompare("log",option+1) == 0)
1183 if ((strchr(arg1,'%') == (char *) NULL))
1184 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1185 (void) SetLogFormat(arg1);
1189 if (LocaleCompare("loop",option+1) == 0)
1191 /* SyncImageSettings() used to set per-image attribute. */
1192 arg1=ArgOption("0");
1193 if (IfMagickFalse(IsGeometry(arg1)))
1194 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1195 (void) SetImageOption(_image_info,option+1,arg1);
1198 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1202 if (LocaleCompare("mattecolor",option+1) == 0)
1204 /* SyncImageSettings() used to set per-image attribute. */
1205 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1206 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
1207 &_image_info->matte_color,_exception);
1210 if (LocaleCompare("monitor",option+1) == 0)
1212 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
1213 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
1216 if (LocaleCompare("monochrome",option+1) == 0)
1218 /* Setting (used by some input coders!) -- why?
1219 Warning: This is also Special '-type' SimpleOperator
1221 _image_info->monochrome= ArgBoolean;
1224 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1228 if (LocaleCompare("orient",option+1) == 0)
1230 /* Is not used when defining for new images.
1231 This makes it more of a 'operation' than a setting
1232 FUTURE: make set meta-data operator instead.
1233 SyncImageSettings() used to set per-image attribute.
1235 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1236 ArgOption("undefined"));
1238 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1240 _image_info->orientation=(OrientationType)parse;
1241 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1244 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1248 if (LocaleCompare("page",option+1) == 0)
1250 /* Only used for new images and image generators.
1251 SyncImageSettings() used to set per-image attribute. ?????
1252 That last is WRONG!!!!
1253 FUTURE: adjust named 'page' sizes according density
1257 page[MaxTextExtent];
1270 (void) DeleteImageOption(_image_info,option+1);
1271 (void) CloneString(&_image_info->page,(char *) NULL);
1274 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1275 image_option=GetImageOption(_image_info,"page");
1276 if (image_option != (const char *) NULL)
1277 flags=ParseAbsoluteGeometry(image_option,&geometry);
1278 canonical_page=GetPageGeometry(arg1);
1279 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1280 canonical_page=DestroyString(canonical_page);
1281 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1282 (unsigned long) geometry.width,(unsigned long) geometry.height);
1283 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1284 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1285 (unsigned long) geometry.width,(unsigned long) geometry.height,
1286 (long) geometry.x,(long) geometry.y);
1287 (void) SetImageOption(_image_info,option+1,page);
1288 (void) CloneString(&_image_info->page,page);
1291 if (LocaleCompare("ping",option+1) == 0)
1293 _image_info->ping = ArgBoolean;
1296 if (LocaleCompare("pointsize",option+1) == 0)
1299 if (IfMagickFalse(IsGeometry(arg1)))
1300 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1301 _image_info->pointsize =
1302 _draw_info->pointsize =
1303 StringToDouble(arg1,(char **) NULL);
1306 _image_info->pointsize=0.0; /* unset pointsize */
1307 _draw_info->pointsize=12.0;
1311 if (LocaleCompare("precision",option+1) == 0)
1313 arg1=ArgOption("-1");
1314 if (IfMagickFalse(IsGeometry(arg1)))
1315 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1316 (void) SetMagickPrecision(StringToInteger(arg1));
1319 /* FUTURE: Only the 'preview' coder appears to use this
1320 * DEPRECIATE the coder? Leaving only the 'preview' operator.
1321 if (LocaleCompare("preview",option+1) == 0)
1323 _image_info->preview_type=UndefinedPreview;
1325 _image_info->preview_type=(PreviewType) ParseCommandOption(
1326 MagickPreviewOptions,MagickFalse,arg1);
1330 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1334 if (LocaleCompare("quality",option+1) == 0)
1336 if (IfMagickFalse(IsGeometry(arg1)))
1337 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1338 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1339 : UNDEFINED_COMPRESSION_QUALITY;
1340 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1343 if (LocaleCompare("quantize",option+1) == 0)
1345 /* Just a set direct in _quantize_info */
1346 arg1=ArgOption("undefined");
1347 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1349 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1351 _quantize_info->colorspace=(ColorspaceType)parse;
1354 if (LocaleCompare("quiet",option+1) == 0)
1356 /* FUTURE: if two -quiet is performed you can not do +quiet!
1357 This needs to be checked over thoughly.
1359 static WarningHandler
1360 warning_handler = (WarningHandler) NULL;
1363 tmp = SetWarningHandler((WarningHandler) NULL);
1365 if ( tmp != (WarningHandler) NULL)
1366 warning_handler = tmp; /* remember the old handler */
1367 if (!IfSetOption) /* set the old handler */
1368 warning_handler=SetWarningHandler(warning_handler);
1371 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1375 if (LocaleCompare("red-primary",option+1) == 0)
1377 /* Image chromaticity X,Y NB: Y=X if Y not defined
1379 SyncImageSettings() used to set per-image attribute.
1381 arg1=ArgOption("0.0");
1382 if (IfMagickFalse(IsGeometry(arg1)))
1383 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1384 (void) SetImageOption(_image_info,option+1,arg1);
1387 if (LocaleCompare("render",option+1) == 0)
1389 /* _draw_info only setting */
1390 _draw_info->render= ArgBooleanNot;
1393 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1397 if (LocaleCompare("sampling-factor",option+1) == 0)
1399 /* FUTURE: should be converted to jpeg:sampling_factor */
1400 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1401 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1402 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
1405 if (LocaleCompare("scene",option+1) == 0)
1407 /* SyncImageSettings() used to set this as a per-image attribute.
1410 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1411 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1412 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1413 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
1416 if (LocaleCompare("seed",option+1) == 0)
1418 if (IfMagickFalse(IsGeometry(arg1)))
1419 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1420 SeedPseudoRandomGenerator(
1421 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
1422 : (size_t) time((time_t *) NULL) );
1425 if (LocaleCompare("size",option+1) == 0)
1427 /* FUTURE: string in _image_info -- convert to Option ???
1428 Look at the special handling for "size" in SetImageOption()
1430 (void) CloneString(&_image_info->size,ArgOption(NULL));
1433 if (LocaleCompare("stretch",option+1) == 0)
1435 arg1=ArgOption("undefined");
1436 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1438 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1440 _draw_info->stretch=(StretchType) parse;
1443 if (LocaleCompare("stroke",option+1) == 0)
1445 /* set stroke color OR stroke-pattern
1446 UPDATE: ensure stroke color is not destroyed is a pattern
1447 is given. Just in case the color is also used for other purposes.
1458 arg1 = ArgOption("none"); /* +fill turns it off! */
1459 (void) SetImageOption(_image_info,option+1,arg1);
1460 if (_draw_info->stroke_pattern != (Image *) NULL)
1461 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
1463 /* is it a color or a image? -- ignore exceptions */
1464 sans=AcquireExceptionInfo();
1465 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
1466 sans=DestroyExceptionInfo(sans);
1468 if (IfMagickFalse(status))
1469 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
1471 _draw_info->stroke=color;
1474 if (LocaleCompare("strokewidth",option+1) == 0)
1476 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1477 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1478 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1479 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1483 if (LocaleCompare("style",option+1) == 0)
1485 arg1=ArgOption("undefined");
1486 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1488 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1490 _draw_info->style=(StyleType) parse;
1493 if (LocaleCompare("synchronize",option+1) == 0)
1495 /* FUTURE: syncronize to storage - but what does that mean? */
1496 _image_info->synchronize = ArgBoolean;
1499 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1503 if (LocaleCompare("taint",option+1) == 0)
1505 /* SyncImageSettings() used to set per-image attribute. */
1506 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1509 if (LocaleCompare("texture",option+1) == 0)
1511 /* FUTURE: move _image_info string to option splay-tree
1512 Other than "montage" what uses "texture" ????
1514 (void) CloneString(&_image_info->texture,ArgOption(NULL));
1517 if (LocaleCompare("tile",option+1) == 0)
1519 _draw_info->fill_pattern=IfSetOption
1520 ?GetImageCache(_image_info,arg1,_exception)
1521 :DestroyImage(_draw_info->fill_pattern);
1524 if (LocaleCompare("tile-offset",option+1) == 0)
1526 /* SyncImageSettings() used to set per-image attribute. ??? */
1527 arg1=ArgOption("0");
1528 if (IfMagickFalse(IsGeometry(arg1)))
1529 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1530 (void) SetImageOption(_image_info,option+1,arg1);
1533 if (LocaleCompare("transparent-color",option+1) == 0)
1535 /* FUTURE: both _image_info attribute & ImageOption in use!
1536 _image_info only used for generating new images.
1537 SyncImageSettings() used to set per-image attribute.
1539 Note that +transparent-color, means fall-back to image
1540 attribute so ImageOption is deleted, not set to a default.
1542 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
1543 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1544 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1545 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1546 &_image_info->transparent_color,_exception);
1549 if (LocaleCompare("treedepth",option+1) == 0)
1551 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1552 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1555 if (LocaleCompare("type",option+1) == 0)
1557 /* SyncImageSettings() used to set per-image attribute. */
1558 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1559 ArgOption("undefined"));
1561 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1563 _image_info->type=(ImageType) parse;
1564 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1567 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1571 if (LocaleCompare("undercolor",option+1) == 0)
1573 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1574 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1575 &_draw_info->undercolor,_exception);
1578 if (LocaleCompare("units",option+1) == 0)
1580 /* SyncImageSettings() used to set per-image attribute.
1581 Should this effect _draw_info X and Y resolution?
1582 FUTURE: this probably should be part of the density setting
1584 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1585 ArgOption("undefined"));
1587 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1589 _image_info->units=(ResolutionType) parse;
1590 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1593 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1597 if (LocaleCompare("verbose",option+1) == 0)
1599 /* FUTURE: Remember all options become image artifacts
1600 _image_info->verbose is only used by coders.
1602 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1603 _image_info->verbose= ArgBoolean;
1604 _image_info->ping=MagickFalse; /* verbose can't be a ping */
1607 if (LocaleCompare("view",option+1) == 0)
1609 /* FUTURE: Convert from _image_info to ImageOption
1610 Only used by coder FPX
1611 And it only tests existance, not its content!
1613 (void) CloneString(&_image_info->view,ArgOption(NULL));
1616 if (LocaleCompare("virtual-pixel",option+1) == 0)
1618 /* SyncImageSettings() used to set per-image attribute.
1619 This is VERY deep in the image caching structure.
1621 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1622 ArgOption("undefined"));
1624 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1626 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1629 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1633 if (LocaleCompare("weight",option+1) == 0)
1635 /* Just what does using a font 'weight' do ???
1636 There is no "-list weight" output (reference manual says there is)
1638 arg1=ArgOption("all");
1639 _draw_info->weight=StringToUnsignedLong(arg1);
1640 if (LocaleCompare(arg1,"all") == 0)
1641 _draw_info->weight=0;
1642 if (LocaleCompare(arg1,"bold") == 0)
1643 _draw_info->weight=700;
1644 if (LocaleCompare(arg1,"bolder") == 0)
1645 if (_draw_info->weight <= 800)
1646 _draw_info->weight+=100;
1647 if (LocaleCompare(arg1,"lighter") == 0)
1648 if (_draw_info->weight >= 100)
1649 _draw_info->weight-=100;
1650 if (LocaleCompare(arg1,"normal") == 0)
1651 _draw_info->weight=400;
1654 if (LocaleCompare("white-point",option+1) == 0)
1656 /* Used as a image chromaticity setting
1657 SyncImageSettings() used to set per-image attribute.
1659 arg1=ArgOption("0.0");
1660 if (IfMagickFalse(IsGeometry(arg1)))
1661 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1662 (void) SetImageOption(_image_info,option+1,arg1);
1665 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1668 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1674 #undef _quantize_info
1677 #undef ArgBooleanNot
1678 #undef ArgBooleanString
1685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1689 + C L I S i m p l e O p e r a t o r I m a g e s %
1693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1695 % WandSimpleOperatorImages() applys one simple image operation given to all
1696 % the images in the CLI wand, with the settings that was previously saved in
1699 % It is assumed that any per-image settings are up-to-date with respect to
1700 % extra settings that were already saved in the wand.
1702 % The format of the WandSimpleOperatorImage method is:
1704 % void CLISimpleOperatorImages(MagickCLI *cli_wand,
1705 % const char *option, const char *arg1, const char *arg2)
1707 % A description of each parameter follows:
1709 % o cli_wand: structure holding settings and images to be operated on
1711 % o option: The option string for the operation
1713 % o arg1, arg2: optional argument strings to the operation
1715 % Any problems will be added to the 'exception' entry of the given wand.
1719 % CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1720 % CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1721 % CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
1723 % Or for handling command line arguments EG: +/-option ["arg1"]
1729 % option_info = GetCommandOptionInfo(argv[i]);
1730 % count=option_info->type;
1731 % option_type=option_info->flags;
1733 % if ( (option_type & SimpleOperatorOptionFlag) != 0 )
1734 % CLISimpleOperatorImages(cli_wand, argv[i],
1735 % count>=1 ? argv[i+1] : (char *)NULL,
1736 % count>=2 ? argv[i+2] : (char *)NULL );
1742 Internal subrountine to apply one simple image operation to the current
1743 image pointed to by the CLI wand.
1745 The image in the list may be modified in three different ways...
1746 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1747 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1748 * one image replace by a list of images (-separate and -crop only!)
1750 In each case the result replaces the single original image in the list, as
1751 well as the pointer to the modified image (last image added if replaced by a
1752 list of images) is returned.
1754 As the image pointed to may be replaced, the first image in the list may
1755 also change. GetFirstImageInList() should be used by caller if they wish
1756 return the Image pointer to the first image in list.
1758 static void CLISimpleOperatorImage(MagickCLI *cli_wand,
1759 const char *option, const char *arg1, const char *arg2)
1776 #define _image_info (cli_wand->wand.image_info)
1777 #define _image (cli_wand->wand.images)
1778 #define _exception (cli_wand->wand.exception)
1779 #define _draw_info (cli_wand->draw_info)
1780 #define _quantize_info (cli_wand->quantize_info)
1781 #define IfNormalOp (*option=='-')
1782 #define IfPlusOp (*option!='-')
1783 #define normal_op IsMagickTrue(IfNormalOp)
1784 #define plus_alt_op IsMagickFalse(IfNormalOp)
1786 assert(cli_wand != (MagickCLI *) NULL);
1787 assert(cli_wand->signature == WandSignature);
1788 assert(cli_wand->wand.signature == WandSignature);
1789 assert(_image != (Image *) NULL); /* an image must be present */
1790 if (IfMagickTrue(cli_wand->wand.debug))
1791 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
1793 (void) SyncImageSettings(_image_info,_image,_exception);
1795 SetGeometryInfo(&geometry_info);
1797 new_image = (Image *)NULL; /* the replacement image, if not null at end */
1799 /* FUTURE: We may need somthing a little more optimized than this!
1800 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1802 switch (*(option+1))
1806 if (LocaleCompare("adaptive-blur",option+1) == 0)
1808 if (IfMagickFalse(IsGeometry(arg1)))
1809 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1810 flags=ParseGeometry(arg1,&geometry_info);
1811 if ((flags & SigmaValue) == 0)
1812 geometry_info.sigma=1.0;
1813 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1814 geometry_info.sigma,_exception);
1817 if (LocaleCompare("adaptive-resize",option+1) == 0)
1819 /* FUTURE: Roll into a resize special operator */
1820 if (IfMagickFalse(IsGeometry(arg1)))
1821 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1822 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1823 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1827 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
1829 if (IfMagickFalse(IsGeometry(arg1)))
1830 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1831 flags=ParseGeometry(arg1,&geometry_info);
1832 if ((flags & SigmaValue) == 0)
1833 geometry_info.sigma=1.0;
1834 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1835 geometry_info.sigma,_exception);
1838 if (LocaleCompare("alpha",option+1) == 0)
1840 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1842 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1844 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1848 if (LocaleCompare("annotate",option+1) == 0)
1852 geometry[MaxTextExtent];
1854 if (IfMagickFalse(IsGeometry(arg1)))
1855 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1856 SetGeometryInfo(&geometry_info);
1857 flags=ParseGeometry(arg1,&geometry_info);
1858 if ((flags & SigmaValue) == 0)
1859 geometry_info.sigma=geometry_info.rho;
1860 text=InterpretImageProperties(_image_info,_image,arg2,
1862 if (text == (char *) NULL)
1864 (void) CloneString(&_draw_info->text,text);
1865 text=DestroyString(text);
1866 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1867 geometry_info.xi,geometry_info.psi);
1868 (void) CloneString(&_draw_info->geometry,geometry);
1869 _draw_info->affine.sx=cos(DegreesToRadians(
1870 fmod(geometry_info.rho,360.0)));
1871 _draw_info->affine.rx=sin(DegreesToRadians(
1872 fmod(geometry_info.rho,360.0)));
1873 _draw_info->affine.ry=(-sin(DegreesToRadians(
1874 fmod(geometry_info.sigma,360.0))));
1875 _draw_info->affine.sy=cos(DegreesToRadians(
1876 fmod(geometry_info.sigma,360.0)));
1877 (void) AnnotateImage(_image,_draw_info,_exception);
1878 GetAffineMatrix(&_draw_info->affine);
1881 if (LocaleCompare("auto-gamma",option+1) == 0)
1883 (void) AutoGammaImage(_image,_exception);
1886 if (LocaleCompare("auto-level",option+1) == 0)
1888 (void) AutoLevelImage(_image,_exception);
1891 if (LocaleCompare("auto-orient",option+1) == 0)
1893 /* This should probably be a MagickCore function */
1894 switch (_image->orientation)
1896 case TopRightOrientation:
1898 new_image=FlopImage(_image,_exception);
1901 case BottomRightOrientation:
1903 new_image=RotateImage(_image,180.0,_exception);
1906 case BottomLeftOrientation:
1908 new_image=FlipImage(_image,_exception);
1911 case LeftTopOrientation:
1913 new_image=TransposeImage(_image,_exception);
1916 case RightTopOrientation:
1918 new_image=RotateImage(_image,90.0,_exception);
1921 case RightBottomOrientation:
1923 new_image=TransverseImage(_image,_exception);
1926 case LeftBottomOrientation:
1928 new_image=RotateImage(_image,270.0,_exception);
1934 if (new_image != (Image *) NULL)
1935 new_image->orientation=TopLeftOrientation;
1938 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
1942 if (LocaleCompare("black-threshold",option+1) == 0)
1944 if (IfMagickFalse(IsGeometry(arg1)))
1945 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1946 (void) BlackThresholdImage(_image,arg1,_exception);
1949 if (LocaleCompare("blue-shift",option+1) == 0)
1951 geometry_info.rho=1.5;
1953 if (IfMagickFalse(IsGeometry(arg1)))
1954 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1955 flags=ParseGeometry(arg1,&geometry_info);
1957 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
1960 if (LocaleCompare("blur",option+1) == 0)
1962 if (IfMagickFalse(IsGeometry(arg1)))
1963 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1964 flags=ParseGeometry(arg1,&geometry_info);
1965 if ((flags & SigmaValue) == 0)
1966 geometry_info.sigma=1.0;
1967 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1971 if (LocaleCompare("border",option+1) == 0)
1979 if (IfMagickFalse(IsGeometry(arg1)))
1980 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1982 value=GetImageOption(_image_info,"compose");
1983 if (value != (const char *) NULL)
1984 compose=(CompositeOperator) ParseCommandOption(
1985 MagickComposeOptions,MagickFalse,value);
1987 compose=OverCompositeOp; /* use Over not _image->compose */
1989 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
1990 if ((flags & SigmaValue) == 0)
1991 geometry.height=geometry.width;
1992 new_image=BorderImage(_image,&geometry,compose,_exception);
1995 if (LocaleCompare("brightness-contrast",option+1) == 0)
2007 if (IfMagickFalse(IsGeometry(arg1)))
2008 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2009 flags=ParseGeometry(arg1,&geometry_info);
2010 brightness=geometry_info.rho;
2012 if ((flags & SigmaValue) != 0)
2013 contrast=geometry_info.sigma;
2014 (void) BrightnessContrastImage(_image,brightness,contrast,
2018 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2022 if (LocaleCompare("cdl",option+1) == 0)
2025 *color_correction_collection;
2028 Color correct with a color decision list.
2030 color_correction_collection=FileToString(arg1,~0,_exception);
2031 if (color_correction_collection == (char *) NULL)
2033 (void) ColorDecisionListImage(_image,color_correction_collection,
2037 if (LocaleCompare("charcoal",option+1) == 0)
2039 if (IfMagickFalse(IsGeometry(arg1)))
2040 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2041 flags=ParseGeometry(arg1,&geometry_info);
2042 if ((flags & SigmaValue) == 0)
2043 geometry_info.sigma=1.0;
2044 if ((flags & XiValue) == 0)
2045 geometry_info.xi=1.0;
2046 new_image=CharcoalImage(_image,geometry_info.rho,
2047 geometry_info.sigma,_exception);
2050 if (LocaleCompare("chop",option+1) == 0)
2052 if (IfMagickFalse(IsGeometry(arg1)))
2053 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2054 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
2055 new_image=ChopImage(_image,&geometry,_exception);
2058 if (LocaleCompare("clamp",option+1) == 0)
2060 (void) ClampImage(_image,_exception);
2063 if (LocaleCompare("clip",option+1) == 0)
2066 (void) ClipImage(_image,_exception);
2067 else /* "+mask" remove the write mask */
2068 (void) SetImageMask(_image,(Image *) NULL,_exception);
2071 if (LocaleCompare("clip-mask",option+1) == 0)
2089 /* "+clip-mask" Remove the write mask */
2090 (void) SetImageMask(_image,(Image *) NULL,_exception);
2093 mask_image=GetImageCache(_image_info,arg1,_exception);
2094 if (mask_image == (Image *) NULL)
2096 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
2098 /* Create a write mask from cli_wand mask image */
2099 /* FUTURE: use Alpha operations instead and create a Grey Image */
2100 mask_view=AcquireCacheView(mask_image);
2101 for (y=0; y < (ssize_t) mask_image->rows; y++)
2103 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
2105 if (q == (Quantum *) NULL)
2107 for (x=0; x < (ssize_t) mask_image->columns; x++)
2109 if (IfMagickFalse(mask_image->matte))
2110 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2111 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2112 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2113 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2114 q+=GetPixelChannels(mask_image);
2116 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
2119 /* clean up and set the write mask */
2120 mask_view=DestroyCacheView(mask_view);
2121 mask_image->matte=MagickTrue;
2122 (void) SetImageMask(_image,mask_image,_exception);
2123 mask_image=DestroyImage(mask_image);
2126 if (LocaleCompare("clip-path",option+1) == 0)
2128 (void) ClipImagePath(_image,arg1,normal_op,_exception);
2131 if (LocaleCompare("colorize",option+1) == 0)
2133 if (IfMagickFalse(IsGeometry(arg1)))
2134 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2135 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
2138 if (LocaleCompare("color-matrix",option+1) == 0)
2143 kernel=AcquireKernelInfo(arg1);
2144 if (kernel == (KernelInfo *) NULL)
2145 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2146 new_image=ColorMatrixImage(_image,kernel,_exception);
2147 kernel=DestroyKernelInfo(kernel);
2150 if (LocaleCompare("colors",option+1) == 0)
2152 /* Reduce the number of colors in the image.
2153 FUTURE: also provide 'plus version with image 'color counts'
2155 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2156 if (_quantize_info->number_colors == 0)
2157 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2158 if ((_image->storage_class == DirectClass) ||
2159 _image->colors > _quantize_info->number_colors)
2160 (void) QuantizeImage(_quantize_info,_image,_exception);
2162 (void) CompressImageColormap(_image,_exception);
2165 if (LocaleCompare("colorspace",option+1) == 0)
2167 /* WARNING: this is both a image_info setting (already done)
2168 and a operator to change image colorspace.
2170 FUTURE: default colorspace should be sRGB!
2171 Unless some type of 'linear colorspace' mode is set.
2173 Note that +colorspace sets "undefined" or no effect on
2174 new images, but forces images already in memory back to RGB!
2175 That seems to be a little strange!
2177 (void) TransformImageColorspace(_image,
2178 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2182 if (LocaleCompare("contrast",option+1) == 0)
2184 /* DEPRECIATED: The -/+level provides far more controlled form */
2185 (void) ContrastImage(_image,normal_op,_exception);
2188 if (LocaleCompare("contrast-stretch",option+1) == 0)
2197 if (IfMagickFalse(IsGeometry(arg1)))
2198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2199 flags=ParseGeometry(arg1,&geometry_info);
2200 black_point=geometry_info.rho;
2201 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2203 if ((flags & PercentValue) != 0) {
2204 black_point*=(double) _image->columns*_image->rows/100.0;
2205 white_point*=(double) _image->columns*_image->rows/100.0;
2207 white_point=(MagickRealType) _image->columns*_image->rows-
2209 (void) ContrastStretchImage(_image,black_point,white_point,
2213 if (LocaleCompare("convolve",option+1) == 0)
2218 kernel_info=AcquireKernelInfo(arg1);
2219 if (kernel_info == (KernelInfo *) NULL)
2220 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2221 /* kernel_info->bias=_image->bias; -- FUTURE: check this path! */
2222 new_image=ConvolveImage(_image,kernel_info,_exception);
2223 kernel_info=DestroyKernelInfo(kernel_info);
2226 if (LocaleCompare("crop",option+1) == 0)
2228 /* WARNING: This can generate multiple images! */
2229 if (IfMagickFalse(IsGeometry(arg1)))
2230 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2231 new_image=CropImageToTiles(_image,arg1,_exception);
2234 if (LocaleCompare("cycle",option+1) == 0)
2236 if (IfMagickFalse(IsGeometry(arg1)))
2237 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2238 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2242 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2246 if (LocaleCompare("decipher",option+1) == 0)
2251 passkey=FileToStringInfo(arg1,~0,_exception);
2252 if (passkey == (StringInfo *) NULL)
2253 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2255 (void) PasskeyDecipherImage(_image,passkey,_exception);
2256 passkey=DestroyStringInfo(passkey);
2259 if (LocaleCompare("depth",option+1) == 0)
2261 /* The _image_info->depth setting has already been set
2262 We just need to apply it to all images in current sequence
2264 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2265 That is it really is an operation, not a setting! Arrgghhh
2267 FUTURE: this should not be an operator!!!
2269 (void) SetImageDepth(_image,_image_info->depth,_exception);
2272 if (LocaleCompare("deskew",option+1) == 0)
2278 if (IfMagickFalse(IsGeometry(arg1)))
2279 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2280 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
2283 threshold=40.0*QuantumRange/100.0;
2284 new_image=DeskewImage(_image,threshold,_exception);
2287 if (LocaleCompare("despeckle",option+1) == 0)
2289 new_image=DespeckleImage(_image,_exception);
2292 if (LocaleCompare("distort",option+1) == 0)
2296 token[MaxTextExtent];
2310 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2312 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2314 if ((DistortImageMethod) parse == ResizeDistortion)
2318 /* Special Case - Argument is actually a resize geometry!
2319 ** Convert that to an appropriate distortion argument array.
2320 ** FUTURE: make a separate special resize operator
2321 Roll into a resize special operator */
2322 if (IfMagickFalse(IsGeometry(arg2)))
2323 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2325 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
2326 resize_args[0]=(double) geometry.width;
2327 resize_args[1]=(double) geometry.height;
2328 new_image=DistortImage(_image,(DistortImageMethod) parse,
2329 (size_t)2,resize_args,MagickTrue,_exception);
2332 /* handle percent arguments */
2333 args=InterpretImageProperties(_image_info,_image,arg2,_exception);
2334 if (args == (char *) NULL)
2336 /* convert arguments into an array of doubles
2337 FUTURE: make this a separate function.
2338 Also make use of new 'sentinal' feature to avoid need for
2342 for (x=0; *p != '\0'; x++)
2344 GetMagickToken(p,&p,token);
2346 GetMagickToken(p,&p,token);
2348 number_arguments=(size_t) x;
2349 arguments=(double *) AcquireQuantumMemory(number_arguments,
2350 sizeof(*arguments));
2351 if (arguments == (double *) NULL)
2352 CLIWandExceptionBreak(ResourceLimitFatalError,
2353 "MemoryAllocationFailed",option);
2354 (void) ResetMagickMemory(arguments,0,number_arguments*
2355 sizeof(*arguments));
2357 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2359 GetMagickToken(p,&p,token);
2361 GetMagickToken(p,&p,token);
2362 arguments[x]=StringToDouble(token,(char **) NULL);
2364 args=DestroyString(args);
2365 new_image=DistortImage(_image,(DistortImageMethod) parse,
2366 number_arguments,arguments,plus_alt_op,_exception);
2367 arguments=(double *) RelinquishMagickMemory(arguments);
2370 if (LocaleCompare("draw",option+1) == 0)
2372 (void) CloneString(&_draw_info->primitive,arg1);
2373 (void) DrawImage(_image,_draw_info,_exception);
2374 (void) CloneString(&_draw_info->primitive,(char *)NULL);
2377 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2381 if (LocaleCompare("edge",option+1) == 0)
2383 if (IfMagickFalse(IsGeometry(arg1)))
2384 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2385 flags=ParseGeometry(arg1,&geometry_info);
2386 if ((flags & SigmaValue) == 0)
2387 geometry_info.sigma=1.0;
2388 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2392 if (LocaleCompare("emboss",option+1) == 0)
2394 if (IfMagickFalse(IsGeometry(arg1)))
2395 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2396 flags=ParseGeometry(arg1,&geometry_info);
2397 if ((flags & SigmaValue) == 0)
2398 geometry_info.sigma=1.0;
2399 new_image=EmbossImage(_image,geometry_info.rho,
2400 geometry_info.sigma,_exception);
2403 if (LocaleCompare("encipher",option+1) == 0)
2408 passkey=FileToStringInfo(arg1,~0,_exception);
2409 if (passkey != (StringInfo *) NULL)
2411 (void) PasskeyEncipherImage(_image,passkey,_exception);
2412 passkey=DestroyStringInfo(passkey);
2416 if (LocaleCompare("enhance",option+1) == 0)
2418 new_image=EnhanceImage(_image,_exception);
2421 if (LocaleCompare("equalize",option+1) == 0)
2423 (void) EqualizeImage(_image,_exception);
2426 if (LocaleCompare("evaluate",option+1) == 0)
2431 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2433 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2435 if (IfMagickFalse(IsGeometry(arg2)))
2436 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
2437 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
2438 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2442 if (LocaleCompare("extent",option+1) == 0)
2444 if (IfMagickFalse(IsGeometry(arg1)))
2445 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2446 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
2447 if (geometry.width == 0)
2448 geometry.width=_image->columns;
2449 if (geometry.height == 0)
2450 geometry.height=_image->rows;
2451 new_image=ExtentImage(_image,&geometry,_exception);
2454 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2458 if (LocaleCompare("features",option+1) == 0)
2460 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
2462 (void) DeleteImageArtifact(_image,"identify:features");
2465 (void) SetImageArtifact(_image,"identify:features","true");
2466 (void) SetImageArtifact(_image,"verbose","true");
2469 if (LocaleCompare("flip",option+1) == 0)
2471 new_image=FlipImage(_image,_exception);
2474 if (LocaleCompare("flop",option+1) == 0)
2476 new_image=FlopImage(_image,_exception);
2479 if (LocaleCompare("floodfill",option+1) == 0)
2484 if (IfMagickFalse(IsGeometry(arg1)))
2485 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2486 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2487 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2488 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2489 geometry.y,plus_alt_op,_exception);
2492 if (LocaleCompare("frame",option+1) == 0)
2503 value=GetImageOption(_image_info,"compose");
2504 if (value != (const char *) NULL)
2505 compose=(CompositeOperator) ParseCommandOption(
2506 MagickComposeOptions,MagickFalse,value);
2508 compose=OverCompositeOp; /* use Over not _image->compose */
2510 if (IfMagickFalse(IsGeometry(arg1)))
2511 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2512 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
2513 frame_info.width=geometry.width;
2514 frame_info.height=geometry.height;
2515 if ((flags & HeightValue) == 0)
2516 frame_info.height=geometry.width;
2517 frame_info.outer_bevel=geometry.x;
2518 frame_info.inner_bevel=geometry.y;
2519 frame_info.x=(ssize_t) frame_info.width;
2520 frame_info.y=(ssize_t) frame_info.height;
2521 frame_info.width=_image->columns+2*frame_info.width;
2522 frame_info.height=_image->rows+2*frame_info.height;
2523 new_image=FrameImage(_image,&frame_info,compose,_exception);
2526 if (LocaleCompare("function",option+1) == 0)
2530 token[MaxTextExtent];
2545 Function Modify Image Values
2546 FUTURE: code should be almost a duplicate of that is "distort"
2548 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2550 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2552 arguments=InterpretImageProperties(_image_info,_image,arg2,
2554 if (arguments == (char *) NULL)
2555 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
2556 p=(char *) arguments;
2557 for (x=0; *p != '\0'; x++)
2559 GetMagickToken(p,&p,token);
2561 GetMagickToken(p,&p,token);
2563 number_parameters=(size_t) x;
2564 parameters=(double *) AcquireQuantumMemory(number_parameters,
2565 sizeof(*parameters));
2566 if (parameters == (double *) NULL)
2567 ThrowWandFatalException(ResourceLimitFatalError,
2568 "MemoryAllocationFailed",_image->filename);
2569 (void) ResetMagickMemory(parameters,0,number_parameters*
2570 sizeof(*parameters));
2571 p=(char *) arguments;
2572 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++) {
2573 GetMagickToken(p,&p,token);
2575 GetMagickToken(p,&p,token);
2576 parameters[x]=StringToDouble(token,(char **) NULL);
2578 arguments=DestroyString(arguments);
2579 (void) FunctionImage(_image,(MagickFunction)parse,number_parameters,
2580 parameters,_exception);
2581 parameters=(double *) RelinquishMagickMemory(parameters);
2584 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2588 if (LocaleCompare("gamma",option+1) == 0)
2590 if (IfMagickFalse(IsGeometry(arg1)))
2591 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2593 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2596 _image->gamma=StringToDouble(arg1,(char **) NULL);
2599 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2600 (LocaleCompare("gaussian",option+1) == 0))
2602 if (IfMagickFalse(IsGeometry(arg1)))
2603 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2604 flags=ParseGeometry(arg1,&geometry_info);
2605 if ((flags & SigmaValue) == 0)
2606 geometry_info.sigma=1.0;
2607 new_image=GaussianBlurImage(_image,geometry_info.rho,
2608 geometry_info.sigma,_exception);
2611 if (LocaleCompare("geometry",option+1) == 0)
2614 Record Image offset for composition. (A Setting)
2615 Resize last _image. (ListOperator) -- DEPRECIATE
2616 FUTURE: Why if no 'offset' does this resize ALL images?
2617 Also why is the setting recorded in the IMAGE non-sense!
2620 { /* remove the previous composition geometry offset! */
2621 if (_image->geometry != (char *) NULL)
2622 _image->geometry=DestroyString(_image->geometry);
2625 if (IfMagickFalse(IsGeometry(arg1)))
2626 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2627 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
2628 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2629 (void) CloneString(&_image->geometry,arg1);
2631 new_image=ResizeImage(_image,geometry.width,geometry.height,
2632 _image->filter,_exception);
2635 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2639 if (LocaleCompare("highlight-color",option+1) == 0)
2641 (void) SetImageArtifact(_image,option+1,arg1);
2644 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2648 if (LocaleCompare("identify",option+1) == 0)
2654 format=GetImageOption(_image_info,"format");
2655 if (format == (char *) NULL)
2657 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2661 text=InterpretImageProperties(_image_info,_image,format,_exception);
2662 if (text == (char *) NULL)
2664 (void) fputs(text,stdout);
2665 (void) fputc('\n',stdout);
2666 text=DestroyString((char *)text);
2669 if (LocaleCompare("implode",option+1) == 0)
2671 if (IfMagickFalse(IsGeometry(arg1)))
2672 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2673 (void) ParseGeometry(arg1,&geometry_info);
2674 new_image=ImplodeImage(_image,geometry_info.rho,
2675 _image->interpolate,_exception);
2678 if (LocaleCompare("interpolative-resize",option+1) == 0)
2680 /* FUTURE: New to IMv7
2681 Roll into a resize special operator */
2682 if (IfMagickFalse(IsGeometry(arg1)))
2683 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2684 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2685 new_image=InterpolativeResizeImage(_image,geometry.width,
2686 geometry.height,_image->interpolate,_exception);
2689 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2693 if (LocaleCompare("lat",option+1) == 0)
2695 if (IfMagickFalse(IsGeometry(arg1)))
2696 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2697 flags=ParseGeometry(arg1,&geometry_info);
2698 if ((flags & PercentValue) != 0)
2699 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2700 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
2701 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2705 if (LocaleCompare("level",option+1) == 0)
2715 if (IfMagickFalse(IsGeometry(arg1)))
2716 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2717 flags=ParseGeometry(arg1,&geometry_info);
2718 black_point=geometry_info.rho;
2719 white_point=(MagickRealType) QuantumRange;
2720 if ((flags & SigmaValue) != 0)
2721 white_point=geometry_info.sigma;
2723 if ((flags & XiValue) != 0)
2724 gamma=geometry_info.xi;
2725 if ((flags & PercentValue) != 0)
2727 black_point*=(MagickRealType) (QuantumRange/100.0);
2728 white_point*=(MagickRealType) (QuantumRange/100.0);
2730 if ((flags & SigmaValue) == 0)
2731 white_point=(MagickRealType) QuantumRange-black_point;
2732 if (IfPlusOp || ((flags & AspectValue) != 0))
2733 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
2735 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
2738 if (LocaleCompare("level-colors",option+1) == 0)
2741 token[MaxTextExtent];
2750 p=(const char *) arg1;
2751 GetMagickToken(p,&p,token); /* get black point color */
2752 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2753 (void) QueryColorCompliance(token,AllCompliance,
2754 &black_point,_exception);
2756 (void) QueryColorCompliance("#000000",AllCompliance,
2757 &black_point,_exception);
2758 if (isalpha((int) token[0]) || (token[0] == '#'))
2759 GetMagickToken(p,&p,token);
2761 white_point=black_point; /* set everything to that color */
2764 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2765 GetMagickToken(p,&p,token); /* Get white point color. */
2766 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2767 (void) QueryColorCompliance(token,AllCompliance,
2768 &white_point,_exception);
2770 (void) QueryColorCompliance("#ffffff",AllCompliance,
2771 &white_point,_exception);
2773 (void) LevelImageColors(_image,&black_point,&white_point,
2774 plus_alt_op,_exception);
2777 if (LocaleCompare("linear-stretch",option+1) == 0)
2786 if (IfMagickFalse(IsGeometry(arg1)))
2787 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2788 flags=ParseGeometry(arg1,&geometry_info);
2789 black_point=geometry_info.rho;
2790 white_point=(MagickRealType) _image->columns*_image->rows;
2791 if ((flags & SigmaValue) != 0)
2792 white_point=geometry_info.sigma;
2793 if ((flags & PercentValue) != 0)
2795 black_point*=(double) _image->columns*_image->rows/100.0;
2796 white_point*=(double) _image->columns*_image->rows/100.0;
2798 if ((flags & SigmaValue) == 0)
2799 white_point=(MagickRealType) _image->columns*_image->rows-
2801 (void) LinearStretchImage(_image,black_point,white_point,_exception);
2804 if (LocaleCompare("liquid-rescale",option+1) == 0)
2806 /* FUTURE: Roll into a resize special operator */
2807 if (IfMagickFalse(IsGeometry(arg1)))
2808 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2809 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
2810 if ((flags & XValue) == 0)
2812 if ((flags & YValue) == 0)
2814 new_image=LiquidRescaleImage(_image,geometry.width,
2815 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
2818 if (LocaleCompare("lowlight-color",option+1) == 0)
2820 (void) SetImageArtifact(_image,option+1,arg1);
2823 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2827 if (LocaleCompare("map",option+1) == 0)
2832 /* DEPRECIATED use -remap */
2833 remap_image=GetImageCache(_image_info,arg1,_exception);
2834 if (remap_image == (Image *) NULL)
2836 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
2837 remap_image=DestroyImage(remap_image);
2840 if (LocaleCompare("mask",option+1) == 0)
2846 { /* Remove a mask. */
2847 (void) SetImageMask(_image,(Image *) NULL,_exception);
2850 /* Set the image mask. */
2851 mask=GetImageCache(_image_info,arg1,_exception);
2852 if (mask == (Image *) NULL)
2854 (void) SetImageMask(_image,mask,_exception);
2855 mask=DestroyImage(mask);
2858 if (LocaleCompare("matte",option+1) == 0)
2861 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2862 DeactivateAlphaChannel, _exception);
2865 if (LocaleCompare("median",option+1) == 0)
2867 /* DEPRECIATED - use -statistic Median */
2868 if (IfMagickFalse(IsGeometry(arg1)))
2869 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2870 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2873 if (LocaleCompare("mode",option+1) == 0)
2875 if (IfMagickFalse(IsGeometry(arg1)))
2876 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2877 flags=ParseGeometry(arg1,&geometry_info);
2878 if ((flags & SigmaValue) == 0)
2879 geometry_info.sigma=geometry_info.rho;
2880 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2881 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
2884 if (LocaleCompare("modulate",option+1) == 0)
2886 if (IfMagickFalse(IsGeometry(arg1)))
2887 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2888 (void) ModulateImage(_image,arg1,_exception);
2891 if (LocaleCompare("monitor",option+1) == 0)
2893 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
2894 (MagickProgressMonitor) NULL,(void *) NULL);
2897 if (LocaleCompare("monochrome",option+1) == 0)
2899 (void) SetImageType(_image,BilevelType,_exception);
2902 if (LocaleCompare("morphology",option+1) == 0)
2905 token[MaxTextExtent];
2917 GetMagickToken(p,&p,token);
2918 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2920 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2923 GetMagickToken(p,&p,token);
2924 if ((*p == ':') || (*p == ','))
2925 GetMagickToken(p,&p,token);
2927 iterations=(ssize_t) StringToLong(p);
2928 kernel=AcquireKernelInfo(arg2);
2929 if (kernel == (KernelInfo *) NULL)
2930 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2932 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2933 iterations,kernel,_exception);
2934 kernel=DestroyKernelInfo(kernel);
2937 if (LocaleCompare("motion-blur",option+1) == 0)
2939 if (IfMagickFalse(IsGeometry(arg1)))
2940 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2941 flags=ParseGeometry(arg1,&geometry_info);
2942 if ((flags & SigmaValue) == 0)
2943 geometry_info.sigma=1.0;
2944 new_image=MotionBlurImage(_image,geometry_info.rho,
2945 geometry_info.sigma,geometry_info.xi,_exception);
2948 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
2952 if (LocaleCompare("negate",option+1) == 0)
2954 (void) NegateImage(_image, plus_alt_op, _exception);
2957 if (LocaleCompare("noise",option+1) == 0)
2961 if (IfMagickFalse(IsGeometry(arg1)))
2962 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2963 flags=ParseGeometry(arg1,&geometry_info);
2964 if ((flags & SigmaValue) == 0)
2965 geometry_info.sigma=geometry_info.rho;
2966 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2967 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
2977 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2979 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2981 value=GetImageOption(_image_info,"attenuate");
2982 if (value != (const char *) NULL)
2983 attenuate=StringToDouble(value,(char **) NULL);
2987 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2992 if (LocaleCompare("normalize",option+1) == 0)
2994 (void) NormalizeImage(_image,_exception);
2997 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3001 if (LocaleCompare("opaque",option+1) == 0)
3006 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3007 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
3011 if (LocaleCompare("ordered-dither",option+1) == 0)
3013 (void) OrderedPosterizeImage(_image,arg1,_exception);
3016 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3020 if (LocaleCompare("paint",option+1) == 0)
3022 (void) ParseGeometry(arg1,&geometry_info);
3023 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
3027 if (LocaleCompare("polaroid",option+1) == 0)
3039 random_info=AcquireRandomInfo();
3040 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
3041 random_info=DestroyRandomInfo(random_info);
3044 if (IfMagickFalse(IsGeometry(arg1)))
3045 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3046 flags=ParseGeometry(arg1,&geometry_info);
3047 angle=geometry_info.rho;
3049 caption=GetImageProperty(_image,"caption",_exception);
3050 new_image=PolaroidImage(_image,_draw_info,caption,angle,
3051 _image->interpolate,_exception);
3054 if (LocaleCompare("posterize",option+1) == 0)
3056 if (IfMagickFalse(IsGeometry(arg1)))
3057 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3058 (void) ParseGeometry(arg1,&geometry_info);
3059 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
3060 _quantize_info->dither,_exception);
3063 if (LocaleCompare("preview",option+1) == 0)
3065 /* FUTURE: should be a 'Genesis' option?
3066 Option however is also in WandSettingOptionInfo()
3069 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
3071 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
3073 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
3076 if (LocaleCompare("profile",option+1) == 0)
3091 { /* Remove a profile from the _image. */
3092 (void) ProfileImage(_image,arg1,(const unsigned char *)
3096 /* Associate a profile with the _image. */
3097 profile_info=CloneImageInfo(_image_info);
3098 profile=GetImageProfile(_image,"iptc");
3099 if (profile != (StringInfo *) NULL)
3100 profile_info->profile=(void *) CloneStringInfo(profile);
3101 profile_image=GetImageCache(profile_info,arg1,_exception);
3102 profile_info=DestroyImageInfo(profile_info);
3103 if (profile_image == (Image *) NULL)
3108 profile_info=CloneImageInfo(_image_info);
3109 (void) CopyMagickString(profile_info->filename,arg1,
3111 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
3112 if (profile != (StringInfo *) NULL)
3114 (void) ProfileImage(_image,profile_info->magick,
3115 GetStringInfoDatum(profile),(size_t)
3116 GetStringInfoLength(profile),_exception);
3117 profile=DestroyStringInfo(profile);
3119 profile_info=DestroyImageInfo(profile_info);
3122 ResetImageProfileIterator(profile_image);
3123 name=GetNextImageProfile(profile_image);
3124 while (name != (const char *) NULL)
3126 profile=GetImageProfile(profile_image,name);
3127 if (profile != (StringInfo *) NULL)
3128 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3129 (size_t) GetStringInfoLength(profile),_exception);
3130 name=GetNextImageProfile(profile_image);
3132 profile_image=DestroyImage(profile_image);
3135 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3139 if (LocaleCompare("radial-blur",option+1) == 0)
3141 if (IfMagickFalse(IsGeometry(arg1)))
3142 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3143 flags=ParseGeometry(arg1,&geometry_info);
3144 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
3147 if (LocaleCompare("raise",option+1) == 0)
3149 if (IfMagickFalse(IsGeometry(arg1)))
3150 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3151 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3152 if ((flags & SigmaValue) == 0)
3153 geometry.height=geometry.width;
3154 (void) RaiseImage(_image,&geometry,normal_op,_exception);
3157 if (LocaleCompare("random-threshold",option+1) == 0)
3159 if (IfMagickFalse(IsGeometry(arg1)))
3160 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3161 (void) RandomThresholdImage(_image,arg1,_exception);
3164 if (LocaleCompare("remap",option+1) == 0)
3169 remap_image=GetImageCache(_image_info,arg1,_exception);
3170 if (remap_image == (Image *) NULL)
3172 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
3173 remap_image=DestroyImage(remap_image);
3176 if (LocaleCompare("repage",option+1) == 0)
3180 if (IfMagickFalse(IsGeometry(arg1)))
3181 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3183 (void) ResetImagePage(_image,arg1);
3186 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
3189 if (LocaleCompare("resample",option+1) == 0)
3191 /* FUTURE: Roll into a resize special operation */
3192 if (IfMagickFalse(IsGeometry(arg1)))
3193 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3194 flags=ParseGeometry(arg1,&geometry_info);
3195 if ((flags & SigmaValue) == 0)
3196 geometry_info.sigma=geometry_info.rho;
3197 new_image=ResampleImage(_image,geometry_info.rho,
3198 geometry_info.sigma,_image->filter,_exception);
3201 if (LocaleCompare("resize",option+1) == 0)
3203 if (IfMagickFalse(IsGeometry(arg1)))
3204 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3205 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3206 new_image=ResizeImage(_image,geometry.width,geometry.height,
3207 _image->filter,_exception);
3210 if (LocaleCompare("roll",option+1) == 0)
3212 if (IfMagickFalse(IsGeometry(arg1)))
3213 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3214 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3215 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
3218 if (LocaleCompare("rotate",option+1) == 0)
3220 if (IfMagickFalse(IsGeometry(arg1)))
3221 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3222 if (strchr(arg1,'>') != (char *) NULL)
3223 if (_image->columns <= _image->rows)
3225 if (strchr(arg1,'<') != (char *) NULL)
3226 if (_image->columns >= _image->rows)
3228 (void) ParseGeometry(arg1,&geometry_info);
3229 new_image=RotateImage(_image,geometry_info.rho,_exception);
3232 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3236 if (LocaleCompare("sample",option+1) == 0)
3238 /* FUTURE: Roll into a resize special operator */
3239 if (IfMagickFalse(IsGeometry(arg1)))
3240 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3241 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3242 new_image=SampleImage(_image,geometry.width,geometry.height,
3246 if (LocaleCompare("scale",option+1) == 0)
3248 /* FUTURE: Roll into a resize special operator */
3249 if (IfMagickFalse(IsGeometry(arg1)))
3250 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3251 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3252 new_image=ScaleImage(_image,geometry.width,geometry.height,
3256 if (LocaleCompare("segment",option+1) == 0)
3258 if (IfMagickFalse(IsGeometry(arg1)))
3259 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3260 flags=ParseGeometry(arg1,&geometry_info);
3261 if ((flags & SigmaValue) == 0)
3262 geometry_info.sigma=1.0;
3263 (void) SegmentImage(_image,_image->colorspace,
3264 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3268 if (LocaleCompare("selective-blur",option+1) == 0)
3270 if (IfMagickFalse(IsGeometry(arg1)))
3271 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3272 flags=ParseGeometry(arg1,&geometry_info);
3273 if ((flags & PercentValue) != 0)
3274 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3275 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3276 geometry_info.sigma,geometry_info.xi,_exception);
3279 if (LocaleCompare("separate",option+1) == 0)
3281 /* WARNING: This can generate multiple images! */
3282 /* FUTURE - this may be replaced by a "-channel" method */
3283 new_image=SeparateImages(_image,_exception);
3286 if (LocaleCompare("sepia-tone",option+1) == 0)
3288 if (IfMagickFalse(IsGeometry(arg1)))
3289 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3290 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3291 (double) QuantumRange+1.0),_exception);
3294 if (LocaleCompare("set",option+1) == 0)
3300 if (LocaleNCompare(arg1,"registry:",9) == 0)
3301 (void) DeleteImageRegistry(arg1+9);
3303 if (LocaleNCompare(arg1,"option:",7) == 0)
3305 (void) DeleteImageOption(_image_info,arg1+7);
3306 (void) DeleteImageArtifact(_image,arg1+7);
3309 (void) DeleteImageProperty(_image,arg1);
3312 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
3313 if (value == (char *) NULL)
3315 if (LocaleNCompare(arg1,"registry:",9) == 0)
3316 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
3318 if (LocaleNCompare(arg1,"option:",7) == 0)
3320 (void) SetImageOption(_image_info,arg1+7,value);
3321 (void) SetImageArtifact(_image,arg1+7,value);
3324 (void) SetImageProperty(_image,arg1,value,_exception);
3325 value=DestroyString(value);
3328 if (LocaleCompare("shade",option+1) == 0)
3330 if (IfMagickFalse(IsGeometry(arg1)))
3331 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3332 flags=ParseGeometry(arg1,&geometry_info);
3333 if ((flags & SigmaValue) == 0)
3334 geometry_info.sigma=1.0;
3335 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3336 geometry_info.sigma,_exception);
3339 if (LocaleCompare("shadow",option+1) == 0)
3341 if (IfMagickFalse(IsGeometry(arg1)))
3342 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3343 flags=ParseGeometry(arg1,&geometry_info);
3344 if ((flags & SigmaValue) == 0)
3345 geometry_info.sigma=1.0;
3346 if ((flags & XiValue) == 0)
3347 geometry_info.xi=4.0;
3348 if ((flags & PsiValue) == 0)
3349 geometry_info.psi=4.0;
3350 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3351 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3352 ceil(geometry_info.psi-0.5),_exception);
3355 if (LocaleCompare("sharpen",option+1) == 0)
3357 if (IfMagickFalse(IsGeometry(arg1)))
3358 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3359 flags=ParseGeometry(arg1,&geometry_info);
3360 if ((flags & SigmaValue) == 0)
3361 geometry_info.sigma=1.0;
3362 if ((flags & XiValue) == 0)
3363 geometry_info.xi=0.0;
3364 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3368 if (LocaleCompare("shave",option+1) == 0)
3370 if (IfMagickFalse(IsGeometry(arg1)))
3371 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3372 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3373 new_image=ShaveImage(_image,&geometry,_exception);
3376 if (LocaleCompare("shear",option+1) == 0)
3378 if (IfMagickFalse(IsGeometry(arg1)))
3379 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3380 flags=ParseGeometry(arg1,&geometry_info);
3381 if ((flags & SigmaValue) == 0)
3382 geometry_info.sigma=geometry_info.rho;
3383 new_image=ShearImage(_image,geometry_info.rho,
3384 geometry_info.sigma,_exception);
3387 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
3389 if (IfMagickFalse(IsGeometry(arg1)))
3390 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3391 flags=ParseGeometry(arg1,&geometry_info);
3392 if ((flags & SigmaValue) == 0)
3393 geometry_info.sigma=(double) QuantumRange/2.0;
3394 if ((flags & PercentValue) != 0)
3395 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3397 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
3398 geometry_info.sigma,
3402 if (LocaleCompare("sketch",option+1) == 0)
3404 if (IfMagickFalse(IsGeometry(arg1)))
3405 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3406 flags=ParseGeometry(arg1,&geometry_info);
3407 if ((flags & SigmaValue) == 0)
3408 geometry_info.sigma=1.0;
3409 new_image=SketchImage(_image,geometry_info.rho,
3410 geometry_info.sigma,geometry_info.xi,_exception);
3413 if (LocaleCompare("solarize",option+1) == 0)
3415 if (IfMagickFalse(IsGeometry(arg1)))
3416 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3417 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3418 QuantumRange+1.0),_exception);
3421 if (LocaleCompare("sparse-color",option+1) == 0)
3426 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3428 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3430 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
3431 if (arguments == (char *) NULL)
3432 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3433 new_image=SparseColorOption(_image,(SparseColorMethod)parse,
3434 arguments,_exception);
3435 arguments=DestroyString(arguments);
3438 if (LocaleCompare("splice",option+1) == 0)
3440 if (IfMagickFalse(IsGeometry(arg1)))
3441 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3442 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3443 new_image=SpliceImage(_image,&geometry,_exception);
3446 if (LocaleCompare("spread",option+1) == 0)
3448 if (IfMagickFalse(IsGeometry(arg1)))
3449 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3450 (void) ParseGeometry(arg1,&geometry_info);
3451 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3455 if (LocaleCompare("statistic",option+1) == 0)
3457 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3459 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
3461 if (IfMagickFalse(IsGeometry(arg2)))
3462 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3463 (void) ParseGeometry(arg2,&geometry_info);
3464 new_image=StatisticImage(_image,(StatisticType)parse,
3465 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3469 if (LocaleCompare("strip",option+1) == 0)
3471 (void) StripImage(_image,_exception);
3474 if (LocaleCompare("swirl",option+1) == 0)
3476 if (IfMagickFalse(IsGeometry(arg1)))
3477 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3478 (void) ParseGeometry(arg1,&geometry_info);
3479 new_image=SwirlImage(_image,geometry_info.rho,
3480 _image->interpolate,_exception);
3483 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3487 if (LocaleCompare("threshold",option+1) == 0)
3492 threshold=(double) QuantumRange/2;
3494 if (IfMagickFalse(IsGeometry(arg1)))
3495 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3496 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
3498 (void) BilevelImage(_image,threshold,_exception);
3501 if (LocaleCompare("thumbnail",option+1) == 0)
3503 if (IfMagickFalse(IsGeometry(arg1)))
3504 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3505 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3506 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3510 if (LocaleCompare("tint",option+1) == 0)
3512 if (IfMagickFalse(IsGeometry(arg1)))
3513 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3514 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
3517 if (LocaleCompare("transform",option+1) == 0)
3519 /* DEPRECIATED -- should really use Distort AffineProjection */
3520 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
3523 if (LocaleCompare("transparent",option+1) == 0)
3528 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3529 (void) TransparentPaintImage(_image,&target,(Quantum)
3530 TransparentAlpha,plus_alt_op,_exception);
3533 if (LocaleCompare("transpose",option+1) == 0)
3535 new_image=TransposeImage(_image,_exception);
3538 if (LocaleCompare("transverse",option+1) == 0)
3540 new_image=TransverseImage(_image,_exception);
3543 if (LocaleCompare("trim",option+1) == 0)
3545 new_image=TrimImage(_image,_exception);
3548 if (LocaleCompare("type",option+1) == 0)
3550 /* Note that "type" setting should have already been defined */
3551 (void) SetImageType(_image,_image_info->type,_exception);
3554 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3558 if (LocaleCompare("unique",option+1) == 0)
3560 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3561 Option is not documented, bt appears to be for "identify".
3562 We may need a identify specific verbose!
3565 (void) DeleteImageArtifact(_image,"identify:unique-colors");
3568 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3569 (void) SetImageArtifact(_image,"verbose","true");
3572 if (LocaleCompare("unique-colors",option+1) == 0)
3574 new_image=UniqueImageColors(_image,_exception);
3577 if (LocaleCompare("unsharp",option+1) == 0)
3579 if (IfMagickFalse(IsGeometry(arg1)))
3580 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3581 flags=ParseGeometry(arg1,&geometry_info);
3582 if ((flags & SigmaValue) == 0)
3583 geometry_info.sigma=1.0;
3584 if ((flags & XiValue) == 0)
3585 geometry_info.xi=1.0;
3586 if ((flags & PsiValue) == 0)
3587 geometry_info.psi=0.05;
3588 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3589 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
3592 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3596 if (LocaleCompare("verbose",option+1) == 0)
3598 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
3599 three places! ImageArtifact ImageOption _image_info->verbose
3600 Some how new images also get this artifact!
3602 (void) SetImageArtifact(_image,option+1,
3603 IfNormalOp ? "true" : "false" );
3606 if (LocaleCompare("vignette",option+1) == 0)
3608 if (IfMagickFalse(IsGeometry(arg1)))
3609 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3610 flags=ParseGeometry(arg1,&geometry_info);
3611 if ((flags & SigmaValue) == 0)
3612 geometry_info.sigma=1.0;
3613 if ((flags & XiValue) == 0)
3614 geometry_info.xi=0.1*_image->columns;
3615 if ((flags & PsiValue) == 0)
3616 geometry_info.psi=0.1*_image->rows;
3617 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3618 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3619 ceil(geometry_info.psi-0.5),_exception);
3622 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3626 if (LocaleCompare("wave",option+1) == 0)
3628 if (IfMagickFalse(IsGeometry(arg1)))
3629 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3630 flags=ParseGeometry(arg1,&geometry_info);
3631 if ((flags & SigmaValue) == 0)
3632 geometry_info.sigma=1.0;
3633 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3634 _image->interpolate,_exception);
3637 if (LocaleCompare("white-threshold",option+1) == 0)
3639 if (IfMagickFalse(IsGeometry(arg1)))
3640 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3641 (void) WhiteThresholdImage(_image,arg1,_exception);
3644 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3647 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3650 Replace current image with any image that was generated
3651 and set image point to last image (so image->next is correct)
3653 if (new_image != (Image *) NULL)
3654 ReplaceImageInListReturnLast(&_image,new_image);
3659 #undef _quantize_info
3668 WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
3669 const char *option, const char *arg1, const char *arg2)
3675 assert(cli_wand != (MagickCLI *) NULL);
3676 assert(cli_wand->signature == WandSignature);
3677 assert(cli_wand->wand.signature == WandSignature);
3678 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3679 if (IfMagickTrue(cli_wand->wand.debug))
3680 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
3682 #if !USE_WAND_METHODS
3683 /* FUTURE add appropriate tracing */
3685 n=GetImageListLength(cli_wand->wand.images);
3686 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3689 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3690 if ( cli_wand->wand.images->next == (Image *) NULL )
3692 cli_wand->wand.images=cli_wand->wand.images->next;
3695 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3697 MagickResetIterator(&cli_wand->wand);
3698 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
3699 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3700 MagickResetIterator(&cli_wand->wand);
3706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3710 + C L I L i s t O p e r a t o r I m a g e s %
3714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3716 % CLIListOperatorImages() applies a single operation that is apply to the
3717 % entire image list as a whole. The result is often a complete replacment
3718 % of the image list with a completely new list, or just a single image.
3720 % The format of the MogrifyImage method is:
3722 % void CLIListOperatorImages(MagickCLI *cli_wand,
3723 % const char *option, const char *arg1, const char *arg2)
3725 % A description of each parameter follows:
3727 % o cli_wand: structure holding settings to be applied
3729 % o option: The option string for the operation
3731 % o arg1, arg2: optional argument strings to the operation
3733 % NOTE: only "limit" uses two arguments.
3737 % CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3738 % CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
3740 % Or for handling command line arguments EG: +/-option ["arg1"]
3746 % option_info = GetCommandOptionInfo(argv[i]);
3747 % count=option_info->type;
3748 % option_type=option_info->flags;
3750 % if ( (option_type & ListOperatorOptionFlag) != 0 )
3751 % CLIListOperatorImages(cli_wand,argv[i],
3752 % count>=1 ? argv[i+1] : (char *)NULL,
3753 % count>=2 ? argv[i+2] : (char *)NULL );
3757 WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
3758 const char *option,const char *arg1, const char *arg2)
3766 #define _image_info (cli_wand->wand.image_info)
3767 #define _images (cli_wand->wand.images)
3768 #define _exception (cli_wand->wand.exception)
3769 #define _draw_info (cli_wand->draw_info)
3770 #define _quantize_info (cli_wand->quantize_info)
3771 #define IfNormalOp (*option=='-')
3772 #define IfPlusOp (*option!='-')
3773 #define normal_op IsMagickTrue(IfNormalOp)
3775 assert(cli_wand != (MagickCLI *) NULL);
3776 assert(cli_wand->signature == WandSignature);
3777 assert(cli_wand->wand.signature == WandSignature);
3778 assert(_images != (Image *) NULL); /* _images must be present */
3779 if (IfMagickTrue(cli_wand->wand.debug))
3780 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
3782 (void) SyncImagesSettings(_image_info,_images,_exception);
3784 new_images=NewImageList();
3786 switch (*(option+1))
3790 if (LocaleCompare("append",option+1) == 0)
3792 new_images=AppendImages(_images,normal_op,_exception);
3795 if (LocaleCompare("average",option+1) == 0)
3797 /* DEPRECIATED - use -evaluate-sequence Mean */
3798 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
3801 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3805 if (LocaleCompare("channel-fx",option+1) == 0)
3807 new_images=ChannelFxImage(_images,arg1,_exception);
3810 if (LocaleCompare("clut",option+1) == 0)
3815 /* FUTURE - make this a compose option, and thus can be used
3816 with layers compose or even compose last image over all other
3819 new_images=RemoveFirstImageFromList(&_images);
3820 clut_image=RemoveLastImageFromList(&_images);
3821 /* FUTURE - produce Exception, rather than silent fail */
3822 if (clut_image == (Image *) NULL)
3824 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
3825 clut_image=DestroyImage(clut_image);
3828 if (LocaleCompare("coalesce",option+1) == 0)
3830 new_images=CoalesceImages(_images,_exception);
3833 if (LocaleCompare("combine",option+1) == 0)
3835 /* FUTURE - this may be replaced by a 'channel' method */
3836 new_images=CombineImages(_images,_exception);
3839 if (LocaleCompare("composite",option+1) == 0)
3857 /* Compose value from "-compose" option only */
3858 value=GetImageOption(_image_info,"compose");
3859 if (value == (const char *) NULL)
3860 compose=OverCompositeOp; /* use Over not source_image->compose */
3862 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3865 /* Get "clip-to-self" expert setting (false is normal) */
3866 value=GetImageOption(_image_info,"compose:clip-to-self");
3867 if (value == (const char *) NULL)
3868 clip_to_self=MagickTrue;
3870 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3871 "compose:clip-to-self")); /* if this is true */
3872 value=GetImageOption(_image_info,"compose:outside-overlay");
3873 if (value != (const char *) NULL) { /* or this false */
3874 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
3875 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
3878 new_images=RemoveFirstImageFromList(&_images);
3879 source_image=RemoveFirstImageFromList(&_images);
3880 if (source_image == (Image *) NULL)
3881 break; /* FUTURE - produce Exception, rather than silent fail */
3883 /* FUTURE - this should not be here! - should be part of -geometry */
3884 (void) TransformImage(&source_image,(char *) NULL,
3885 source_image->geometry,_exception);
3887 SetGeometry(source_image,&geometry);
3888 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3889 GravityAdjustGeometry(new_images->columns,new_images->rows,
3890 new_images->gravity, &geometry);
3892 mask_image=RemoveFirstImageFromList(&_images);
3893 if (mask_image != (Image *) NULL)
3894 { /* handle a third write mask image */
3895 if ((compose == DisplaceCompositeOp) ||
3896 (compose == DistortCompositeOp)) {
3897 /* Merge Y displacement into X displace/distort map. */
3898 (void) CompositeImage(source_image,mask_image,
3899 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3900 mask_image=DestroyImage(mask_image);
3903 /* Set a blending mask for the composition. */
3904 (void) NegateImage(mask_image,MagickFalse,_exception);
3905 (void) SetImageMask(new_images,mask_image,_exception);
3906 mask_image=DestroyImage(mask_image);
3909 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3910 geometry.x,geometry.y,_exception);
3911 (void) SetImageMask(new_images,(Image *) NULL,_exception);
3912 source_image=DestroyImage(source_image);
3915 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3919 if (LocaleCompare("deconstruct",option+1) == 0)
3921 /* DEPRECIATED - use -layers CompareAny */
3922 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
3925 if (LocaleCompare("delete",option+1) == 0)
3928 DeleteImages(&_images,arg1,_exception);
3930 DeleteImages(&_images,"-1",_exception);
3933 if (LocaleCompare("duplicate",option+1) == 0)
3943 if (IfMagickFalse(IsGeometry(arg1)))
3944 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3946 number_duplicates=(size_t) StringToLong(arg1);
3948 if (p == (const char *) NULL)
3949 new_images=DuplicateImages(_images,number_duplicates,"-1",
3952 new_images=DuplicateImages(_images,number_duplicates,p,
3956 new_images=DuplicateImages(_images,1,"-1",_exception);
3957 AppendImageToList(&_images, new_images);
3958 new_images=(Image *)NULL;
3961 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3965 if (LocaleCompare("evaluate-sequence",option+1) == 0)
3967 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3969 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3971 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3975 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3979 if (LocaleCompare("fft",option+1) == 0)
3981 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
3984 if (LocaleCompare("flatten",option+1) == 0)
3986 /* REDIRECTED to use -layers flatten instead */
3987 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
3990 if (LocaleCompare("fx",option+1) == 0)
3992 new_images=FxImage(_images,arg1,_exception);
3995 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
3999 if (LocaleCompare("hald-clut",option+1) == 0)
4001 /* FUTURE - make this a compose option (and thus layers compose )
4002 or perhaps compose last image over all other _images.
4007 new_images=RemoveFirstImageFromList(&_images);
4008 hald_image=RemoveLastImageFromList(&_images);
4009 if (hald_image == (Image *) NULL)
4011 (void) HaldClutImage(new_images,hald_image,_exception);
4012 hald_image=DestroyImage(hald_image);
4015 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4019 if (LocaleCompare("ift",option+1) == 0)
4025 magnitude_image=RemoveFirstImageFromList(&_images);
4026 phase_image=RemoveFirstImageFromList(&_images);
4027 /* FUTURE - produce Exception, rather than silent fail */
4028 if (phase_image == (Image *) NULL)
4030 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
4031 normal_op,_exception);
4032 magnitude_image=DestroyImage(magnitude_image);
4033 phase_image=DestroyImage(phase_image);
4036 if (LocaleCompare("insert",option+1) == 0)
4045 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
4046 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4048 insert_image=RemoveLastImageFromList(&_images);
4050 index=(ssize_t) StringToLong(arg1);
4051 index_image=insert_image;
4053 PrependImageToList(&_images,insert_image);
4054 else if (index == (ssize_t) GetImageListLength(_images))
4055 AppendImageToList(&_images,insert_image);
4058 index_image=GetImageFromList(_images,index-1);
4059 if (index_image == (Image *) NULL)
4060 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
4061 InsertImageInList(&index_image,insert_image);
4063 _images=GetFirstImageInList(index_image);
4066 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4070 if (LocaleCompare("layers",option+1) == 0)
4072 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4074 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4076 switch ((ImageLayerMethod) parse)
4080 new_images=CoalesceImages(_images,_exception);
4083 case CompareAnyLayer:
4084 case CompareClearLayer:
4085 case CompareOverlayLayer:
4088 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
4095 case TrimBoundsLayer:
4097 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
4103 new_images=DisposeImages(_images,_exception);
4106 case OptimizeImageLayer:
4108 new_images=OptimizeImageLayers(_images,_exception);
4111 case OptimizePlusLayer:
4113 new_images=OptimizePlusImageLayers(_images,_exception);
4116 case OptimizeTransLayer:
4118 OptimizeImageTransparency(_images,_exception);
4121 case RemoveDupsLayer:
4123 RemoveDuplicateLayers(&_images,_exception);
4126 case RemoveZeroLayer:
4128 RemoveZeroDelayLayers(&_images,_exception);
4132 { /* General Purpose, GIF Animation Optimizer. */
4133 new_images=CoalesceImages(_images,_exception);
4134 if (new_images == (Image *) NULL)
4136 _images=DestroyImageList(_images);
4137 _images=OptimizeImageLayers(new_images,_exception);
4138 if (_images == (Image *) NULL)
4140 new_images=DestroyImageList(new_images);
4141 OptimizeImageTransparency(_images,_exception);
4142 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4146 case CompositeLayer:
4160 value=GetImageOption(_image_info,"compose");
4161 compose=OverCompositeOp; /* Default to Over */
4162 if (value != (const char *) NULL)
4163 compose=(CompositeOperator) ParseCommandOption(
4164 MagickComposeOptions,MagickFalse,value);
4166 /* Split image sequence at the first 'NULL:' image. */
4168 while (source != (Image *) NULL)
4170 source=GetNextImageInList(source);
4171 if ((source != (Image *) NULL) &&
4172 (LocaleCompare(source->magick,"NULL") == 0))
4175 if (source != (Image *) NULL)
4177 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4178 (GetNextImageInList(source) == (Image *) NULL))
4179 source=(Image *) NULL;
4181 { /* Separate the two lists, junk the null: image. */
4182 source=SplitImageList(source->previous);
4183 DeleteImageFromList(&source);
4186 if (source == (Image *) NULL)
4188 (void) ThrowMagickException(_exception,GetMagickModule(),
4189 OptionError,"MissingNullSeparator","layers Composite");
4192 /* Adjust offset with gravity and virtual canvas. */
4193 SetGeometry(_images,&geometry);
4194 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
4195 geometry.width=source->page.width != 0 ?
4196 source->page.width : source->columns;
4197 geometry.height=source->page.height != 0 ?
4198 source->page.height : source->rows;
4199 GravityAdjustGeometry(_images->page.width != 0 ?
4200 _images->page.width : _images->columns,
4201 _images->page.height != 0 ? _images->page.height :
4202 _images->rows,_images->gravity,&geometry);
4204 /* Compose the two image sequences together */
4205 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4207 source=DestroyImageList(source);
4213 if (LocaleCompare("limit",option+1) == 0)
4218 limit=MagickResourceInfinity;
4219 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
4221 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
4223 if (LocaleCompare("unlimited",arg2) != 0)
4224 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
4225 (void) SetMagickResourceLimit((ResourceType)parse,limit);
4228 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4232 if (LocaleCompare("map",option+1) == 0)
4234 /* DEPRECIATED use +remap */
4235 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4238 if (LocaleCompare("morph",option+1) == 0)
4243 if (IfMagickFalse(IsGeometry(arg1)))
4244 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4245 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4247 if (morph_image == (Image *) NULL)
4249 _images=DestroyImageList(_images);
4250 _images=morph_image;
4253 if (LocaleCompare("mosaic",option+1) == 0)
4255 /* REDIRECTED to use -layers mosaic instead */
4256 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
4259 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4263 if (LocaleCompare("print",option+1) == 0)
4268 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
4269 if (string == (char *) NULL)
4271 (void) FormatLocaleFile(stdout,"%s",string);
4272 string=DestroyString(string);
4275 if (LocaleCompare("process",option+1) == 0)
4284 arguments=StringToArgv(arg1,&number_arguments);
4285 if (arguments == (char **) NULL)
4287 if (strchr(arguments[1],'=') != (char *) NULL)
4308 Support old style syntax, filter="-option arg1".
4310 length=strlen(arg1);
4311 token=(char *) NULL;
4312 if (~length >= (MaxTextExtent-1))
4313 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4315 if (token == (char *) NULL)
4319 token_info=AcquireTokenInfo();
4320 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4321 "\"",'\0',&breaker,&next,"e);
4322 token_info=DestroyTokenInfo(token_info);
4328 argv=(&(arguments[next]));
4329 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4332 token=DestroyString(token);
4335 (void) SubstituteString(&arguments[1],"-","");
4336 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4337 number_arguments-2,(const char **) arguments+2,_exception);
4338 for (j=0; j < number_arguments; j++)
4339 arguments[j]=DestroyString(arguments[j]);
4340 arguments=(char **) RelinquishMagickMemory(arguments);
4343 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4347 if (LocaleCompare("remap",option+1) == 0)
4349 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4352 if (LocaleCompare("reverse",option+1) == 0)
4354 ReverseImageList(&_images);
4357 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4361 if (LocaleCompare("smush",option+1) == 0)
4369 if (IfMagickFalse(IsGeometry(arg1)))
4370 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4371 offset=(ssize_t) StringToLong(arg1);
4372 smush_image=SmushImages(_images,normal_op,offset,_exception);
4373 if (smush_image == (Image *) NULL)
4375 _images=DestroyImageList(_images);
4376 _images=smush_image;
4379 if (LocaleCompare("swap",option+1) == 0) {
4399 if (IfMagickFalse(IsGeometry(arg1)))
4400 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
4401 flags=ParseGeometry(arg1,&geometry_info);
4402 index=(ssize_t) geometry_info.rho;
4403 if ((flags & SigmaValue) != 0)
4404 swap_index=(ssize_t) geometry_info.sigma;
4406 p=GetImageFromList(_images,index);
4407 q=GetImageFromList(_images,swap_index);
4408 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4409 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
4411 break; /* same image - no-op - not an error */
4412 swap=CloneImage(p,0,0,MagickTrue,_exception);
4413 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4414 ReplaceImageInList(&q,swap);
4415 _images=GetFirstImageInList(q);
4418 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4422 if (LocaleCompare("write",option+1) == 0)
4433 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4434 (void) DeleteImageRegistry(key);
4435 write_images=_images;
4437 write_images=CloneImageList(_images,_exception);
4438 write_info=CloneImageInfo(_image_info);
4439 (void) WriteImages(write_info,write_images,arg1,_exception);
4440 write_info=DestroyImageInfo(write_info);
4442 write_images=DestroyImageList(write_images);
4445 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4448 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
4450 if (new_images == (Image *) NULL)
4453 if (_images != (Image *) NULL)
4454 _images=DestroyImageList(_images);
4455 _images=GetFirstImageInList(new_images);
4462 #undef _quantize_info
4469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4473 + C L I S p e c i a l O p e r a t i o n s %
4477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4479 % CLISpecialOption() Applies operations that may involve empty image lists
4480 % and or stacks of image lists or image_info settings.
4482 % The classic operators of this type is -read, and image stack operators,
4483 % which can be applied to empty image lists.
4485 % Note: unlike other Operators, these may involve other special 'option'
4486 % character prefixes, other than simply '-' or '+'.
4488 % The format of the CLISpecialOption method is:
4490 % void CLISpecialOption(MagickCLI *cli_wand,const char *option,
4493 % A description of each parameter follows:
4495 % o cli_wand: the main CLI Wand to use.
4497 % o option: The special option (with any switch char) to process
4499 % o arg1: Argument for option, if required
4503 % CLISpecialOperator(cli_wand,"-read","rose:");
4505 % Or for handling command line arguments EG: +/-option ["arg1"]
4511 % option_info = GetCommandOptionInfo(argv[i]);
4512 % count=option_info->type;
4513 % option_type=option_info->flags;
4515 % if ( (option_type & SpecialOptionFlag) != 0 )
4516 % CLISpecialOperator(cli_wand,argv[i],
4517 % count>=1 ? argv[i+1] : (char *)NULL);
4522 WandExport void CLISpecialOperator(MagickCLI *cli_wand,
4523 const char *option, const char *arg1)
4525 #define _exception (cli_wand->wand.exception)
4527 assert(cli_wand != (MagickCLI *) NULL);
4528 assert(cli_wand->signature == WandSignature);
4529 assert(cli_wand->wand.signature == WandSignature);
4530 if (IfMagickTrue(cli_wand->wand.debug))
4531 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4533 if(cli_wand->wand.images != (Image *)NULL)
4534 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
4540 if (LocaleCompare("noop",option+1) == 0)
4542 if (LocaleCompare("sans",option+1) == 0)
4544 if (LocaleCompare("sans0",option+1) == 0)
4546 if (LocaleCompare("sans2",option+1) == 0)
4551 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4552 ( LocaleCompare("--",option) == 0 ) ) {
4561 /* Expand the filename argument (meta-characters or "@filelist" ) */
4565 status=ExpandFilenames(&argc,&argv);
4567 if (IfMagickFalse(status))
4568 CLIWandExceptArgReturn(ResourceLimitError,"MemoryAllocationFailed",
4569 option,GetExceptionMessage(errno));
4571 /* loop over expanded list reading images */
4572 for (i=0; i<argc; i++) {
4573 #if !USE_WAND_METHODS
4576 if (IfMagickTrue(cli_wand->wand.image_info->ping))
4577 new_images=PingImages(cli_wand->wand.image_info,argv[i],_exception);
4579 new_images=ReadImages(cli_wand->wand.image_info,argv[i],_exception);
4580 AppendImageToList(&cli_wand->wand.images, new_images);
4582 /* read images using MagickWand method - no ping */
4583 /* This is not working! - it locks up in a CPU loop! */
4584 MagickSetLastIterator(&cli_wand->wand);
4585 MagickReadImage(&cli_wand->wand,arg1);
4586 MagickSetFirstIterator(&cli_wand->wand);
4589 /* FUTURE: how do I free the expanded filename arguments??? */
4594 Parenthesis and Brace operations
4596 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
4597 /* link image and setting stacks - option is itself saved on stack! */
4598 (void) SetImageOption(cli_wand->wand.image_info,option+1,
4599 *option == '-' ? "true" : (char *) NULL);
4602 if (LocaleCompare("(",option) == 0) {
4603 /* stack 'push' images */
4611 node=cli_wand->image_list_stack;
4612 for ( ; node != (Stack *)NULL; node=node->next)
4614 if ( size >= MAX_STACK_DEPTH )
4615 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
4616 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4617 if (node == (Stack *) NULL)
4618 CLIWandExceptionReturn(ResourceLimitFatalError,
4619 "MemoryAllocationFailed",option);
4620 node->data = (void *)cli_wand->wand.images;
4621 cli_wand->wand.images = NewImageList();
4622 node->next = cli_wand->image_list_stack;
4623 cli_wand->image_list_stack = node;
4625 /* handle respect-parenthesis */
4626 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4627 "respect-parenthesis"))))
4628 option="{"; /* fall-thru so as to push image settings too */
4632 if (LocaleCompare("{",option) == 0) {
4633 /* stack 'push' of image_info settings */
4641 node=cli_wand->image_info_stack;
4642 for ( ; node != (Stack *)NULL; node=node->next)
4644 if ( size >= MAX_STACK_DEPTH )
4645 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
4646 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4647 if (node == (Stack *) NULL)
4648 CLIWandExceptionReturn(ResourceLimitFatalError,
4649 "MemoryAllocationFailed",option);
4651 node->data = (void *)cli_wand->wand.image_info;
4652 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4653 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4654 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4656 cli_wand->wand.image_info = (ImageInfo *)node->data;
4657 node = (Stack *)RelinquishMagickMemory(node);
4661 node->next = cli_wand->image_info_stack;
4662 cli_wand->image_info_stack = node;
4666 if (LocaleCompare(")",option) == 0) {
4667 /* pop images from stack */
4671 node = (Stack *)cli_wand->image_list_stack;
4672 if ( node == (Stack *)NULL)
4673 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
4674 cli_wand->image_list_stack = node->next;
4676 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4677 cli_wand->wand.images= (Image *)node->data;
4678 node = (Stack *)RelinquishMagickMemory(node);
4680 /* handle respect-parenthesis - of the previous 'pushed' settings */
4681 node = cli_wand->image_info_stack;
4682 if ( node != (Stack *)NULL)
4684 if (IfMagickTrue(IsStringTrue(GetImageOption(
4685 cli_wand->wand.image_info,"respect-parenthesis"))))
4686 option="}"; /* fall-thru so as to pop image settings too */
4693 if (LocaleCompare("}",option) == 0) {
4694 /* pop image_info settings from stack */
4698 node = (Stack *)cli_wand->image_info_stack;
4699 if ( node == (Stack *)NULL)
4700 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
4701 cli_wand->image_info_stack = node->next;
4703 (void) DestroyImageInfo(cli_wand->wand.image_info);
4704 cli_wand->wand.image_info = (ImageInfo *)node->data;
4705 node = (Stack *)RelinquishMagickMemory(node);
4707 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4708 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4709 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4713 if (LocaleCompare("clone",option+1) == 0) {
4719 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
4720 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
4721 if ( cli_wand->image_list_stack == (Stack *)NULL)
4722 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4723 new_images = (Image *)cli_wand->image_list_stack->data;
4724 if (new_images == (Image *) NULL)
4725 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4726 new_images=CloneImages(new_images,arg1,_exception);
4727 if (new_images == (Image *) NULL)
4728 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
4729 AppendImageToList(&cli_wand->wand.images,new_images);
4733 Informational Operations
4735 if (LocaleCompare("version",option+1) == 0) {
4736 (void) FormatLocaleFile(stdout,"Version: %s\n",
4737 GetMagickVersion((size_t *) NULL));
4738 (void) FormatLocaleFile(stdout,"Copyright: %s\n",
4739 GetMagickCopyright());
4740 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
4741 GetMagickFeatures());
4744 if (LocaleCompare("list",option+1) == 0) {
4745 /* FUTURE: This should really be built into the MagickCore
4746 It does not actually require any wand or images at all!
4751 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4753 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4758 case MagickCoderOptions:
4760 (void) ListCoderInfo((FILE *) NULL,_exception);
4763 case MagickColorOptions:
4765 (void) ListColorInfo((FILE *) NULL,_exception);
4768 case MagickConfigureOptions:
4770 (void) ListConfigureInfo((FILE *) NULL,_exception);
4773 case MagickDelegateOptions:
4775 (void) ListDelegateInfo((FILE *) NULL,_exception);
4778 case MagickFontOptions:
4780 (void) ListTypeInfo((FILE *) NULL,_exception);
4783 case MagickFormatOptions:
4784 (void) ListMagickInfo((FILE *) NULL,_exception);
4786 case MagickLocaleOptions:
4787 (void) ListLocaleInfo((FILE *) NULL,_exception);
4789 case MagickLogOptions:
4790 (void) ListLogInfo((FILE *) NULL,_exception);
4792 case MagickMagicOptions:
4793 (void) ListMagicInfo((FILE *) NULL,_exception);
4795 case MagickMimeOptions:
4796 (void) ListMimeInfo((FILE *) NULL,_exception);
4798 case MagickModuleOptions:
4799 (void) ListModuleInfo((FILE *) NULL,_exception);
4801 case MagickPolicyOptions:
4802 (void) ListPolicyInfo((FILE *) NULL,_exception);
4804 case MagickResourceOptions:
4805 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4807 case MagickThresholdOptions:
4808 (void) ListThresholdMaps((FILE *) NULL,_exception);
4811 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4819 // adjust stack handling
4820 // Other 'special' options this should handle
4821 // "region" "list" "version"
4822 // It does not do "exit" however as due to its side-effect requirements
4825 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
4827 CLIWandException(OptionError,"UnrecognizedOption",option);