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 (image->debug != MagickFalse)
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 (image->matte != MagickFalse))
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 */
228 /* control points and color values */
229 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
232 (void) ThrowMagickException(exception,GetMagickModule(),
233 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
234 "Invalid number of Arguments");
235 return( (Image *)NULL);
238 /* Allocate and fill in the floating point arguments */
239 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
240 sizeof(*sparse_arguments));
241 if (sparse_arguments == (double *) NULL) {
242 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
243 "MemoryAllocationFailed","%s","SparseColorOption");
244 return( (Image *)NULL);
246 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
247 sizeof(*sparse_arguments));
250 while( *p != '\0' && x < number_arguments ) {
252 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
253 if ( token[0] == '\0' ) break;
254 if ( isalpha((int) token[0]) || token[0] == '#' ) {
255 (void) ThrowMagickException(exception,GetMagickModule(),
256 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
257 "Color found, instead of X-coord");
261 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
263 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
264 if ( token[0] == '\0' ) break;
265 if ( isalpha((int) token[0]) || token[0] == '#' ) {
266 (void) ThrowMagickException(exception,GetMagickModule(),
267 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
268 "Color found, instead of Y-coord");
272 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
273 /* color name or function given in string argument */
274 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
275 if ( token[0] == '\0' ) break;
276 if ( isalpha((int) token[0]) || token[0] == '#' ) {
277 /* Color string given */
278 (void) QueryColorCompliance(token,AllCompliance,&color,
280 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
281 sparse_arguments[x++] = QuantumScale*color.red;
282 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
283 sparse_arguments[x++] = QuantumScale*color.green;
284 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
285 sparse_arguments[x++] = QuantumScale*color.blue;
286 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
287 (image->colorspace == CMYKColorspace))
288 sparse_arguments[x++] = QuantumScale*color.black;
289 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
290 (image->matte != MagickFalse))
291 sparse_arguments[x++] = QuantumScale*color.alpha;
294 /* Colors given as a set of floating point values - experimental */
295 /* NB: token contains the first floating point value to use! */
296 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
298 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
299 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
301 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
302 token[0] = ','; /* used this token - get another */
304 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
306 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
307 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
309 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
310 token[0] = ','; /* used this token - get another */
312 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
314 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
315 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
317 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
318 token[0] = ','; /* used this token - get another */
320 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
321 (image->colorspace == CMYKColorspace))
323 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
324 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
326 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
327 token[0] = ','; /* used this token - get another */
329 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
330 (image->matte != MagickFalse))
332 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
333 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
335 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
336 token[0] = ','; /* used this token - get another */
340 if ( number_arguments != x && !error ) {
341 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
342 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
343 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
344 return( (Image *)NULL);
347 return( (Image *)NULL);
349 /* Call the Sparse Color Interpolation function with the parsed arguments */
350 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
352 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
353 return( sparse_image );
357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 + A c q u i r e W a n d C L I %
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 % AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
368 % Wand). The given image_info and exception is included as is if provided.
370 % Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
373 % The format of the NewMagickWand method is:
375 % MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
376 % ExceptionInfo *exception)
379 WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
380 ExceptionInfo *exception)
385 /* precaution - as per NewMagickWand() */
387 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
388 const char *quantum = GetMagickQuantumDepth(&depth);
389 if (depth != MAGICKCORE_QUANTUM_DEPTH)
390 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
393 /* allocate memory for MgaickCLI */
394 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
395 if (cli_wand == (MagickCLI *) NULL)
397 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
398 GetExceptionMessage(errno));
399 return((MagickCLI *)NULL);
402 /* Initialize Wand Part of MagickCLI
403 FUTURE: this is a repeat of code from NewMagickWand()
404 However some parts may be given fro man external source!
406 cli_wand->wand.id=AcquireWandId();
407 (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
408 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
409 cli_wand->wand.images=NewImageList();
410 if ( image_info == (ImageInfo *)NULL)
411 cli_wand->wand.image_info=AcquireImageInfo();
413 cli_wand->wand.image_info=image_info;
414 if ( exception == (ExceptionInfo *)NULL)
415 cli_wand->wand.exception=AcquireExceptionInfo();
417 cli_wand->wand.exception=exception;
418 cli_wand->wand.debug=IsEventLogging();
419 cli_wand->wand.signature=WandSignature;
421 /* Initialize CLI Part of MagickCLI */
422 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
423 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
424 cli_wand->image_list_stack=(Stack *)NULL;
425 cli_wand->image_info_stack=(Stack *)NULL;
426 cli_wand->location="'%s' at unknown location";
427 cli_wand->filename="";
430 cli_wand->signature=WandSignature;
432 if (cli_wand->wand.debug != MagickFalse)
433 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
442 + D e s t r o y W a n d C L I %
446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448 % DestroyMagickCLI() destorys everything in a CLI wand, including image_info
449 % and any exceptions, if still present in the wand.
451 % The format of the NewMagickWand method is:
453 % MagickWand *DestroyMagickCLI()
454 % Exception *exception)
457 WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
462 assert(cli_wand != (MagickCLI *) NULL);
463 assert(cli_wand->signature == WandSignature);
464 assert(cli_wand->wand.signature == WandSignature);
465 if (cli_wand->wand.debug != MagickFalse)
466 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
468 /* Destroy CLI part of MagickCLI */
469 if (cli_wand->draw_info != (DrawInfo *) NULL )
470 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
471 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
472 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
473 while(cli_wand->image_list_stack != (Stack *)NULL)
475 node=cli_wand->image_list_stack;
476 cli_wand->image_list_stack=node->next;
477 (void) DestroyImageList((Image *)node->data);
478 (void) RelinquishMagickMemory(node);
480 while(cli_wand->image_info_stack != (Stack *)NULL)
482 node=cli_wand->image_info_stack;
483 cli_wand->image_info_stack=node->next;
484 (void) DestroyImageInfo((ImageInfo *)node->data);
485 (void) RelinquishMagickMemory(node);
487 cli_wand->signature=(~WandSignature);
489 /* Destroy Wand part MagickCLI */
490 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
491 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
492 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
493 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
494 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
495 RelinquishWandId(cli_wand->wand.id);
496 cli_wand->wand.signature=(~WandSignature);
498 return((MagickCLI *)NULL);
502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
506 + C L I C a t c h E x c e p t i o n %
510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512 % CLICatchException() will report exceptions, either just non-fatal warnings
513 % only, or all errors, according to 'all_execeptions' boolean argument.
515 % The function returns true is errors are fatal, in which case the caller
516 % should abort and re-call with an 'all_exceptions' argument of true before
519 % The cut-off level between fatal and non-fatal may be controlled by options
520 % (FUTURE), but defaults to 'Error' exceptions.
522 % The format of the CLICatchException method is:
524 % MagickBooleanType CLICatchException(MagickCLI *cli_wand,
525 % const MagickBooleanType all_exceptions );
528 WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
529 const MagickBooleanType all_exceptions )
533 assert(cli_wand != (MagickCLI *) NULL);
534 assert(cli_wand->signature == WandSignature);
535 assert(cli_wand->wand.signature == WandSignature);
536 if (cli_wand->wand.debug != MagickFalse)
537 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
539 // FUTURE: '-regard_warning' should make this more sensitive.
540 // Note pipelined options may like more control over this level
542 status = MagickFalse;
543 if (cli_wand->wand.exception->severity > ErrorException)
546 if ( status == MagickFalse || all_exceptions != MagickFalse )
547 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557 + C L I S e t t i n g O p t i o n I n f o %
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
563 % CLISettingOptionInfo() applies a single settings option into a CLI wand
564 % holding the image_info, draw_info, quantize_info structures that will be
565 % used when processing the images.
567 % These options do no require images to be present in the CLI wand for them
568 % to be able to be set, in which case they will generally be applied to image
569 % that are read in later
571 % Options handled by this function are listed in CommandOptions[] of
572 % "option.c" that is one of "SettingOptionFlags" option flags.
574 % The format of the CLISettingOptionInfo method is:
576 % void CLISettingOptionInfo(MagickCLI *cli_wand,
577 % const char *option, const char *arg)
579 % A description of each parameter follows:
581 % o cli_wand: structure holding settings to be applied
583 % o option: The option string to be set
585 % o arg: The single argument used to set this option.
589 % CLISettingOptionInfo(cli_wand, "-background", "Red"); // set value
590 % CLISettingOptionInfo(cli_wand, "-adjoin", NULL); // set boolean
591 % CLISettingOptionInfo(cli_wand, "+adjoin", NULL); // unset
593 % Or for handling command line arguments EG: +/-option ["arg"]
598 % option_info = GetCommandOptionInfo(argv[i]);
599 % count=option_info->type;
600 % option_type=option_info->flags;
602 % if ( (option_type & SettingOperatorOptionFlags) != 0 )
603 % CLISettingOptionInfo(cli_wand, argv[i],
604 % (count>0) ? argv[i+1] : (char *)NULL);
608 WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
609 const char *option,const char *arg)
611 assert(cli_wand != (MagickCLI *) NULL);
612 assert(cli_wand->signature == WandSignature);
613 assert(cli_wand->wand.signature == WandSignature);
614 if (cli_wand->wand.debug != MagickFalse)
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 ArgOption(def) (IfSetOption?arg:(const char *)(def))
623 #define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
624 #define ArgBooleanNot (IfSetOption?MagickFalse:MagickTrue)
630 if (LocaleCompare("adjoin",option+1) == 0)
632 image_info->adjoin = ArgBoolean;
635 if (LocaleCompare("affine",option+1) == 0)
637 /* DEPRECIATED: draw_info setting only: for -draw and -transform */
639 (void) ParseAffineGeometry(arg,&draw_info->affine,exception);
641 GetAffineMatrix(&draw_info->affine);
644 if (LocaleCompare("antialias",option+1) == 0)
646 image_info->antialias =
647 draw_info->stroke_antialias =
648 draw_info->text_antialias = ArgBoolean;
651 if (LocaleCompare("attenuate",option+1) == 0)
653 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
656 if (LocaleCompare("authenticate",option+1) == 0)
658 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
665 if (LocaleCompare("background",option+1) == 0)
667 /* FUTURE: both image_info attribute & ImageOption in use!
668 image_info only used directly for generating new images.
669 SyncImageSettings() used to set per-image attribute.
671 FUTURE: if image_info->background_color is not set then
672 we should fall back to image
673 Note that +background, means fall-back to image background
674 and only if not set fall back to BackgroundColor const.
676 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
677 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
678 &image_info->background_color,exception);
681 if (LocaleCompare("bias",option+1) == 0)
683 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
684 as it is actually rarely used except in direct convolve operations
685 Usage outside a direct convolve operation is actally non-sensible!
687 SyncImageSettings() used to set per-image attribute.
689 (void) SetImageOption(image_info,option+1,ArgOption("0"));
692 if (LocaleCompare("black-point-compensation",option+1) == 0)
694 /* Used as a image chromaticity setting
695 SyncImageSettings() used to set per-image attribute.
697 (void) SetImageOption(image_info,option+1,
698 IfSetOption ? "true" : "false" );
701 if (LocaleCompare("blue-primary",option+1) == 0)
703 /* Image chromaticity X,Y NB: Y=X if Y not defined
704 Used by many coders including PNG
705 SyncImageSettings() used to set per-image attribute.
707 (void) SetImageOption(image_info,option+1,ArgOption("0.0"));
710 if (LocaleCompare("bordercolor",option+1) == 0)
712 /* FUTURE: both image_info attribute & ImageOption in use!
713 SyncImageSettings() used to set per-image attribute.
717 (void) SetImageOption(image_info,option+1,arg);
718 (void) QueryColorCompliance(arg,AllCompliance,
719 &image_info->border_color,exception);
720 (void) QueryColorCompliance(arg,AllCompliance,
721 &draw_info->border_color,exception);
724 (void) DeleteImageOption(image_info,option+1);
725 (void) QueryColorCompliance(BorderColor,AllCompliance,
726 &image_info->border_color,exception);
727 (void) QueryColorCompliance(BorderColor,AllCompliance,
728 &draw_info->border_color,exception);
731 if (LocaleCompare("box",option+1) == 0)
733 /* DEPRECIATED - now "undercolor" */
734 CLISettingOptionInfo(cli_wand,"undercolor",arg);
741 if (LocaleCompare("cache",option+1) == 0)
746 limit=MagickResourceInfinity;
747 if (LocaleCompare("unlimited",arg) != 0)
748 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg,100.0);
749 (void) SetMagickResourceLimit(MemoryResource,limit);
750 (void) SetMagickResourceLimit(MapResource,2*limit);
753 if (LocaleCompare("caption",option+1) == 0)
755 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
758 if (LocaleCompare("channel",option+1) == 0)
760 /* FUTURE: -channel mask {vaules}
761 This is applied to images in SimpleImageOperator!!!
762 Move it to SyncImageSettings() - or alternative
764 image_info->channel=(ChannelType) (
765 IfSetOption ? ParseChannelOption(arg) : DefaultChannels );
768 if (LocaleCompare("colorspace",option+1) == 0)
770 /* Setting used for new images via AquireImage()
771 But also used as a SimpleImageOperator
772 Undefined colorspace means don't modify images on
773 read or as a operation */
774 image_info->colorspace=(ColorspaceType) ParseCommandOption(
775 MagickColorspaceOptions,MagickFalse,ArgOption("undefined"));
778 if (LocaleCompare("comment",option+1) == 0)
780 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
783 if (LocaleCompare("compose",option+1) == 0)
785 /* FUTURE: image_info should be used,
786 SyncImageSettings() used to set per-image attribute. - REMOVE
788 This setting should NOT be used to set image 'compose'
789 "-layer" operators shoud use image_info if defined otherwise
790 they should use a per-image compose setting.
792 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
793 image_info->compose=(CompositeOperator) ParseCommandOption(
794 MagickComposeOptions,MagickFalse,ArgOption("undefined"));
797 if (LocaleCompare("compress",option+1) == 0)
799 /* FUTURE: What should be used? image_info or ImageOption ???
800 The former is more efficent, but Crisy prefers the latter!
801 SyncImageSettings() used to set per-image attribute.
803 The coders appears to use image_info, not Image_Option
804 however the image attribute (for save) is set from the
807 Note that "undefined" is a different setting to "none".
809 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
810 image_info->compression=(CompressionType) ParseCommandOption(
811 MagickCompressOptions,MagickFalse,ArgOption("undefined"));
818 if (LocaleCompare("debug",option+1) == 0)
820 /* SyncImageSettings() used to set per-image attribute. */
821 (void) SetLogEventMask(ArgOption("none"));
822 image_info->debug=IsEventLogging(); /* extract logging*/
823 cli_wand->wand.debug=IsEventLogging();
826 if (LocaleCompare("define",option+1) == 0)
828 /* DefineImageOption() equals SetImageOption() but with '='
829 It does not however set individual image options.
830 "-set" will set individual image options as well!
832 if (LocaleNCompare(arg,"registry:",9) == 0)
835 (void) DefineImageRegistry(StringRegistryType,arg+9,exception);
837 (void) DeleteImageRegistry(arg+9);
841 (void) DefineImageOption(image_info,arg);
843 (void) DeleteImageOption(image_info,arg);
846 if (LocaleCompare("delay",option+1) == 0)
848 /* Only used for new images via AcquireImage()
849 FUTURE: Option should also be used for "-morph" (color morphing)
851 (void) SetImageOption(image_info,option+1,ArgOption("0"));
854 if (LocaleCompare("density",option+1) == 0)
856 /* FUTURE: strings used in image_info attr and draw_info!
857 Basically as density can be in a XxY form!
859 SyncImageSettings() used to set per-image attribute.
861 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
862 (void) CloneString(&image_info->density,ArgOption(NULL));
863 (void) CloneString(&draw_info->density,image_info->density);
866 if (LocaleCompare("depth",option+1) == 0)
868 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
869 SyncImageSettings() used to set per-image attribute.
871 image_info->depth=IfSetOption?StringToUnsignedLong(arg)
872 :MAGICKCORE_QUANTUM_DEPTH;
875 if (LocaleCompare("direction",option+1) == 0)
877 /* Image Option is only used to set draw_info */
878 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
879 draw_info->direction=(DirectionType) ParseCommandOption(
880 MagickDirectionOptions,MagickFalse,
881 ArgOption("undefined"));
884 if (LocaleCompare("display",option+1) == 0)
886 (void) CloneString(&image_info->server_name,ArgOption(NULL));
887 (void) CloneString(&draw_info->server_name,image_info->server_name);
890 if (LocaleCompare("dispose",option+1) == 0)
892 /* only used in setting new images */
893 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
896 if (LocaleCompare("dither",option+1) == 0)
898 /* image_info attr (on/off), quantize_info attr (on/off)
899 but also ImageInfo and quantize_info method!
900 FUTURE: merge the duality of the dithering options
902 image_info->dither = quantize_info->dither = ArgBoolean;
903 (void) SetImageOption(image_info,option+1,ArgOption("none"));
904 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
905 MagickDitherOptions,MagickFalse,ArgOption("none"));
906 if (quantize_info->dither_method == NoDitherMethod)
907 image_info->dither = quantize_info->dither = MagickFalse;
914 if (LocaleCompare("encoding",option+1) == 0)
916 (void) CloneString(&draw_info->encoding,ArgOption("undefined"));
917 (void) SetImageOption(image_info,option+1,draw_info->encoding);
920 if (LocaleCompare("endian",option+1) == 0)
922 /* Both image_info attr and ImageInfo */
923 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
924 image_info->endian=(EndianType) ParseCommandOption(
925 MagickEndianOptions,MagickFalse,ArgOption("undefined"));
928 if (LocaleCompare("extract",option+1) == 0)
930 (void) CloneString(&image_info->extract,ArgOption(NULL));
937 if (LocaleCompare("family",option+1) == 0)
939 (void) CloneString(&draw_info->family,ArgOption(NULL));
942 if (LocaleCompare("fill",option+1) == 0)
944 /* Set "fill" OR "fill-pattern" in draw_info
945 The original fill color is preserved if a fill-pattern is given.
946 That way it does not effect other operations that directly using
947 the fill color and, can be retored using "+tile".
961 value = ArgOption("none");
962 (void) SetImageOption(image_info,option+1,value);
963 if (draw_info->fill_pattern != (Image *) NULL)
964 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
966 /* is it a color or a image? -- ignore exceptions */
967 sans=AcquireExceptionInfo();
968 status=QueryColorCompliance(value,AllCompliance,&color,sans);
969 sans=DestroyExceptionInfo(sans);
971 if (status == MagickFalse)
972 draw_info->fill_pattern=GetImageCache(image_info,value,exception);
974 draw_info->fill=color;
977 if (LocaleCompare("filter",option+1) == 0)
979 /* SyncImageSettings() used to set per-image attribute. */
980 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
983 if (LocaleCompare("font",option+1) == 0)
985 (void) CloneString(&draw_info->font,ArgOption(NULL));
986 (void) CloneString(&image_info->font,draw_info->font);
989 if (LocaleCompare("format",option+1) == 0)
991 /* FUTURE: why the ping test, you could set ping after this! */
996 for (q=strchr(arg,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
997 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
998 image_info->ping=MagickFalse;
1000 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1003 if (LocaleCompare("fuzz",option+1) == 0)
1005 /* Option used to set image fuzz! unless blank canvas (from color)
1006 Image attribute used for color compare operations
1007 SyncImageSettings() used to set per-image attribute.
1009 Can't find anything else using image_info->fuzz directly!
1013 image_info->fuzz=StringToDoubleInterval(arg,(double)
1015 (void) SetImageOption(image_info,option+1,arg);
1018 image_info->fuzz=0.0;
1019 (void) SetImageOption(image_info,option+1,"0");
1026 if (LocaleCompare("gravity",option+1) == 0)
1028 /* SyncImageSettings() used to set per-image attribute. */
1029 (void) SetImageOption(image_info,option+1,ArgOption("none"));
1030 draw_info->gravity=(GravityType) ParseCommandOption(
1031 MagickGravityOptions,MagickFalse,ArgOption("none"));
1034 if (LocaleCompare("green-primary",option+1) == 0)
1036 /* Image chromaticity X,Y NB: Y=X if Y not defined
1037 SyncImageSettings() used to set per-image attribute.
1038 Used directly by many coders
1040 (void) SetImageOption(image_info,option+1,ArgOption("0.0"));
1047 if (LocaleCompare("intent",option+1) == 0)
1049 /* Only used by coders: MIFF, MPC, BMP, PNG
1050 and for image profile call to AcquireTransformThreadSet()
1051 SyncImageSettings() used to set per-image attribute.
1053 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
1056 if (LocaleCompare("interlace",option+1) == 0)
1058 /* image_info is directly used by coders (so why an image setting?)
1059 SyncImageSettings() used to set per-image attribute.
1061 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
1062 image_info->interlace=(InterlaceType) ParseCommandOption(
1063 MagickInterlaceOptions,MagickFalse,ArgOption("undefined"));
1066 if (LocaleCompare("interline-spacing",option+1) == 0)
1068 (void) SetImageOption(image_info,option+1, ArgOption(NULL));
1069 draw_info->interline_spacing=StringToDouble(ArgOption("0"),
1073 if (LocaleCompare("interpolate",option+1) == 0)
1075 /* SyncImageSettings() used to set per-image attribute. */
1076 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
1079 if (LocaleCompare("interword-spacing",option+1) == 0)
1081 (void) SetImageOption(image_info,option+1, ArgOption(NULL));
1082 draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
1089 if (LocaleCompare("kerning",option+1) == 0)
1091 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1092 draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
1099 if (LocaleCompare("label",option+1) == 0)
1101 /* only used for new images - not in SyncImageOptions() */
1102 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1105 if (LocaleCompare("log",option+1) == 0)
1108 (void) SetLogFormat(arg);
1111 if (LocaleCompare("loop",option+1) == 0)
1113 /* SyncImageSettings() used to set per-image attribute. */
1114 (void) SetImageOption(image_info,option+1,ArgOption("0"));
1121 if (LocaleCompare("mattecolor",option+1) == 0)
1123 /* SyncImageSettings() used to set per-image attribute. */
1124 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1125 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
1126 &image_info->matte_color,exception);
1129 if (LocaleCompare("monitor",option+1) == 0)
1131 (void) SetImageInfoProgressMonitor(image_info, IfSetOption?
1132 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
1135 if (LocaleCompare("monochrome",option+1) == 0)
1137 /* Setting (for some input coders)
1138 But also a special 'type' operator
1140 image_info->monochrome= ArgBoolean;
1147 if (LocaleCompare("orient",option+1) == 0)
1149 /* Is not used when defining for new images.
1150 This makes it more of a 'operation' than a setting
1151 FUTURE: make set meta-data operator instead.
1152 SyncImageSettings() used to set per-image attribute.
1154 (void) SetImageOption(image_info,option+1, ArgOption(NULL));
1155 image_info->orientation=(InterlaceType) ParseCommandOption(
1156 MagickOrientationOptions,MagickFalse,ArgOption("undefined"));
1162 if (LocaleCompare("page",option+1) == 0)
1164 /* Only used for new images and image generators
1165 SyncImageSettings() used to set per-image attribute. ?????
1166 That last is WRONG!!!!
1170 page[MaxTextExtent];
1183 (void) DeleteImageOption(image_info,option+1);
1184 (void) CloneString(&image_info->page,(char *) NULL);
1187 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1188 image_option=GetImageOption(image_info,"page");
1189 if (image_option != (const char *) NULL)
1190 flags=ParseAbsoluteGeometry(image_option,&geometry);
1191 canonical_page=GetPageGeometry(arg);
1192 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1193 canonical_page=DestroyString(canonical_page);
1194 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1195 (unsigned long) geometry.width,(unsigned long) geometry.height);
1196 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1197 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1198 (unsigned long) geometry.width,(unsigned long) geometry.height,
1199 (long) geometry.x,(long) geometry.y);
1200 (void) SetImageOption(image_info,option+1,page);
1201 (void) CloneString(&image_info->page,page);
1204 if (LocaleCompare("ping",option+1) == 0)
1206 image_info->ping = ArgBoolean;
1209 if (LocaleCompare("pointsize",option+1) == 0)
1211 image_info->pointsize=draw_info->pointsize=
1212 StringToDouble(ArgOption("12"),(char **) NULL);
1215 if (LocaleCompare("precision",option+1) == 0)
1217 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
1220 /* FUTURE: Only the 'preview' coder appears to use this
1221 * Depreciate the coder? Leaving only the 'preview' operator.
1222 if (LocaleCompare("preview",option+1) == 0)
1224 image_info->preview_type=UndefinedPreview;
1226 image_info->preview_type=(PreviewType) ParseCommandOption(
1227 MagickPreviewOptions,MagickFalse,arg);
1235 if (LocaleCompare("quality",option+1) == 0)
1237 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1238 image_info->quality=UNDEFINED_COMPRESSION_QUALITY;
1240 image_info->quality=StringToUnsignedLong(arg);
1243 if (LocaleCompare("quantize",option+1) == 0)
1245 /* Just a set direct in quantize_info */
1246 quantize_info->colorspace=UndefinedColorspace;
1248 quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
1249 MagickColorspaceOptions,MagickFalse,arg);
1252 if (LocaleCompare("quiet",option+1) == 0)
1254 /* FUTURE: if two -quiet is performed you can not do +quiet! */
1255 static WarningHandler
1256 warning_handler = (WarningHandler) NULL;
1259 tmp = SetWarningHandler((WarningHandler) NULL);
1261 if ( tmp != (WarningHandler) NULL)
1262 warning_handler = tmp; /* remember the old handler */
1263 if (!IfSetOption) /* set the old handler */
1264 warning_handler=SetWarningHandler(warning_handler);
1271 if (LocaleCompare("red-primary",option+1) == 0)
1273 /* Image chromaticity X,Y NB: Y=X if Y not defined
1275 SyncImageSettings() used to set per-image attribute.
1277 (void) SetImageOption(image_info,option+1,ArgOption("0.0"));
1280 if (LocaleCompare("render",option+1) == 0)
1282 /* draw_info only setting */
1283 draw_info->render= ArgBooleanNot;
1286 if (LocaleCompare("respect-parenthesis",option+1) == 0)
1288 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1295 if (LocaleCompare("sampling-factor",option+1) == 0)
1297 /* FUTURE: should be converted to jpeg:sampling_factor */
1298 (void) CloneString(&image_info->sampling_factor,ArgOption(NULL));
1301 if (LocaleCompare("scene",option+1) == 0)
1303 /* SyncImageSettings() used to set per-image attribute.
1306 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1307 image_info->scene=StringToUnsignedLong(ArgOption("0"));
1310 if (LocaleCompare("seed",option+1) == 0)
1312 SeedPseudoRandomGenerator(
1313 IfSetOption ? (size_t) StringToUnsignedLong(arg)
1314 : (size_t) time((time_t *) NULL) );
1317 if (LocaleCompare("size",option+1) == 0)
1319 /* FUTURE: string in image_info -- convert to Option ???
1320 Look at the special handling for "size" in SetImageOption()
1322 (void) CloneString(&image_info->size,ArgOption(NULL));
1325 if (LocaleCompare("stretch",option+1) == 0)
1327 draw_info->stretch=(StretchType) ParseCommandOption(
1328 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
1331 if (LocaleCompare("stroke",option+1) == 0)
1333 /* set stroke color OR stroke-pattern
1334 UPDATE: ensure stroke color is not destroyed is a pattern
1335 is given. Just in case the color is also used for other purposes.
1349 value = ArgOption("none");
1350 (void) SetImageOption(image_info,option+1,value);
1351 if (draw_info->stroke_pattern != (Image *) NULL)
1352 draw_info->stroke_pattern=DestroyImage(draw_info->stroke_pattern);
1354 /* is it a color or a image? -- ignore exceptions */
1355 sans=AcquireExceptionInfo();
1356 status=QueryColorCompliance(value,AllCompliance,&color,sans);
1357 sans=DestroyExceptionInfo(sans);
1359 if (status == MagickFalse)
1360 draw_info->stroke_pattern=GetImageCache(image_info,value,exception);
1362 draw_info->stroke=color;
1365 if (LocaleCompare("strokewidth",option+1) == 0)
1367 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1368 draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1372 if (LocaleCompare("style",option+1) == 0)
1374 draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1375 MagickFalse,ArgOption("undefined"));
1378 if (LocaleCompare("synchronize",option+1) == 0)
1380 image_info->synchronize = ArgBoolean;
1387 if (LocaleCompare("taint",option+1) == 0)
1389 /* SyncImageSettings() used to set per-image attribute. */
1390 (void) SetImageOption(image_info,option+1,
1391 IfSetOption ? "true" : "false");
1394 if (LocaleCompare("texture",option+1) == 0)
1396 /* FUTURE: move image_info string to option splay-tree */
1397 (void) CloneString(&image_info->texture,ArgOption(NULL));
1400 if (LocaleCompare("tile",option+1) == 0)
1402 draw_info->fill_pattern=IfSetOption
1403 ?GetImageCache(image_info,arg,exception)
1404 :DestroyImage(draw_info->fill_pattern);
1407 if (LocaleCompare("tile-offset",option+1) == 0)
1409 /* SyncImageSettings() used to set per-image attribute. ??? */
1410 (void) SetImageOption(image_info,option+1,ArgOption("0"));
1413 if (LocaleCompare("transparent-color",option+1) == 0)
1415 /* FUTURE: both image_info attribute & ImageOption in use!
1416 image_info only used for generating new images.
1417 SyncImageSettings() used to set per-image attribute.
1419 Note that +transparent-color, means fall-back to image
1420 attribute so ImageOption is deleted, not set to a default.
1422 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1423 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1424 &image_info->transparent_color,exception);
1427 if (LocaleCompare("treedepth",option+1) == 0)
1429 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1430 quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1433 if (LocaleCompare("type",option+1) == 0)
1435 /* SyncImageSettings() used to set per-image attribute. */
1436 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1437 image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1438 MagickFalse,ArgOption("undefined"));
1445 if (LocaleCompare("undercolor",option+1) == 0)
1447 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1448 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1449 &draw_info->undercolor,exception);
1452 if (LocaleCompare("units",option+1) == 0)
1454 /* SyncImageSettings() used to set per-image attribute.
1455 Should this effect draw_info X and Y resolution?
1456 FUTURE: this probably should be part of the density setting
1458 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1459 image_info->units=(ResolutionType) ParseCommandOption(
1460 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
1467 if (LocaleCompare("verbose",option+1) == 0)
1469 /* FUTURE: Also an image artifact, set in Simple Operators.
1470 But artifact is only used in verbose output.
1472 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1473 image_info->verbose= ArgBoolean;
1474 image_info->ping=MagickFalse; /* verbose can't be a ping */
1477 if (LocaleCompare("view",option+1) == 0)
1479 /* FUTURE: Convert from image_info to ImageOption
1480 Only used by coder FPX
1482 (void) CloneString(&image_info->view,ArgOption(NULL));
1485 if (LocaleCompare("virtual-pixel",option+1) == 0)
1487 /* SyncImageSettings() used to set per-image attribute.
1488 This is VERY deep in the image caching structure.
1490 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1497 if (LocaleCompare("weight",option+1) == 0)
1499 /* Just what does using a font 'weight' do ???
1500 There is no "-list weight" output (reference manual says there is)
1504 draw_info->weight=StringToUnsignedLong(arg);
1505 if (LocaleCompare(arg,"all") == 0)
1506 draw_info->weight=0;
1507 if (LocaleCompare(arg,"bold") == 0)
1508 draw_info->weight=700;
1509 if (LocaleCompare(arg,"bolder") == 0)
1510 if (draw_info->weight <= 800)
1511 draw_info->weight+=100;
1512 if (LocaleCompare(arg,"lighter") == 0)
1513 if (draw_info->weight >= 100)
1514 draw_info->weight-=100;
1515 if (LocaleCompare(arg,"normal") == 0)
1516 draw_info->weight=400;
1519 if (LocaleCompare("white-point",option+1) == 0)
1521 /* Used as a image chromaticity setting
1522 SyncImageSettings() used to set per-image attribute.
1524 (void) SetImageOption(image_info,option+1,ArgOption("0.0"));
1535 #undef quantize_info
1544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1548 + C L I S i m p l e O p e r a t o r I m a g e s %
1552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554 % WandSimpleOperatorImages() applys one simple image operation given to all
1555 % the images in the CLI wand, with the settings that was previously saved in
1558 % It is assumed that any per-image settings are up-to-date with respect to
1559 % extra settings that were already saved in the wand.
1561 % The format of the WandSimpleOperatorImage method is:
1563 % void CLISimpleOperatorImages(MagickCLI *cli_wand,
1564 % const char *option, const char *arg1, const char *arg2)
1566 % A description of each parameter follows:
1568 % o cli_wand: structure holding settings and images to be operated on
1570 % o option: The option string for the operation
1572 % o arg1, arg2: optional argument strings to the operation
1574 % Any problems will be added to the 'exception' entry of the given wand.
1578 % CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1579 % CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1580 % CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
1582 % Or for handling command line arguments EG: +/-option ["arg"]
1588 % option_info = GetCommandOptionInfo(argv[i]);
1589 % count=option_info->type;
1590 % option_type=option_info->flags;
1592 % if ( (option_type & SimpleOperatorOptionFlag) != 0 )
1593 % CLISimpleOperatorImages(cli_wand, argv[i],
1594 % count>=1 ? argv[i+1] : (char *)NULL,
1595 % count>=2 ? argv[i+2] : (char *)NULL );
1601 Internal subrountine to apply one simple image operation to the current
1602 image pointed to by the CLI wand.
1604 The image in the list may be modified in three different ways...
1605 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1606 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1607 * one image replace by a list of images (-separate and -crop only!)
1609 In each case the result replaces the single original image in the list, as
1610 well as the pointer to the modified image (last image added if replaced by a
1611 list of images) is returned.
1613 As the image pointed to may be replaced, the first image in the list may
1614 also change. GetFirstImageInList() should be used by caller if they wish
1615 return the Image pointer to the first image in list.
1617 static void CLISimpleOperatorImage(MagickCLI *cli_wand,
1618 const char *option, const char *arg1, const char *arg2)
1632 #define image_info (cli_wand->wand.image_info)
1633 #define image (cli_wand->wand.images)
1634 #define exception (cli_wand->wand.exception)
1635 #define draw_info (cli_wand->draw_info)
1636 #define quantize_info (cli_wand->quantize_info)
1637 #define IfNormalOp (*option=='-')
1638 #define IfPlusOp (*option!='-')
1639 #define normal_op (IfNormalOp?MagickTrue:MagickFalse)
1640 #define plus_alt_op (IfNormalOp?MagickFalse:MagickTrue)
1642 assert(cli_wand != (MagickCLI *) NULL);
1643 assert(cli_wand->signature == WandSignature);
1644 assert(cli_wand->wand.signature == WandSignature);
1645 assert(image != (Image *) NULL); /* an image must be present */
1646 if (cli_wand->wand.debug != MagickFalse)
1647 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
1649 SetGeometryInfo(&geometry_info);
1651 new_image = (Image *)NULL; /* the replacement image, if not null at end */
1653 /* FUTURE: We may need somthing a little more optimized than this!
1654 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1656 (void) SyncImageSettings(image_info,image,exception);
1658 switch (*(option+1))
1662 if (LocaleCompare("adaptive-blur",option+1) == 0)
1664 flags=ParseGeometry(arg1,&geometry_info);
1665 if ((flags & SigmaValue) == 0)
1666 geometry_info.sigma=1.0;
1667 if ((flags & XiValue) == 0)
1668 geometry_info.xi=0.0;
1669 new_image=AdaptiveBlurImage(image,geometry_info.rho,
1670 geometry_info.sigma,geometry_info.xi,exception);
1673 if (LocaleCompare("adaptive-resize",option+1) == 0)
1675 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
1676 new_image=AdaptiveResizeImage(image,geometry.width,geometry.height,
1680 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
1682 flags=ParseGeometry(arg1,&geometry_info);
1683 if ((flags & SigmaValue) == 0)
1684 geometry_info.sigma=1.0;
1685 if ((flags & XiValue) == 0)
1686 geometry_info.xi=0.0;
1687 new_image=AdaptiveSharpenImage(image,geometry_info.rho,
1688 geometry_info.sigma,geometry_info.xi,exception);
1691 if (LocaleCompare("alpha",option+1) == 0)
1696 alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
1698 (void) SetImageAlphaChannel(image,alpha_type,exception);
1701 if (LocaleCompare("annotate",option+1) == 0)
1705 geometry[MaxTextExtent];
1707 SetGeometryInfo(&geometry_info);
1708 flags=ParseGeometry(arg1,&geometry_info);
1709 if ((flags & SigmaValue) == 0)
1710 geometry_info.sigma=geometry_info.rho;
1711 text=InterpretImageProperties(image_info,image,arg2,
1713 if (text == (char *) NULL)
1715 (void) CloneString(&draw_info->text,text);
1716 text=DestroyString(text);
1717 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1718 geometry_info.xi,geometry_info.psi);
1719 (void) CloneString(&draw_info->geometry,geometry);
1720 draw_info->affine.sx=cos(DegreesToRadians(
1721 fmod(geometry_info.rho,360.0)));
1722 draw_info->affine.rx=sin(DegreesToRadians(
1723 fmod(geometry_info.rho,360.0)));
1724 draw_info->affine.ry=(-sin(DegreesToRadians(
1725 fmod(geometry_info.sigma,360.0))));
1726 draw_info->affine.sy=cos(DegreesToRadians(
1727 fmod(geometry_info.sigma,360.0)));
1728 (void) AnnotateImage(image,draw_info,exception);
1729 GetAffineMatrix(&draw_info->affine);
1732 if (LocaleCompare("auto-gamma",option+1) == 0)
1734 (void) AutoGammaImage(image,exception);
1737 if (LocaleCompare("auto-level",option+1) == 0)
1739 (void) AutoLevelImage(image,exception);
1742 if (LocaleCompare("auto-orient",option+1) == 0)
1744 /* This should probbaly be a MagickCore function */
1745 switch (image->orientation)
1747 case TopRightOrientation:
1749 new_image=FlopImage(image,exception);
1752 case BottomRightOrientation:
1754 new_image=RotateImage(image,180.0,exception);
1757 case BottomLeftOrientation:
1759 new_image=FlipImage(image,exception);
1762 case LeftTopOrientation:
1764 new_image=TransposeImage(image,exception);
1767 case RightTopOrientation:
1769 new_image=RotateImage(image,90.0,exception);
1772 case RightBottomOrientation:
1774 new_image=TransverseImage(image,exception);
1777 case LeftBottomOrientation:
1779 new_image=RotateImage(image,270.0,exception);
1785 if (new_image != (Image *) NULL)
1786 new_image->orientation=TopLeftOrientation;
1793 if (LocaleCompare("black-threshold",option+1) == 0)
1795 (void) BlackThresholdImage(image,arg1,exception);
1798 if (LocaleCompare("blue-shift",option+1) == 0)
1800 geometry_info.rho=1.5;
1802 flags=ParseGeometry(arg1,&geometry_info);
1803 new_image=BlueShiftImage(image,geometry_info.rho,exception);
1806 if (LocaleCompare("blur",option+1) == 0)
1808 /* FUTURE: use of "bias" in a blur is non-sensible */
1809 flags=ParseGeometry(arg1,&geometry_info);
1810 if ((flags & SigmaValue) == 0)
1811 geometry_info.sigma=1.0;
1812 if ((flags & XiValue) == 0)
1813 geometry_info.xi=0.0;
1814 new_image=BlurImage(image,geometry_info.rho,
1815 geometry_info.sigma,geometry_info.xi,exception);
1818 if (LocaleCompare("border",option+1) == 0)
1826 value=GetImageOption(image_info,"compose");
1827 if (value != (const char *) NULL)
1828 compose=(CompositeOperator) ParseCommandOption(
1829 MagickComposeOptions,MagickFalse,value);
1831 compose=OverCompositeOp; /* use Over not image->compose */
1833 flags=ParsePageGeometry(image,arg1,&geometry,exception);
1834 if ((flags & SigmaValue) == 0)
1835 geometry.height=geometry.width;
1836 new_image=BorderImage(image,&geometry,compose,exception);
1839 if (LocaleCompare("brightness-contrast",option+1) == 0)
1851 flags=ParseGeometry(arg1,&geometry_info);
1852 brightness=geometry_info.rho;
1854 if ((flags & SigmaValue) != 0)
1855 contrast=geometry_info.sigma;
1856 (void) BrightnessContrastImage(image,brightness,contrast,
1864 if (LocaleCompare("cdl",option+1) == 0)
1867 *color_correction_collection;
1870 Color correct with a color decision list.
1872 color_correction_collection=FileToString(arg1,~0,exception);
1873 if (color_correction_collection == (char *) NULL)
1875 (void) ColorDecisionListImage(image,color_correction_collection,
1879 if (LocaleCompare("channel",option+1) == 0)
1881 /* The "channel" setting has already been set
1882 FUTURE: This probably should be part of WandSettingOptionInfo()
1883 or SyncImageSettings().
1885 SetPixelChannelMapMask(image,image_info->channel);
1888 if (LocaleCompare("channel-extract",option+1) == 0)
1890 puts("stand by...");
1893 if (LocaleCompare("channel-swap",option+1) == 0)
1895 puts("stand by...");
1898 if (LocaleCompare("charcoal",option+1) == 0)
1900 flags=ParseGeometry(arg1,&geometry_info);
1901 if ((flags & SigmaValue) == 0)
1902 geometry_info.sigma=1.0;
1903 if ((flags & XiValue) == 0)
1904 geometry_info.xi=1.0;
1905 new_image=CharcoalImage(image,geometry_info.rho,
1906 geometry_info.sigma,geometry_info.xi,exception);
1909 if (LocaleCompare("chop",option+1) == 0)
1911 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
1912 new_image=ChopImage(image,&geometry,exception);
1915 if (LocaleCompare("clamp",option+1) == 0)
1917 (void) ClampImage(image,exception);
1920 if (LocaleCompare("clip",option+1) == 0)
1923 (void) ClipImage(image,exception);
1924 else /* "+mask" remove the write mask */
1925 (void) SetImageMask(image,(Image *) NULL,exception);
1928 if (LocaleCompare("clip-mask",option+1) == 0)
1946 /* "+clip-mask" Remove the write mask */
1947 (void) SetImageMask(image,(Image *) NULL,exception);
1950 mask_image=GetImageCache(image_info,arg1,exception);
1951 if (mask_image == (Image *) NULL)
1953 if (SetImageStorageClass(mask_image,DirectClass,exception)
1956 /* Create a write mask from cli_wandp-mask image */
1957 /* FUTURE: use Alpha operations instead and create a Grey Image */
1958 mask_view=AcquireCacheView(mask_image);
1959 for (y=0; y < (ssize_t) mask_image->rows; y++)
1961 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1963 if (q == (Quantum *) NULL)
1965 for (x=0; x < (ssize_t) mask_image->columns; x++)
1967 if (mask_image->matte == MagickFalse)
1968 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1969 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1970 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1971 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1972 q+=GetPixelChannels(mask_image);
1974 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1977 /* clean up and set the write mask */
1978 mask_view=DestroyCacheView(mask_view);
1979 mask_image->matte=MagickTrue;
1980 (void) SetImageMask(image,mask_image,exception);
1981 mask_image=DestroyImage(mask_image);
1984 if (LocaleCompare("clip-path",option+1) == 0)
1986 (void) ClipImagePath(image,arg1,normal_op,exception);
1989 if (LocaleCompare("colorize",option+1) == 0)
1991 new_image=ColorizeImage(image,arg1,&draw_info->fill,exception);
1994 if (LocaleCompare("color-matrix",option+1) == 0)
1999 kernel=AcquireKernelInfo(arg1);
2000 if (kernel == (KernelInfo *) NULL)
2002 new_image=ColorMatrixImage(image,kernel,exception);
2003 kernel=DestroyKernelInfo(kernel);
2006 if (LocaleCompare("colors",option+1) == 0)
2008 /* Reduce the number of colors in the image.
2009 FUTURE: also provide 'plus version with image 'color counts'
2011 quantize_info->number_colors=StringToUnsignedLong(arg1);
2012 if (quantize_info->number_colors == 0)
2014 if ((image->storage_class == DirectClass) ||
2015 image->colors > quantize_info->number_colors)
2016 (void) QuantizeImage(quantize_info,image,exception);
2018 (void) CompressImageColormap(image,exception);
2021 if (LocaleCompare("colorspace",option+1) == 0)
2023 /* WARNING: this is both a image_info setting (already done)
2024 and a operator to change image colorspace.
2026 FUTURE: default colorspace should be sRGB!
2027 Unless some type of 'linear colorspace' mode is set.
2029 Note that +colorspace sets "undefined" or no effect on
2030 new images, but forces images already in memory back to RGB!
2031 That seems to be a little strange!
2033 (void) TransformImageColorspace(image,
2034 IfNormalOp ? image_info->colorspace : RGBColorspace,
2038 if (LocaleCompare("contrast",option+1) == 0)
2040 (void) ContrastImage(image,normal_op,exception);
2043 if (LocaleCompare("contrast-stretch",option+1) == 0)
2052 flags=ParseGeometry(arg1,&geometry_info);
2053 black_point=geometry_info.rho;
2054 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2056 if ((flags & PercentValue) != 0)
2058 black_point*=(double) image->columns*image->rows/100.0;
2059 white_point*=(double) image->columns*image->rows/100.0;
2061 white_point=(MagickRealType) image->columns*image->rows-
2063 (void) ContrastStretchImage(image,black_point,white_point,
2067 if (LocaleCompare("convolve",option+1) == 0)
2072 kernel_info=AcquireKernelInfo(arg1);
2073 if (kernel_info == (KernelInfo *) NULL)
2075 kernel_info->bias=image->bias;
2076 new_image=ConvolveImage(image,kernel_info,exception);
2077 kernel_info=DestroyKernelInfo(kernel_info);
2080 if (LocaleCompare("crop",option+1) == 0)
2082 /* WARNING: This can generate multiple images! */
2083 new_image=CropImageToTiles(image,arg1,exception);
2086 if (LocaleCompare("cycle",option+1) == 0)
2088 (void) CycleColormapImage(image,(ssize_t) StringToLong(arg1),
2096 if (LocaleCompare("decipher",option+1) == 0)
2101 passkey=FileToStringInfo(arg1,~0,exception);
2102 if (passkey != (StringInfo *) NULL)
2104 (void) PasskeyDecipherImage(image,passkey,exception);
2105 passkey=DestroyStringInfo(passkey);
2109 if (LocaleCompare("depth",option+1) == 0)
2111 /* The image_info->depth setting has already been set
2112 We just need to apply it to all images in current sequence
2114 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2115 That is it really is an operation, not a setting! Arrgghhh
2117 FUTURE: this should not be an operator!!!
2119 (void) SetImageDepth(image,image_info->depth,exception);
2122 if (LocaleCompare("deskew",option+1) == 0)
2128 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
2130 threshold=40.0*QuantumRange/100.0;
2131 new_image=DeskewImage(image,threshold,exception);
2134 if (LocaleCompare("despeckle",option+1) == 0)
2136 new_image=DespeckleImage(image,exception);
2139 if (LocaleCompare("distort",option+1) == 0)
2143 token[MaxTextExtent];
2160 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
2162 if (method == ResizeDistortion)
2166 /* Special Case - Argument is actually a resize geometry!
2167 ** Convert that to an appropriate distortion argument array.
2168 ** FUTURE: make a separate special resize operator
2170 (void) ParseRegionGeometry(image,arg2,&geometry,
2172 resize_args[0]=(double) geometry.width;
2173 resize_args[1]=(double) geometry.height;
2174 new_image=DistortImage(image,method,(size_t)2,
2175 resize_args,MagickTrue,exception);
2178 /* handle percent arguments */
2179 args=InterpretImageProperties(image_info,image,arg2,
2181 if (args == (char *) NULL)
2183 /* convert arguments into an array of doubles
2184 FUTURE: make this a separate function.
2185 Also make use of new 'sentinal' feature to avoid need for
2189 for (x=0; *p != '\0'; x++)
2191 GetMagickToken(p,&p,token);
2193 GetMagickToken(p,&p,token);
2195 number_arguments=(size_t) x;
2196 arguments=(double *) AcquireQuantumMemory(number_arguments,
2197 sizeof(*arguments));
2198 if (arguments == (double *) NULL)
2199 ThrowWandFatalException(ResourceLimitFatalError,
2200 "MemoryAllocationFailed",image->filename);
2201 (void) ResetMagickMemory(arguments,0,number_arguments*
2202 sizeof(*arguments));
2204 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2206 GetMagickToken(p,&p,token);
2208 GetMagickToken(p,&p,token);
2209 arguments[x]=StringToDouble(token,(char **) NULL);
2211 args=DestroyString(args);
2212 new_image=DistortImage(image,method,number_arguments,arguments,
2213 plus_alt_op,exception);
2214 arguments=(double *) RelinquishMagickMemory(arguments);
2217 if (LocaleCompare("draw",option+1) == 0)
2219 (void) CloneString(&draw_info->primitive,arg1);
2220 (void) DrawImage(image,draw_info,exception);
2221 (void) CloneString(&draw_info->primitive,(char *)NULL);
2228 if (LocaleCompare("edge",option+1) == 0)
2230 flags=ParseGeometry(arg1,&geometry_info);
2231 if ((flags & SigmaValue) == 0)
2232 geometry_info.sigma=1.0;
2233 new_image=EdgeImage(image,geometry_info.rho,
2234 geometry_info.sigma,exception);
2237 if (LocaleCompare("emboss",option+1) == 0)
2239 flags=ParseGeometry(arg1,&geometry_info);
2240 if ((flags & SigmaValue) == 0)
2241 geometry_info.sigma=1.0;
2242 new_image=EmbossImage(image,geometry_info.rho,
2243 geometry_info.sigma,exception);
2246 if (LocaleCompare("encipher",option+1) == 0)
2251 passkey=FileToStringInfo(arg1,~0,exception);
2252 if (passkey != (StringInfo *) NULL)
2254 (void) PasskeyEncipherImage(image,passkey,exception);
2255 passkey=DestroyStringInfo(passkey);
2259 if (LocaleCompare("enhance",option+1) == 0)
2261 new_image=EnhanceImage(image,exception);
2264 if (LocaleCompare("equalize",option+1) == 0)
2266 (void) EqualizeImage(image,exception);
2269 if (LocaleCompare("evaluate",option+1) == 0)
2274 MagickEvaluateOperator
2277 op=(MagickEvaluateOperator) ParseCommandOption(
2278 MagickEvaluateOptions,MagickFalse,arg1);
2279 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
2280 (void) EvaluateImage(image,op,constant,exception);
2283 if (LocaleCompare("extent",option+1) == 0)
2285 flags=ParseGravityGeometry(image,arg1,&geometry,exception);
2286 if (geometry.width == 0)
2287 geometry.width=image->columns;
2288 if (geometry.height == 0)
2289 geometry.height=image->rows;
2290 new_image=ExtentImage(image,&geometry,exception);
2297 if (LocaleCompare("features",option+1) == 0)
2299 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
2301 (void) DeleteImageArtifact(image,"identify:features");
2304 (void) SetImageArtifact(image,"identify:features","true");
2305 (void) SetImageArtifact(image,"verbose","true");
2308 if (LocaleCompare("flip",option+1) == 0)
2310 new_image=FlipImage(image,exception);
2313 if (LocaleCompare("flop",option+1) == 0)
2315 new_image=FlopImage(image,exception);
2318 if (LocaleCompare("floodfill",option+1) == 0)
2323 (void) ParsePageGeometry(image,arg1,&geometry,exception);
2324 (void) QueryColorCompliance(arg2,AllCompliance,&target,exception);
2325 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
2326 geometry.y,plus_alt_op,exception);
2329 if (LocaleCompare("frame",option+1) == 0)
2340 value=GetImageOption(image_info,"compose");
2341 if (value != (const char *) NULL)
2342 compose=(CompositeOperator) ParseCommandOption(
2343 MagickComposeOptions,MagickFalse,value);
2345 compose=OverCompositeOp; /* use Over not image->compose */
2347 flags=ParsePageGeometry(image,arg1,&geometry,exception);
2348 frame_info.width=geometry.width;
2349 frame_info.height=geometry.height;
2350 if ((flags & HeightValue) == 0)
2351 frame_info.height=geometry.width;
2352 frame_info.outer_bevel=geometry.x;
2353 frame_info.inner_bevel=geometry.y;
2354 frame_info.x=(ssize_t) frame_info.width;
2355 frame_info.y=(ssize_t) frame_info.height;
2356 frame_info.width=image->columns+2*frame_info.width;
2357 frame_info.height=image->rows+2*frame_info.height;
2358 new_image=FrameImage(image,&frame_info,compose,exception);
2361 if (LocaleCompare("function",option+1) == 0)
2365 token[MaxTextExtent];
2383 Function Modify Image Values
2384 FUTURE: code should be almost a duplicate of that is "distort"
2386 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
2388 arguments=InterpretImageProperties(image_info,image,arg2,
2390 if (arguments == (char *) NULL)
2392 p=(char *) arguments;
2393 for (x=0; *p != '\0'; x++)
2395 GetMagickToken(p,&p,token);
2397 GetMagickToken(p,&p,token);
2399 number_parameters=(size_t) x;
2400 parameters=(double *) AcquireQuantumMemory(number_parameters,
2401 sizeof(*parameters));
2402 if (parameters == (double *) NULL)
2403 ThrowWandFatalException(ResourceLimitFatalError,
2404 "MemoryAllocationFailed",image->filename);
2405 (void) ResetMagickMemory(parameters,0,number_parameters*
2406 sizeof(*parameters));
2407 p=(char *) arguments;
2408 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2410 GetMagickToken(p,&p,token);
2412 GetMagickToken(p,&p,token);
2413 parameters[x]=StringToDouble(token,(char **) NULL);
2415 arguments=DestroyString(arguments);
2416 (void) FunctionImage(image,function,number_parameters,parameters,
2418 parameters=(double *) RelinquishMagickMemory(parameters);
2425 if (LocaleCompare("gamma",option+1) == 0)
2428 (void) GammaImage(image,StringToDouble(arg1,(char **) NULL),
2431 image->gamma=StringToDouble(arg1,(char **) NULL);
2434 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2435 (LocaleCompare("gaussian",option+1) == 0))
2437 flags=ParseGeometry(arg1,&geometry_info);
2438 if ((flags & SigmaValue) == 0)
2439 geometry_info.sigma=1.0;
2440 new_image=GaussianBlurImage(image,geometry_info.rho,
2441 geometry_info.sigma,exception);
2444 if (LocaleCompare("geometry",option+1) == 0)
2447 Record Image offset for composition. (A Setting)
2448 Resize last image. (ListOperator)
2449 FUTURE: Why if no 'offset' does this resize ALL images?
2450 Also why is the setting recorded in the IMAGE non-sense!
2453 { /* remove the previous composition geometry offset! */
2454 if (image->geometry != (char *) NULL)
2455 image->geometry=DestroyString(image->geometry);
2458 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
2459 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2460 (void) CloneString(&image->geometry,arg1);
2462 new_image=ResizeImage(image,geometry.width,geometry.height,
2463 image->filter,image->blur,exception);
2470 if (LocaleCompare("highlight-color",option+1) == 0)
2472 (void) SetImageArtifact(image,option+1,arg1);
2479 if (LocaleCompare("identify",option+1) == 0)
2485 format=GetImageOption(image_info,"format");
2486 if (format == (char *) NULL)
2488 (void) IdentifyImage(image,stdout,image_info->verbose,
2492 text=InterpretImageProperties(image_info,image,format,exception);
2493 if (text == (char *) NULL)
2495 (void) fputs(text,stdout);
2496 (void) fputc('\n',stdout);
2497 text=DestroyString((char *)text);
2500 if (LocaleCompare("implode",option+1) == 0)
2502 (void) ParseGeometry(arg1,&geometry_info);
2503 new_image=ImplodeImage(image,geometry_info.rho,
2504 image->interpolate,exception);
2507 if (LocaleCompare("interpolative-resize",option+1) == 0)
2509 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2510 new_image=InterpolativeResizeImage(image,geometry.width,
2511 geometry.height,image->interpolate,exception);
2518 if (LocaleCompare("lat",option+1) == 0)
2520 flags=ParseGeometry(arg1,&geometry_info);
2521 if ((flags & PercentValue) != 0)
2522 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2523 new_image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
2524 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2528 if (LocaleCompare("level",option+1) == 0)
2538 flags=ParseGeometry(arg1,&geometry_info);
2539 black_point=geometry_info.rho;
2540 white_point=(MagickRealType) QuantumRange;
2541 if ((flags & SigmaValue) != 0)
2542 white_point=geometry_info.sigma;
2544 if ((flags & XiValue) != 0)
2545 gamma=geometry_info.xi;
2546 if ((flags & PercentValue) != 0)
2548 black_point*=(MagickRealType) (QuantumRange/100.0);
2549 white_point*=(MagickRealType) (QuantumRange/100.0);
2551 if ((flags & SigmaValue) == 0)
2552 white_point=(MagickRealType) QuantumRange-black_point;
2553 if (IfPlusOp || ((flags & AspectValue) != 0))
2554 (void) LevelizeImage(image,black_point,white_point,gamma,exception);
2556 (void) LevelImage(image,black_point,white_point,gamma,exception);
2559 if (LocaleCompare("level-colors",option+1) == 0)
2562 token[MaxTextExtent];
2571 p=(const char *) arg1;
2572 GetMagickToken(p,&p,token); /* get black point color */
2573 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2574 (void) QueryColorCompliance(token,AllCompliance,
2575 &black_point,exception);
2577 (void) QueryColorCompliance("#000000",AllCompliance,
2578 &black_point,exception);
2579 if (isalpha((int) token[0]) || (token[0] == '#'))
2580 GetMagickToken(p,&p,token);
2582 white_point=black_point; /* set everything to that color */
2585 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2586 GetMagickToken(p,&p,token); /* Get white point color. */
2587 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2588 (void) QueryColorCompliance(token,AllCompliance,
2589 &white_point,exception);
2591 (void) QueryColorCompliance("#ffffff",AllCompliance,
2592 &white_point,exception);
2594 (void) LevelImageColors(image,&black_point,&white_point,
2595 plus_alt_op,exception);
2598 if (LocaleCompare("linear-stretch",option+1) == 0)
2607 flags=ParseGeometry(arg1,&geometry_info);
2608 black_point=geometry_info.rho;
2609 white_point=(MagickRealType) image->columns*image->rows;
2610 if ((flags & SigmaValue) != 0)
2611 white_point=geometry_info.sigma;
2612 if ((flags & PercentValue) != 0)
2614 black_point*=(double) image->columns*image->rows/100.0;
2615 white_point*=(double) image->columns*image->rows/100.0;
2617 if ((flags & SigmaValue) == 0)
2618 white_point=(MagickRealType) image->columns*image->rows-
2620 (void) LinearStretchImage(image,black_point,white_point,exception);
2623 if (LocaleCompare("liquid-rescale",option+1) == 0)
2625 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
2626 if ((flags & XValue) == 0)
2628 if ((flags & YValue) == 0)
2630 new_image=LiquidRescaleImage(image,geometry.width,
2631 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2634 if (LocaleCompare("lowlight-color",option+1) == 0)
2636 (void) SetImageArtifact(image,option+1,arg1);
2643 if (LocaleCompare("map",option+1) == 0)
2648 /* DEPRECIATED use -remap */
2649 remap_image=GetImageCache(image_info,arg1,exception);
2650 if (remap_image == (Image *) NULL)
2652 (void) RemapImage(quantize_info,image,remap_image,exception);
2653 remap_image=DestroyImage(remap_image);
2656 if (LocaleCompare("mask",option+1) == 0)
2662 { /* Remove a mask. */
2663 (void) SetImageMask(image,(Image *) NULL,exception);
2666 /* Set the image mask. */
2667 mask=GetImageCache(image_info,arg1,exception);
2668 if (mask == (Image *) NULL)
2670 (void) SetImageMask(image,mask,exception);
2671 mask=DestroyImage(mask);
2674 if (LocaleCompare("matte",option+1) == 0)
2677 (void) SetImageAlphaChannel(image,IfNormalOp ? SetAlphaChannel :
2678 DeactivateAlphaChannel, exception);
2681 if (LocaleCompare("mode",option+1) == 0)
2683 flags=ParseGeometry(arg1,&geometry_info);
2684 if ((flags & SigmaValue) == 0)
2685 geometry_info.sigma=geometry_info.rho;
2686 new_image=StatisticImage(image,ModeStatistic,(size_t)
2687 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2690 if (LocaleCompare("modulate",option+1) == 0)
2692 (void) ModulateImage(image,arg1,exception);
2695 if (LocaleCompare("monitor",option+1) == 0)
2697 (void) SetImageProgressMonitor(image, IfNormalOp ? MonitorProgress :
2698 (MagickProgressMonitor) NULL,(void *) NULL);
2701 if (LocaleCompare("monochrome",option+1) == 0)
2703 (void) SetImageType(image,BilevelType,exception);
2706 if (LocaleCompare("morphology",option+1) == 0)
2709 token[MaxTextExtent];
2724 GetMagickToken(p,&p,token);
2725 method=(MorphologyMethod) ParseCommandOption(
2726 MagickMorphologyOptions,MagickFalse,token);
2728 GetMagickToken(p,&p,token);
2729 if ((*p == ':') || (*p == ','))
2730 GetMagickToken(p,&p,token);
2732 iterations=(ssize_t) StringToLong(p);
2733 kernel=AcquireKernelInfo(arg2);
2734 if (kernel == (KernelInfo *) NULL)
2736 (void) ThrowMagickException(exception,GetMagickModule(),
2737 OptionError,"UnabletoParseKernel","morphology");
2740 new_image=MorphologyImage(image,method,iterations,kernel,exception);
2741 kernel=DestroyKernelInfo(kernel);
2744 if (LocaleCompare("motion-blur",option+1) == 0)
2746 flags=ParseGeometry(arg1,&geometry_info);
2747 if ((flags & SigmaValue) == 0)
2748 geometry_info.sigma=1.0;
2749 new_image=MotionBlurImage(image,geometry_info.rho,
2750 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2758 if (LocaleCompare("negate",option+1) == 0)
2760 (void) NegateImage(image, plus_alt_op, exception);
2763 if (LocaleCompare("noise",option+1) == 0)
2767 flags=ParseGeometry(arg1,&geometry_info);
2768 if ((flags & SigmaValue) == 0)
2769 geometry_info.sigma=geometry_info.rho;
2770 new_image=StatisticImage(image,NonpeakStatistic,(size_t)
2771 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2784 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
2787 value=GetImageOption(image_info,"attenuate");
2788 if (value != (const char *) NULL)
2789 attenuate=StringToDouble(value,(char **) NULL);
2793 new_image=AddNoiseImage(image,noise,attenuate,exception);
2797 if (LocaleCompare("normalize",option+1) == 0)
2799 (void) NormalizeImage(image,exception);
2806 if (LocaleCompare("opaque",option+1) == 0)
2811 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
2812 (void) OpaquePaintImage(image,&target,&draw_info->fill,plus_alt_op,
2816 if (LocaleCompare("ordered-dither",option+1) == 0)
2818 (void) OrderedPosterizeImage(image,arg1,exception);
2825 if (LocaleCompare("paint",option+1) == 0)
2827 (void) ParseGeometry(arg1,&geometry_info);
2828 new_image=OilPaintImage(image,geometry_info.rho,geometry_info.sigma,
2832 if (LocaleCompare("polaroid",option+1) == 0)
2845 random_info=AcquireRandomInfo();
2846 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2847 random_info=DestroyRandomInfo(random_info);
2851 SetGeometryInfo(&geometry_info);
2852 flags=ParseGeometry(arg1,&geometry_info);
2853 angle=geometry_info.rho;
2855 caption=GetImageProperty(image,"caption",exception);
2856 new_image=PolaroidImage(image,draw_info,caption,angle,
2857 image->interpolate,exception);
2860 if (LocaleCompare("posterize",option+1) == 0)
2862 (void) ParseGeometry(arg1,&geometry_info);
2863 (void) PosterizeImage(image,(size_t) geometry_info.rho,
2864 quantize_info->dither,exception);
2867 if (LocaleCompare("preview",option+1) == 0)
2872 /* FUTURE: should be a 'Genesis' option?
2873 Option however is also in WandSettingOptionInfo()
2875 preview_type=UndefinedPreview;
2877 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2879 new_image=PreviewImage(image,preview_type,exception);
2882 if (LocaleCompare("profile",option+1) == 0)
2897 { /* Remove a profile from the image. */
2898 (void) ProfileImage(image,arg1,(const unsigned char *)
2902 /* Associate a profile with the image. */
2903 profile_info=CloneImageInfo(image_info);
2904 profile=GetImageProfile(image,"iptc");
2905 if (profile != (StringInfo *) NULL)
2906 profile_info->profile=(void *) CloneStringInfo(profile);
2907 profile_image=GetImageCache(profile_info,arg1,exception);
2908 profile_info=DestroyImageInfo(profile_info);
2909 if (profile_image == (Image *) NULL)
2914 profile_info=CloneImageInfo(image_info);
2915 (void) CopyMagickString(profile_info->filename,arg1,
2917 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
2918 if (profile != (StringInfo *) NULL)
2920 (void) ProfileImage(image,profile_info->magick,
2921 GetStringInfoDatum(profile),(size_t)
2922 GetStringInfoLength(profile),exception);
2923 profile=DestroyStringInfo(profile);
2925 profile_info=DestroyImageInfo(profile_info);
2928 ResetImageProfileIterator(profile_image);
2929 name=GetNextImageProfile(profile_image);
2930 while (name != (const char *) NULL)
2932 profile=GetImageProfile(profile_image,name);
2933 if (profile != (StringInfo *) NULL)
2934 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
2935 (size_t) GetStringInfoLength(profile),exception);
2936 name=GetNextImageProfile(profile_image);
2938 profile_image=DestroyImage(profile_image);
2945 if (LocaleCompare("radial-blur",option+1) == 0)
2947 flags=ParseGeometry(arg1,&geometry_info);
2948 new_image=RadialBlurImage(image,geometry_info.rho,
2949 geometry_info.sigma,exception);
2952 if (LocaleCompare("raise",option+1) == 0)
2954 flags=ParsePageGeometry(image,arg1,&geometry,exception);
2955 if ((flags & SigmaValue) == 0)
2956 geometry.height=geometry.width;
2957 (void) RaiseImage(image,&geometry,normal_op,exception);
2960 if (LocaleCompare("random-threshold",option+1) == 0)
2962 (void) RandomThresholdImage(image,arg1,exception);
2965 if (LocaleCompare("remap",option+1) == 0)
2970 remap_image=GetImageCache(image_info,arg1,exception);
2971 if (remap_image == (Image *) NULL)
2973 (void) RemapImage(quantize_info,image,remap_image,exception);
2974 remap_image=DestroyImage(remap_image);
2977 if (LocaleCompare("repage",option+1) == 0)
2980 (void) ResetImagePage(image,arg1);
2982 (void) ParseAbsoluteGeometry("0x0+0+0",&image->page);
2985 if (LocaleCompare("resample",option+1) == 0)
2987 /* FUTURE: remove blur arguemnt - no longer used */
2988 flags=ParseGeometry(arg1,&geometry_info);
2989 if ((flags & SigmaValue) == 0)
2990 geometry_info.sigma=geometry_info.rho;
2991 new_image=ResampleImage(image,geometry_info.rho,
2992 geometry_info.sigma,image->filter,image->blur,exception);
2995 if (LocaleCompare("resize",option+1) == 0)
2997 /* FUTURE: remove blur argument - no longer used */
2998 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2999 new_image=ResizeImage(image,geometry.width,geometry.height,
3000 image->filter,image->blur,exception);
3003 if (LocaleCompare("roll",option+1) == 0)
3005 (void) ParsePageGeometry(image,arg1,&geometry,exception);
3006 new_image=RollImage(image,geometry.x,geometry.y,exception);
3009 if (LocaleCompare("rotate",option+1) == 0)
3011 if (strchr(arg1,'>') != (char *) NULL)
3012 if (image->columns <= image->rows)
3014 if (strchr(arg1,'<') != (char *) NULL)
3015 if (image->columns >= image->rows)
3018 (void) ParseGeometry(arg1,&geometry_info);
3019 new_image=RotateImage(image,geometry_info.rho,exception);
3026 if (LocaleCompare("sample",option+1) == 0)
3028 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3029 new_image=SampleImage(image,geometry.width,geometry.height,
3033 if (LocaleCompare("scale",option+1) == 0)
3035 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3036 new_image=ScaleImage(image,geometry.width,geometry.height,
3040 if (LocaleCompare("selective-blur",option+1) == 0)
3042 flags=ParseGeometry(arg1,&geometry_info);
3043 if ((flags & PercentValue) != 0)
3044 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3045 new_image=SelectiveBlurImage(image,geometry_info.rho,
3046 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3049 if (LocaleCompare("separate",option+1) == 0)
3051 /* WARNING: This can generate multiple images! */
3052 /* FUTURE - this may be replaced by a "-channel" method */
3053 new_image=SeparateImages(image,exception);
3056 if (LocaleCompare("sepia-tone",option+1) == 0)
3061 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
3062 new_image=SepiaToneImage(image,threshold,exception);
3065 if (LocaleCompare("segment",option+1) == 0)
3067 flags=ParseGeometry(arg1,&geometry_info);
3068 if ((flags & SigmaValue) == 0)
3069 geometry_info.sigma=1.0;
3070 (void) SegmentImage(image,image->colorspace,
3071 image_info->verbose,geometry_info.rho,geometry_info.sigma,
3075 if (LocaleCompare("set",option+1) == 0)
3082 if (LocaleNCompare(arg1,"registry:",9) == 0)
3083 (void) DeleteImageRegistry(arg1+9);
3085 if (LocaleNCompare(arg1,"option:",7) == 0)
3087 (void) DeleteImageOption(image_info,arg1+7);
3088 (void) DeleteImageArtifact(image,arg1+7);
3091 (void) DeleteImageProperty(image,arg1);
3094 value=InterpretImageProperties(image_info,image,arg2,
3096 if (value == (char *) NULL)
3098 if (LocaleNCompare(arg1,"registry:",9) == 0)
3099 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
3102 if (LocaleNCompare(arg1,"option:",7) == 0)
3104 (void) SetImageOption(image_info,arg1+7,value);
3105 (void) SetImageArtifact(image,arg1+7,value);
3108 (void) SetImageProperty(image,arg1,value,exception);
3109 value=DestroyString(value);
3112 if (LocaleCompare("shade",option+1) == 0)
3114 flags=ParseGeometry(arg1,&geometry_info);
3115 if ((flags & SigmaValue) == 0)
3116 geometry_info.sigma=1.0;
3117 new_image=ShadeImage(image,normal_op,geometry_info.rho,
3118 geometry_info.sigma,exception);
3121 if (LocaleCompare("shadow",option+1) == 0)
3123 flags=ParseGeometry(arg1,&geometry_info);
3124 if ((flags & SigmaValue) == 0)
3125 geometry_info.sigma=1.0;
3126 if ((flags & XiValue) == 0)
3127 geometry_info.xi=4.0;
3128 if ((flags & PsiValue) == 0)
3129 geometry_info.psi=4.0;
3130 new_image=ShadowImage(image,geometry_info.rho,
3131 geometry_info.sigma,image->bias,(ssize_t)
3132 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
3136 if (LocaleCompare("sharpen",option+1) == 0)
3138 flags=ParseGeometry(arg1,&geometry_info);
3139 if ((flags & SigmaValue) == 0)
3140 geometry_info.sigma=1.0;
3141 if ((flags & XiValue) == 0)
3142 geometry_info.xi=0.0;
3143 new_image=SharpenImage(image,geometry_info.rho,
3144 geometry_info.sigma,geometry_info.xi,exception);
3147 if (LocaleCompare("shave",option+1) == 0)
3149 flags=ParsePageGeometry(image,arg1,&geometry,exception);
3150 new_image=ShaveImage(image,&geometry,exception);
3153 if (LocaleCompare("shear",option+1) == 0)
3155 flags=ParseGeometry(arg1,&geometry_info);
3156 if ((flags & SigmaValue) == 0)
3157 geometry_info.sigma=geometry_info.rho;
3158 new_image=ShearImage(image,geometry_info.rho,
3159 geometry_info.sigma,exception);
3162 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
3164 flags=ParseGeometry(arg1,&geometry_info);
3165 if ((flags & SigmaValue) == 0)
3166 geometry_info.sigma=(double) QuantumRange/2.0;
3167 if ((flags & PercentValue) != 0)
3168 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3170 (void) SigmoidalContrastImage(image,normal_op,geometry_info.rho,
3171 geometry_info.sigma,
3175 if (LocaleCompare("sketch",option+1) == 0)
3177 flags=ParseGeometry(arg1,&geometry_info);
3178 if ((flags & SigmaValue) == 0)
3179 geometry_info.sigma=1.0;
3180 new_image=SketchImage(image,geometry_info.rho,
3181 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3184 if (LocaleCompare("solarize",option+1) == 0)
3186 (void) SolarizeImage(image,StringToDoubleInterval(arg1,(double)
3187 QuantumRange+1.0),exception);
3190 if (LocaleCompare("sparse-color",option+1) == 0)
3198 method=(SparseColorMethod) ParseCommandOption(
3199 MagickSparseColorOptions,MagickFalse,arg1);
3200 arguments=InterpretImageProperties(image_info,image,arg2,exception);
3201 if (arguments == (char *) NULL)
3203 new_image=SparseColorOption(image,method,arguments,exception);
3204 arguments=DestroyString(arguments);
3207 if (LocaleCompare("splice",option+1) == 0)
3209 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
3210 new_image=SpliceImage(image,&geometry,exception);
3213 if (LocaleCompare("spread",option+1) == 0)
3215 (void) ParseGeometry(arg1,&geometry_info);
3216 new_image=SpreadImage(image,geometry_info.rho,image->interpolate,
3220 if (LocaleCompare("statistic",option+1) == 0)
3225 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
3227 (void) ParseGeometry(arg2,&geometry_info);
3228 new_image=StatisticImage(image,type,(size_t) geometry_info.rho,
3229 (size_t) geometry_info.sigma,exception);
3232 if (LocaleCompare("strip",option+1) == 0)
3234 (void) StripImage(image,exception);
3237 if (LocaleCompare("swirl",option+1) == 0)
3239 (void) ParseGeometry(arg1,&geometry_info);
3240 new_image=SwirlImage(image,geometry_info.rho,
3241 image->interpolate,exception);
3248 if (LocaleCompare("threshold",option+1) == 0)
3254 threshold=(double) QuantumRange/2;
3256 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
3257 (void) BilevelImage(image,threshold,exception);
3260 if (LocaleCompare("thumbnail",option+1) == 0)
3262 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3263 new_image=ThumbnailImage(image,geometry.width,geometry.height,
3267 if (LocaleCompare("tint",option+1) == 0)
3269 new_image=TintImage(image,arg1,&draw_info->fill,exception);
3272 if (LocaleCompare("transform",option+1) == 0)
3275 new_image=AffineTransformImage(image,&draw_info->affine,
3279 if (LocaleCompare("transparent",option+1) == 0)
3284 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
3285 (void) TransparentPaintImage(image,&target,(Quantum)
3286 TransparentAlpha,plus_alt_op,exception);
3289 if (LocaleCompare("transpose",option+1) == 0)
3291 new_image=TransposeImage(image,exception);
3294 if (LocaleCompare("transverse",option+1) == 0)
3296 new_image=TransverseImage(image,exception);
3299 if (LocaleCompare("trim",option+1) == 0)
3301 new_image=TrimImage(image,exception);
3304 if (LocaleCompare("type",option+1) == 0)
3306 /* Note that "type" setting should have already been defined */
3307 (void) SetImageType(image,image_info->type,exception);
3314 if (LocaleCompare("unique",option+1) == 0)
3316 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
3319 (void) DeleteImageArtifact(image,"identify:unique-colors");
3322 (void) SetImageArtifact(image,"identify:unique-colors","true");
3323 (void) SetImageArtifact(image,"verbose","true");
3326 if (LocaleCompare("unique-colors",option+1) == 0)
3328 new_image=UniqueImageColors(image,exception);
3331 if (LocaleCompare("unsharp",option+1) == 0)
3333 flags=ParseGeometry(arg1,&geometry_info);
3334 if ((flags & SigmaValue) == 0)
3335 geometry_info.sigma=1.0;
3336 if ((flags & XiValue) == 0)
3337 geometry_info.xi=1.0;
3338 if ((flags & PsiValue) == 0)
3339 geometry_info.psi=0.05;
3340 new_image=UnsharpMaskImage(image,geometry_info.rho,
3341 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3348 if (LocaleCompare("verbose",option+1) == 0)
3350 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
3351 three places! ImageArtifact ImageOption image_info->verbose
3352 Some how new images also get this artifact presumably here
3354 (void) SetImageArtifact(image,option+1,
3355 IfNormalOp ? "true" : "false" );
3358 if (LocaleCompare("vignette",option+1) == 0)
3360 flags=ParseGeometry(arg1,&geometry_info);
3361 if ((flags & SigmaValue) == 0)
3362 geometry_info.sigma=1.0;
3363 if ((flags & XiValue) == 0)
3364 geometry_info.xi=0.1*image->columns;
3365 if ((flags & PsiValue) == 0)
3366 geometry_info.psi=0.1*image->rows;
3367 new_image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
3368 image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3369 (ssize_t) ceil(geometry_info.psi-0.5),exception);
3376 if (LocaleCompare("wave",option+1) == 0)
3378 flags=ParseGeometry(arg1,&geometry_info);
3379 if ((flags & SigmaValue) == 0)
3380 geometry_info.sigma=1.0;
3381 new_image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
3382 image->interpolate,exception);
3385 if (LocaleCompare("white-threshold",option+1) == 0)
3387 (void) WhiteThresholdImage(image,arg1,exception);
3396 Replace current image with any image that was generated
3397 and set image point to last image (so image->next is correct)
3399 if (new_image != (Image *) NULL)
3400 ReplaceImageInListReturnLast(&image,new_image);
3405 #undef quantize_info
3414 WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
3415 const char *option, const char *arg1, const char *arg2)
3421 assert(cli_wand != (MagickCLI *) NULL);
3422 assert(cli_wand->signature == WandSignature);
3423 assert(cli_wand->wand.signature == WandSignature);
3424 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3425 if (cli_wand->wand.debug != MagickFalse)
3426 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
3428 #if !USE_WAND_METHODS
3429 /* FUTURE add appropriate tracing */
3431 n=GetImageListLength(cli_wand->wand.images);
3432 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3435 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3436 if ( cli_wand->wand.images->next == (Image *) NULL )
3438 cli_wand->wand.images=cli_wand->wand.images->next;
3441 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3443 MagickResetIterator(&cli_wand->wand);
3444 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3445 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3446 MagickResetIterator(&cli_wand->wand);
3452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3456 + C L I L i s t O p e r a t o r I m a g e s %
3460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3462 % CLIListOperatorImages() applies a single operation that is apply to the
3463 % entire image list as a whole. The result is often a complete replacment
3464 % of the image list with a completely new list, or just a single image.
3466 % The format of the MogrifyImage method is:
3468 % void CLIListOperatorImages(MagickCLI *cli_wand,
3469 % const char *option, const char *arg1, const char *arg2)
3471 % A description of each parameter follows:
3473 % o cli_wand: structure holding settings to be applied
3475 % o option: The option string for the operation
3477 % o arg1, arg2: optional argument strings to the operation
3479 % NOTE: only "limit" currently uses two arguments.
3483 % CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3484 % CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
3486 % Or for handling command line arguments EG: +/-option ["arg"]
3492 % option_info = GetCommandOptionInfo(argv[i]);
3493 % count=option_info->type;
3494 % option_type=option_info->flags;
3496 % if ( (option_type & ListOperatorOptionFlag) != 0 )
3497 % CLIListOperatorImages(cli_wand,argv[i],
3498 % count>=1 ? argv[i+1] : (char *)NULL,
3499 % count>=2 ? argv[i+2] : (char *)NULL );
3503 WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
3504 const char *option,const char *arg1, const char *arg2)
3509 #define image_info (cli_wand->wand.image_info)
3510 #define images (cli_wand->wand.images)
3511 #define exception (cli_wand->wand.exception)
3512 #define draw_info (cli_wand->draw_info)
3513 #define quantize_info (cli_wand->quantize_info)
3514 #define IfNormalOp (*option=='-')
3515 #define IfPlusOp (*option!='-')
3516 #define normal_op (IfNormalOp?MagickTrue:MagickFalse)
3518 assert(cli_wand != (MagickCLI *) NULL);
3519 assert(cli_wand->signature == WandSignature);
3520 assert(cli_wand->wand.signature == WandSignature);
3521 assert(images != (Image *) NULL); /* images must be present */
3522 if (cli_wand->wand.debug != MagickFalse)
3523 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
3525 (void) SyncImagesSettings(image_info,images,exception);
3527 new_images=NewImageList();
3529 switch (*(option+1))
3533 if (LocaleCompare("append",option+1) == 0)
3535 new_images=AppendImages(images,normal_op,exception);
3538 if (LocaleCompare("average",option+1) == 0)
3540 /* DEPRECIATED - use -evaluate-sequence Mean */
3541 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
3548 if (LocaleCompare("channel-inject",option+1) == 0)
3550 puts("stand by...");
3553 if (LocaleCompare("clut",option+1) == 0)
3558 /* FUTURE - make this a compose option, and thus can be used
3559 with layers compose or even compose last image over all other
3562 new_images=RemoveFirstImageFromList(&images);
3563 clut_image=RemoveLastImageFromList(&images);
3564 /* FUTURE - produce Exception, rather than silent fail */
3565 if (clut_image == (Image *) NULL)
3567 (void) ClutImage(new_images,clut_image,images->interpolate,exception);
3568 clut_image=DestroyImage(clut_image);
3571 if (LocaleCompare("coalesce",option+1) == 0)
3573 new_images=CoalesceImages(images,exception);
3576 if (LocaleCompare("combine",option+1) == 0)
3578 /* FUTURE - this may be replaced by a 'channel' method */
3579 new_images=CombineImages(images,exception);
3582 if (LocaleCompare("composite",option+1) == 0)
3597 value=GetImageOption(image_info,"compose");
3598 if (value != (const char *) NULL)
3599 compose=(CompositeOperator) ParseCommandOption(
3600 MagickComposeOptions,MagickFalse,value);
3602 compose=OverCompositeOp; /* use Over not source_image->compose */
3604 new_images=RemoveFirstImageFromList(&images);
3605 source_image=RemoveFirstImageFromList(&images);
3606 /* FUTURE - produce Exception, rather than silent fail */
3607 if (source_image == (Image *) NULL)
3610 /* FUTURE - this should not be here! - should be part of -geometry */
3611 (void) TransformImage(&source_image,(char *) NULL,
3612 source_image->geometry,exception);
3614 SetGeometry(source_image,&geometry);
3615 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3616 GravityAdjustGeometry(new_images->columns,new_images->rows,
3617 new_images->gravity, &geometry);
3619 mask_image=RemoveFirstImageFromList(&images);
3620 if (mask_image != (Image *) NULL)
3621 { /* handle a third write mask image */
3622 if ((compose == DisplaceCompositeOp) ||
3623 (compose == DistortCompositeOp))
3624 { /* Merge Y displacement into X displace/distort map. */
3625 (void) CompositeImage(source_image,CopyGreenCompositeOp,
3626 mask_image,0,0,exception);
3627 mask_image=DestroyImage(mask_image);
3632 Set a blending mask for the composition.
3634 (void) NegateImage(mask_image,MagickFalse,exception);
3635 (void) SetImageMask(new_images,mask_image,exception);
3636 mask_image=DestroyImage(mask_image);
3639 (void) CompositeImage(new_images,compose,source_image,geometry.x,
3640 geometry.y,exception);
3641 (void) SetImageMask(new_images,(Image *) NULL,exception);
3642 source_image=DestroyImage(source_image);
3649 if (LocaleCompare("deconstruct",option+1) == 0)
3651 /* DEPRECIATED - use -layers CompareAny */
3652 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
3655 if (LocaleCompare("delete",option+1) == 0)
3658 DeleteImages(&images,arg1,exception);
3660 DeleteImages(&images,"-1",exception);
3663 if (LocaleCompare("duplicate",option+1) == 0)
3673 number_duplicates=(size_t) StringToLong(arg1);
3675 if (p == (const char *) NULL)
3676 new_images=DuplicateImages(images,number_duplicates,
3679 new_images=DuplicateImages(images,number_duplicates,p,
3683 new_images=DuplicateImages(images,1,"-1",exception);
3684 AppendImageToList(&images, new_images);
3685 new_images=(Image *)NULL;
3692 if (LocaleCompare("evaluate-sequence",option+1) == 0)
3694 MagickEvaluateOperator
3697 method=(MagickEvaluateOperator) ParseCommandOption(
3698 MagickEvaluateOptions,MagickFalse,arg1);
3699 new_images=EvaluateImages(images,method,exception);
3706 if (LocaleCompare("fft",option+1) == 0)
3708 new_images=ForwardFourierTransformImage(images,normal_op,exception);
3711 if (LocaleCompare("flatten",option+1) == 0)
3713 /* DEPRECIATED use -layers mosaic instead */
3714 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
3717 if (LocaleCompare("fx",option+1) == 0)
3719 new_images=FxImage(images,arg1,exception);
3726 if (LocaleCompare("hald-clut",option+1) == 0)
3728 /* FUTURE - make this a compose option (and thus layers compose )
3729 or perhaps compose last image over all other images.
3734 new_images=RemoveFirstImageFromList(&images);
3735 hald_image=RemoveLastImageFromList(&images);
3736 if (hald_image == (Image *) NULL)
3738 (void) HaldClutImage(new_images,hald_image,exception);
3739 hald_image=DestroyImage(hald_image);
3746 if (LocaleCompare("ift",option+1) == 0)
3752 magnitude_image=RemoveFirstImageFromList(&images);
3753 phase_image=RemoveFirstImageFromList(&images);
3754 /* FUTURE - produce Exception, rather than silent fail */
3755 if (phase_image == (Image *) NULL)
3757 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
3758 normal_op,exception);
3759 magnitude_image=DestroyImage(magnitude_image);
3760 phase_image=DestroyImage(phase_image);
3763 if (LocaleCompare("insert",option+1) == 0)
3773 insert_image=RemoveLastImageFromList(&images);
3775 index=(ssize_t) StringToLong(arg1);
3776 index_image=insert_image;
3778 PrependImageToList(&images,insert_image);
3779 else if (index == (ssize_t) GetImageListLength(images))
3780 AppendImageToList(&images,insert_image);
3783 index_image=GetImageFromList(images,index-1);
3784 if (index_image == (Image *) NULL)
3786 (void) ThrowMagickException(exception,GetMagickModule(),
3787 OptionError,"NoSuchImage","'%s'",arg1);
3790 InsertImageInList(&index_image,insert_image);
3792 images=GetFirstImageInList(index_image);
3799 if (LocaleCompare("layers",option+1) == 0)
3804 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
3810 new_images=CoalesceImages(images,exception);
3813 case CompareAnyLayer:
3814 case CompareClearLayer:
3815 case CompareOverlayLayer:
3818 new_images=CompareImagesLayers(images,method,exception);
3824 case TrimBoundsLayer:
3826 new_images=MergeImageLayers(images,method,exception);
3831 new_images=DisposeImages(images,exception);
3834 case OptimizeImageLayer:
3836 new_images=OptimizeImageLayers(images,exception);
3839 case OptimizePlusLayer:
3841 new_images=OptimizePlusImageLayers(images,exception);
3844 case OptimizeTransLayer:
3846 OptimizeImageTransparency(images,exception);
3849 case RemoveDupsLayer:
3851 RemoveDuplicateLayers(&images,exception);
3854 case RemoveZeroLayer:
3856 RemoveZeroDelayLayers(&images,exception);
3860 { /* General Purpose, GIF Animation Optimizer. */
3861 new_images=CoalesceImages(images,exception);
3862 if (new_images == (Image *) NULL)
3864 images=DestroyImageList(images);
3865 images=OptimizeImageLayers(new_images,exception);
3866 if (images == (Image *) NULL)
3868 new_images=DestroyImageList(new_images);
3869 OptimizeImageTransparency(images,exception);
3870 (void) RemapImages(quantize_info,images,(Image *) NULL,
3874 case CompositeLayer:
3888 value=GetImageOption(image_info,"compose");
3889 compose=OverCompositeOp; /* Default to Over */
3890 if (value != (const char *) NULL)
3891 compose=(CompositeOperator) ParseCommandOption(
3892 MagickComposeOptions,MagickFalse,value);
3894 /* Split image sequence at the first 'NULL:' image. */
3896 while (source != (Image *) NULL)
3898 source=GetNextImageInList(source);
3899 if ((source != (Image *) NULL) &&
3900 (LocaleCompare(source->magick,"NULL") == 0))
3903 if (source != (Image *) NULL)
3905 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3906 (GetNextImageInList(source) == (Image *) NULL))
3907 source=(Image *) NULL;
3909 { /* Separate the two lists, junk the null: image. */
3910 source=SplitImageList(source->previous);
3911 DeleteImageFromList(&source);
3914 if (source == (Image *) NULL)
3916 (void) ThrowMagickException(exception,GetMagickModule(),
3917 OptionError,"MissingNullSeparator","layers Composite");
3920 /* Adjust offset with gravity and virtual canvas. */
3921 SetGeometry(images,&geometry);
3922 (void) ParseAbsoluteGeometry(images->geometry,&geometry);
3923 geometry.width=source->page.width != 0 ?
3924 source->page.width : source->columns;
3925 geometry.height=source->page.height != 0 ?
3926 source->page.height : source->rows;
3927 GravityAdjustGeometry(images->page.width != 0 ?
3928 images->page.width : images->columns,
3929 images->page.height != 0 ? images->page.height :
3930 images->rows,images->gravity,&geometry);
3932 /* Compose the two image sequences together */
3933 CompositeLayers(images,compose,source,geometry.x,geometry.y,
3935 source=DestroyImageList(source);
3941 if (LocaleCompare("limit",option+1) == 0)
3949 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
3951 limit=MagickResourceInfinity;
3952 if (LocaleCompare("unlimited",arg2) != 0)
3953 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
3954 (void) SetMagickResourceLimit(type,limit);
3961 if (LocaleCompare("map",option+1) == 0)
3963 /* DEPRECIATED use +remap */
3964 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
3967 if (LocaleCompare("morph",option+1) == 0)
3972 morph_image=MorphImages(images,StringToUnsignedLong(arg1),
3974 if (morph_image == (Image *) NULL)
3976 images=DestroyImageList(images);
3980 if (LocaleCompare("mosaic",option+1) == 0)
3982 /* DEPRECIATED use -layers mosaic instead */
3983 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
3990 if (LocaleCompare("print",option+1) == 0)
3995 string=InterpretImageProperties(image_info,images,arg1,
3997 if (string == (char *) NULL)
3999 (void) FormatLocaleFile(stdout,"%s",string);
4000 string=DestroyString(string);
4002 if (LocaleCompare("process",option+1) == 0)
4011 arguments=StringToArgv(arg1,&number_arguments);
4012 if (arguments == (char **) NULL)
4014 if (strchr(arguments[1],'=') != (char *) NULL)
4035 Support old style syntax, filter="-option arg".
4037 length=strlen(arg1);
4038 token=(char *) NULL;
4039 if (~length >= (MaxTextExtent-1))
4040 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4042 if (token == (char *) NULL)
4046 token_info=AcquireTokenInfo();
4047 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4048 "\"",'\0',&breaker,&next,"e);
4049 token_info=DestroyTokenInfo(token_info);
4055 argv=(&(arguments[next]));
4056 (void) InvokeDynamicImageFilter(token,&images,1,&argv,
4059 token=DestroyString(token);
4062 (void) SubstituteString(&arguments[1],"-","");
4063 (void) InvokeDynamicImageFilter(arguments[1],&images,
4064 number_arguments-2,(const char **) arguments+2,exception);
4065 for (j=0; j < number_arguments; j++)
4066 arguments[j]=DestroyString(arguments[j]);
4067 arguments=(char **) RelinquishMagickMemory(arguments);
4074 if (LocaleCompare("remap",option+1) == 0)
4076 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
4077 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
4080 if (LocaleCompare("reverse",option+1) == 0)
4082 ReverseImageList(&images);
4089 if (LocaleCompare("smush",option+1) == 0)
4097 offset=(ssize_t) StringToLong(arg1);
4098 smush_image=SmushImages(images,normal_op,offset,exception);
4099 if (smush_image == (Image *) NULL)
4101 images=DestroyImageList(images);
4105 if (LocaleCompare("swap",option+1) == 0)
4127 flags=ParseGeometry(arg1,&geometry_info);
4128 index=(ssize_t) geometry_info.rho;
4129 if ((flags & SigmaValue) != 0)
4130 swap_index=(ssize_t) geometry_info.sigma;
4132 p=GetImageFromList(images,index);
4133 q=GetImageFromList(images,swap_index);
4134 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4136 (void) ThrowMagickException(exception,GetMagickModule(),
4137 OptionError,"NoSuchImage","'%s'",images->filename);
4142 swap=CloneImage(p,0,0,MagickTrue,exception);
4143 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4144 ReplaceImageInList(&q,swap);
4145 images=GetFirstImageInList(q);
4152 if (LocaleCompare("write",option+1) == 0)
4163 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4164 (void) DeleteImageRegistry(key);
4165 write_images=images;
4167 write_images=CloneImageList(images,exception);
4168 write_info=CloneImageInfo(image_info);
4169 (void) WriteImages(write_info,write_images,arg1,exception);
4170 write_info=DestroyImageInfo(write_info);
4172 write_images=DestroyImageList(write_images);
4180 if (new_images == (Image *) NULL)
4183 if (images != (Image *) NULL)
4184 images=DestroyImageList(images);
4185 images=GetFirstImageInList(new_images);
4192 #undef quantize_info
4199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4203 + C L I S p e c i a l O p e r a t i o n s %
4207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4209 % CLISpecialOption() Applies operations that may involve empty image lists
4210 % and or stacks of image lists or image_info settings.
4212 % The classic operators of this type is -read, and image stack operators,
4213 % which can be applied to empty image lists.
4215 % Note: unlike other Operators, these may involve other special 'option'
4216 % character prefixes, other than simply '-' or '+'.
4218 % The format of the CLISpecialOption method is:
4220 % void CLISpecialOption(MagickCLI *cli_wand,const char *option,
4223 % A description of each parameter follows:
4225 % o cli_wand: the main CLI Wand to use.
4227 % o option: The special option (with any switch char) to process
4229 % o arg: Argument for option, if required
4233 % CLISpecialOperator(cli_wand,"-read", "rose:");
4235 % Or for handling command line arguments EG: +/-option ["arg"]
4241 % option_info = GetCommandOptionInfo(argv[i]);
4242 % count=option_info->type;
4243 % option_type=option_info->flags;
4245 % if ( (option_type & SpecialOptionFlag) != 0 )
4246 % CLISpecialOperator(cli_wand,argv[i],
4247 % count>=1 ? argv[i+1] : (char *)NULL);
4252 WandExport void CLISpecialOperator(MagickCLI *cli_wand,
4253 const char *option, const char *arg)
4255 #define exception (cli_wand->wand.exception)
4257 assert(cli_wand != (MagickCLI *) NULL);
4258 assert(cli_wand->signature == WandSignature);
4259 assert(cli_wand->wand.signature == WandSignature);
4260 if (cli_wand->wand.debug != MagickFalse)
4261 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4263 if (LocaleCompare("(",option) == 0)
4265 /* stack 'push' images */
4276 node=cli_wand->image_list_stack;
4277 for ( ; node != (Stack *)NULL; node=node->next)
4279 if ( size >= MAX_STACK_DEPTH )
4281 ThrowMagickException(exception,GetMagickModule(),
4282 OptionError,"ParenthesisNestedTooDeeply", option);
4285 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4286 if (node == (Stack *) NULL)
4288 ThrowMagickException(exception,GetMagickModule(),
4289 ResourceLimitFatalError,"MemoryAllocationFailed", "PushImages");
4292 node->data = (void *)cli_wand->wand.images;
4293 cli_wand->wand.images = NewImageList();
4294 node->next = cli_wand->image_list_stack;
4295 cli_wand->image_list_stack = node;
4297 /* handle respect-parenthesis */
4298 value=GetImageOption(cli_wand->wand.image_info,"respect-parenthesis");
4299 if (value != (const char *) NULL)
4304 if (LocaleCompare("{",option) == 0)
4306 /* stack 'push' of image_info settings */
4314 node=cli_wand->image_info_stack;
4315 for ( ; node != (Stack *)NULL; node=node->next)
4317 if ( size >= MAX_STACK_DEPTH ) {
4318 ThrowMagickException(exception,GetMagickModule(),
4319 OptionError,"ParenthesisNestedTooDeeply", option);
4322 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4323 if (node == (Stack *) NULL) {
4324 ThrowMagickException(exception,GetMagickModule(),
4325 ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
4329 node->data = (void *)cli_wand->wand.image_info;
4330 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4331 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4332 ThrowMagickException(exception,GetMagickModule(),
4333 ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
4334 cli_wand->wand.image_info = (ImageInfo *)node->data;
4335 node = (Stack *)RelinquishMagickMemory(node);
4339 node->next = cli_wand->image_info_stack;
4340 cli_wand->image_info_stack = node;
4344 if (LocaleCompare(")",option) == 0)
4346 /* pop images from stack */
4353 node = (void *)cli_wand->image_list_stack;
4354 if ( node == (Stack *)NULL)
4356 ThrowMagickException(exception,GetMagickModule(),
4357 OptionError,"UnbalancedParenthesis", option);
4360 cli_wand->image_list_stack = node->next;
4362 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4363 cli_wand->wand.images= (Image *)node->data;
4364 node = (Stack *)RelinquishMagickMemory(node);
4366 /* handle respect-parenthesis - of the previous 'push' settings */
4367 node = cli_wand->image_info_stack;
4368 if ( node != (Stack *)NULL)
4370 value=GetImageOption((ImageInfo *)node->data,"respect-parenthesis");
4371 if (value != (const char *) NULL)
4379 if (LocaleCompare("}",option) == 0)
4381 /* pop image_info settings from stack */
4385 node = (void *)cli_wand->image_info_stack;
4386 if ( node == (Stack *)NULL)
4388 ThrowMagickException(exception,GetMagickModule(),
4389 OptionError,"UnbalancedParenthesis", option);
4392 cli_wand->image_info_stack = node->next;
4394 (void) DestroyImageInfo(cli_wand->wand.image_info);
4395 cli_wand->wand.image_info = (ImageInfo *)node->data;
4396 node = (Stack *)RelinquishMagickMemory(node);
4398 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4399 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4400 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4404 if (LocaleCompare("clone",option+1) == 0)
4411 if (IsSceneGeometry(arg,MagickFalse) == MagickFalse)
4413 ThrowMagickException(exception,GetMagickModule(),
4414 OptionError,"InvalidArgument", "'%s': %s", option, arg);
4417 if ( cli_wand->image_list_stack == (Stack *)NULL)
4419 ThrowMagickException(exception,GetMagickModule(),
4420 OptionError,"UnableToCloneImage", option);
4423 new_images = (Image *)cli_wand->image_list_stack->data;
4424 if (new_images == (Image *) NULL)
4426 ThrowMagickException(exception,GetMagickModule(),
4427 OptionError,"UnableToCloneImage", option);
4430 new_images=CloneImages(new_images,arg,exception);
4431 if (new_images == (Image *) NULL)
4433 ThrowMagickException(exception,GetMagickModule(),
4434 OptionError,"NoSuchImage",option);
4437 AppendImageToList(&cli_wand->wand.images,new_images);
4440 if ( LocaleCompare("read",option+1) == 0 )
4442 #if !USE_WAND_METHODS
4446 if (cli_wand->wand.image_info->ping != MagickFalse)
4447 new_images=PingImages(cli_wand->wand.image_info,arg,exception);
4449 new_images=ReadImages(cli_wand->wand.image_info,arg,exception);
4450 AppendImageToList(&cli_wand->wand.images, new_images);
4452 /* read images using MagickWand method - no ping */
4453 /* This is not working! - it locks up in a CPU loop! */
4454 MagickSetLastIterator(&cli_wand->wand);
4455 MagickReadImage(&cli_wand->wand,arg);
4456 MagickSetFirstIterator(&cli_wand->wand);
4461 if (LocaleCompare("noop",option+1) == 0)
4463 if (LocaleCompare("sans",option+1) == 0)
4465 if (LocaleCompare("sans0",option+1) == 0)
4467 if (LocaleCompare("sans2",option+1) == 0)
4469 if (LocaleCompare("list",option+1) == 0)
4471 /* FUTURE: This should really be built into the MagickCore
4472 It does not actually require any wand or images at all!
4477 list=ParseCommandOption(MagickListOptions,MagickFalse, arg);
4480 case MagickCoderOptions:
4482 (void) ListCoderInfo((FILE *) NULL,exception);
4485 case MagickColorOptions:
4487 (void) ListColorInfo((FILE *) NULL,exception);
4490 case MagickConfigureOptions:
4492 (void) ListConfigureInfo((FILE *) NULL,exception);
4495 case MagickDelegateOptions:
4497 (void) ListDelegateInfo((FILE *) NULL,exception);
4500 case MagickFontOptions:
4502 (void) ListTypeInfo((FILE *) NULL,exception);
4505 case MagickFormatOptions:
4506 (void) ListMagickInfo((FILE *) NULL,exception);
4508 case MagickLocaleOptions:
4509 (void) ListLocaleInfo((FILE *) NULL,exception);
4511 case MagickLogOptions:
4512 (void) ListLogInfo((FILE *) NULL,exception);
4514 case MagickMagicOptions:
4515 (void) ListMagicInfo((FILE *) NULL,exception);
4517 case MagickMimeOptions:
4518 (void) ListMimeInfo((FILE *) NULL,exception);
4520 case MagickModuleOptions:
4521 (void) ListModuleInfo((FILE *) NULL,exception);
4523 case MagickPolicyOptions:
4524 (void) ListPolicyInfo((FILE *) NULL,exception);
4526 case MagickResourceOptions:
4527 (void) ListMagickResourceInfo((FILE *) NULL,exception);
4529 case MagickThresholdOptions:
4530 (void) ListThresholdMaps((FILE *) NULL,exception);
4533 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4541 // adjust stack handling
4542 // Other 'special' options this should handle
4543 // "region" "list" "version"
4544 // It does not do "exit" however as due to its side-effect requirements
4547 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
4548 MagickExceptionReturn(OptionError,"InvalidUseOfOption",option);