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 "MagickCore/monitor-private.h"
55 #include "MagickCore/thread-private.h"
56 #include "MagickCore/string-private.h"
61 #define UndefinedCompressionQuality 0UL
63 Constant declaration. (temporary exports)
66 BackgroundColor[] = "#fff", /* white */
67 BorderColor[] = "#dfdfdf", /* sRGB gray */
68 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
71 ** Function to report on the progress of image operations
73 static MagickBooleanType MonitorProgress(const char *text,
74 const MagickOffsetType offset,const MagickSizeType extent,
75 void *wand_unused(client_data))
78 message[MaxTextExtent],
89 (void) CopyMagickMemory(tag,text,MaxTextExtent);
91 if (p != (char *) NULL)
93 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
94 locale_message=GetLocaleMessage(message);
95 if (locale_message == message)
97 if (p == (char *) NULL)
98 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
99 locale_message,(long) offset,(unsigned long) extent,(long)
100 (100L*offset/(extent-1)));
102 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
103 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
104 (100L*offset/(extent-1)));
105 if (offset == (MagickOffsetType) (extent-1))
106 (void) FormatLocaleFile(stderr,"\n");
107 (void) fflush(stderr);
112 ** GetImageCache() will read an image into a image cache if not already
113 ** present then return the image that is in the cache under that filename.
115 static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
116 ExceptionInfo *exception)
130 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
131 sans_exception=AcquireExceptionInfo();
132 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
133 sans_exception=DestroyExceptionInfo(sans_exception);
134 if (image != (Image *) NULL)
136 read_info=CloneImageInfo(image_info);
137 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
138 image=ReadImage(read_info,exception);
139 read_info=DestroyImageInfo(read_info);
140 if (image != (Image *) NULL)
141 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
146 SparseColorOption() parse the complex -sparse-color argument into an
147 an array of floating point values than call SparseColorImage().
148 Argument is a complex mix of floating-point pixel coodinates, and color
149 specifications (or direct floating point numbers). The number of floats
150 needed to represent a color varies depending on teh current channel
153 static Image *SparseColorOption(const Image *image,
154 const SparseColorMethod method,const char *arguments,
155 ExceptionInfo *exception)
158 token[MaxTextExtent];
182 assert(image != (Image *) NULL);
183 assert(image->signature == MagickSignature);
184 if (image->debug != MagickFalse)
185 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
186 assert(exception != (ExceptionInfo *) NULL);
187 assert(exception->signature == MagickSignature);
189 Limit channels according to image - and add up number of color channel.
192 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
194 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
196 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
198 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
199 (image->colorspace == CMYKColorspace))
201 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
202 (image->matte != MagickFalse))
206 Read string, to determine number of arguments needed,
212 GetMagickToken(p,&p,token);
213 if ( token[0] == ',' ) continue;
214 if ( isalpha((int) token[0]) || token[0] == '#' )
215 x += number_colors; /* color argument found */
217 x++; /* floating point argument */
221 /* control points and color values */
222 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
225 (void) ThrowMagickException(exception,GetMagickModule(),
226 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
227 "Invalid number of Arguments");
228 return( (Image *)NULL);
231 /* Allocate and fill in the floating point arguments */
232 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
233 sizeof(*sparse_arguments));
234 if (sparse_arguments == (double *) NULL) {
235 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
236 "MemoryAllocationFailed","%s","SparseColorOption");
237 return( (Image *)NULL);
239 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
240 sizeof(*sparse_arguments));
243 while( *p != '\0' && x < number_arguments ) {
245 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
246 if ( token[0] == '\0' ) break;
247 if ( isalpha((int) token[0]) || token[0] == '#' ) {
248 (void) ThrowMagickException(exception,GetMagickModule(),
249 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
250 "Color found, instead of X-coord");
254 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
256 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
257 if ( token[0] == '\0' ) break;
258 if ( isalpha((int) token[0]) || token[0] == '#' ) {
259 (void) ThrowMagickException(exception,GetMagickModule(),
260 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
261 "Color found, instead of Y-coord");
265 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
266 /* color name or function given in string argument */
267 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
268 if ( token[0] == '\0' ) break;
269 if ( isalpha((int) token[0]) || token[0] == '#' ) {
270 /* Color string given */
271 (void) QueryColorCompliance(token,AllCompliance,&color,
273 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
274 sparse_arguments[x++] = QuantumScale*color.red;
275 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
276 sparse_arguments[x++] = QuantumScale*color.green;
277 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
278 sparse_arguments[x++] = QuantumScale*color.blue;
279 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
280 (image->colorspace == CMYKColorspace))
281 sparse_arguments[x++] = QuantumScale*color.black;
282 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
283 (image->matte != MagickFalse))
284 sparse_arguments[x++] = QuantumScale*color.alpha;
287 /* Colors given as a set of floating point values - experimental */
288 /* NB: token contains the first floating point value to use! */
289 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
291 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
292 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
294 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
295 token[0] = ','; /* used this token - get another */
297 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
299 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
300 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
302 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
303 token[0] = ','; /* used this token - get another */
305 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
307 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
308 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
310 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
311 token[0] = ','; /* used this token - get another */
313 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
314 (image->colorspace == CMYKColorspace))
316 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
317 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
319 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
320 token[0] = ','; /* used this token - get another */
322 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
323 (image->matte != MagickFalse))
325 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
326 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
328 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
329 token[0] = ','; /* used this token - get another */
333 if ( number_arguments != x && !error ) {
334 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
335 "InvalidArgument","`%s': %s","sparse-color","Argument Parsing Error");
336 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
337 return( (Image *)NULL);
340 return( (Image *)NULL);
342 /* Call the Sparse Color Interpolation function with the parsed arguments */
343 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
345 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
346 return( sparse_image );
350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354 + W a n d S e t t i n g O p t i o n I n f o %
358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360 % WandSettingOptionInfo() applies a single settings option into a CLI wand
361 % holding the image_info, draw_info, quantize_info structures that will be
362 % used when processing the images also found within the wand.
364 % These options do no require images to be present in the wand for them to be
365 % able to be set, in which case they will be applied to
367 % Options handled by this function are listed in CommandOptions[] of
368 % "option.c" that is one of "SettingOptionFlags" option flags.
370 % The format of the WandSettingOptionInfo method is:
372 % void WandSettingOptionInfo(MagickWand *wand,const char *option,
375 % A description of each parameter follows:
377 % o wand: structure holding settings to be applied
379 % o option: The option string to be set
381 % o arg: The single argument used to set this option.
382 % If NULL the setting is reset to its default value.
383 % For boolean (no argument) settings false=NULL, true=any_string
387 % WandSettingOptionInfo(wand, "background", MagickTrue, "Red");
388 % WandSettingOptionInfo(wand, "adjoin", "true");
389 % WandSettingOptionInfo(wand, "adjoin", NULL);
391 % Or for handling command line arguments EG: +/-option ["arg"]
396 % count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
397 % flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
398 % if ( (flags & SettingOptionFlags) != 0 )
399 % WandSettingOptionInfo(wand, argv[i]+1,
400 % (((*argv[i])!='-') ? (char *)NULL
401 % : (count>0) ? argv[i+1] : "true") );
405 WandExport void WandSettingOptionInfo(MagickWand *wand,const char *option,
408 assert(wand != (MagickWand *) NULL);
409 assert(wand->signature == WandSignature);
410 assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
411 if (wand->debug != MagickFalse)
412 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
414 #define image_info (wand->image_info)
415 #define draw_info (wand->draw_info)
416 #define quantize_info (wand->quantize_info)
417 #define exception (wand->exception)
418 #define IfSetOption (arg!=(char *)NULL)
419 #define ArgOption(def) (IfSetOption?arg:(const char *)(def))
420 #define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
426 if (LocaleCompare("adjoin",option) == 0)
428 image_info->adjoin = ArgBoolean;
431 if (LocaleCompare("affine",option) == 0)
433 /* DEPRECIATED: draw_info setting only: for -draw and -transform */
435 (void) ParseAffineGeometry(arg,&draw_info->affine,exception);
437 GetAffineMatrix(&draw_info->affine);
440 if (LocaleCompare("antialias",option) == 0)
442 image_info->antialias =
443 draw_info->stroke_antialias =
444 draw_info->text_antialias = ArgBoolean;
447 if (LocaleCompare("attenuate",option+1) == 0)
449 (void) SetImageOption(image_info,option,ArgOption(NULL));
452 if (LocaleCompare("authenticate",option) == 0)
454 (void) SetImageOption(image_info,option,ArgOption(NULL));
461 if (LocaleCompare("background",option) == 0)
463 /* FUTURE: both image_info attribute & ImageOption in use!
464 image_info only used directly for generating new images.
465 SyncImageSettings() used to set per-image attribute.
467 FUTURE: if image_info->background_color is not set then
468 we should fall back to image
469 Note that +background, means fall-back to image background
470 and only if not set fall back to BackgroundColor const.
472 (void) SetImageOption(image_info,option,ArgOption(NULL));
473 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
474 &image_info->background_color,exception);
477 if (LocaleCompare("bias",option) == 0)
479 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
480 as it is actually rarely used except in direct convolve operations
481 Usage outside a direct convolve operation is actally non-sensible!
483 SyncImageSettings() used to set per-image attribute.
485 (void) SetImageOption(image_info,option,ArgOption("0"));
488 if (LocaleCompare("black-point-compensation",option) == 0)
490 /* Used as a image chromaticity setting
491 SyncImageSettings() used to set per-image attribute.
493 (void) SetImageOption(image_info,option,
494 IfSetOption ? "true" : "false" );
497 if (LocaleCompare("blue-primary",option) == 0)
499 /* Image chromaticity X,Y NB: Y=X if Y not defined
500 Used by many coders including PNG
501 SyncImageSettings() used to set per-image attribute.
503 (void) SetImageOption(image_info,option,ArgOption("0.0"));
506 if (LocaleCompare("bordercolor",option) == 0)
508 /* FUTURE: both image_info attribute & ImageOption in use!
509 SyncImageSettings() used to set per-image attribute.
513 (void) SetImageOption(image_info,option,arg);
514 (void) QueryColorCompliance(arg,AllCompliance,
515 &image_info->border_color,exception);
516 (void) QueryColorCompliance(arg,AllCompliance,
517 &draw_info->border_color,exception);
520 (void) DeleteImageOption(image_info,option);
521 (void) QueryColorCompliance(BorderColor,AllCompliance,
522 &image_info->border_color,exception);
523 (void) QueryColorCompliance(BorderColor,AllCompliance,
524 &draw_info->border_color,exception);
527 if (LocaleCompare("box",option) == 0)
529 /* DEPRECIATED - now "undercolor" */
530 WandSettingOptionInfo(wand,"undercolor",arg);
537 if (LocaleCompare("cache",option) == 0)
542 limit=MagickResourceInfinity;
543 if (LocaleCompare("unlimited",arg) != 0)
544 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg,100.0);
545 (void) SetMagickResourceLimit(MemoryResource,limit);
546 (void) SetMagickResourceLimit(MapResource,2*limit);
549 if (LocaleCompare("caption",option) == 0)
551 (void) SetImageOption(image_info,option,ArgOption(NULL));
554 if (LocaleCompare("channel",option) == 0)
556 /* This is applied to images in SimpleImageOperator!!!
557 FUTURE: move it to SyncImageSettings() - or alternative
559 image_info->channel=(ChannelType) (
560 IfSetOption ? ParseChannelOption(arg) : DefaultChannels );
563 if (LocaleCompare("colorspace",option) == 0)
565 /* Setting used for new images via AquireImage()
566 But also used as a SimpleImageOperator
567 Undefined colorspace means don't modify images on
568 read or as a operation */
569 image_info->colorspace=(ColorspaceType) ParseCommandOption(
570 MagickColorspaceOptions,MagickFalse,ArgOption("undefined"));
573 if (LocaleCompare("comment",option) == 0)
575 (void) SetImageOption(image_info,option,ArgOption(NULL));
578 if (LocaleCompare("compose",option) == 0)
580 /* FUTURE: image_info should be used,
581 SyncImageSettings() used to set per-image attribute. - REMOVE
583 This setting should NOT be used to set image 'compose'
584 "-layer" operators shoud use image_info if defined otherwise
585 they should use a per-image compose setting.
587 (void) SetImageOption(image_info,option,ArgOption(NULL));
588 image_info->compose=(CompositeOperator) ParseCommandOption(
589 MagickComposeOptions,MagickFalse,ArgOption("undefined"));
592 if (LocaleCompare("compress",option) == 0)
594 /* FUTURE: What should be used? image_info or ImageOption ???
595 The former is more efficent, but Crisy prefers the latter!
596 SyncImageSettings() used to set per-image attribute.
598 The coders appears to use image_info, not Image_Option
599 however the image attribute (for save) is set from the
602 Note that "undefined" is a different setting to "none".
604 (void) SetImageOption(image_info,option,ArgOption(NULL));
605 image_info->compression=(CompressionType) ParseCommandOption(
606 MagickCompressOptions,MagickFalse,ArgOption("undefined"));
613 if (LocaleCompare("debug",option) == 0)
615 /* SyncImageSettings() used to set per-image attribute. */
616 (void) SetLogEventMask(ArgOption("none"));
617 image_info->debug=IsEventLogging(); /* extract logging*/
618 wand->debug=IsEventLogging();
621 if (LocaleCompare("define",option) == 0)
623 /* DefineImageOption() equals SetImageOption() but with '='
624 It does not however set individual image options.
625 -set will set individual image options as well!
627 if (LocaleNCompare(arg,"registry:",9) == 0)
630 (void) DefineImageRegistry(StringRegistryType,arg+9,
633 (void) DeleteImageRegistry(arg+9);
637 (void) DefineImageOption(image_info,arg);
639 (void) DeleteImageOption(image_info,arg);
642 if (LocaleCompare("delay",option) == 0)
644 /* Only used for new images via AcquireImage()
645 FUTURE: Option should also be used for "-morph" (color morphing)
647 (void) SetImageOption(image_info,option,ArgOption("0"));
650 if (LocaleCompare("density",option) == 0)
652 /* FUTURE: strings used in image_info attr and draw_info!
653 Basically as density can be in a XxY form!
655 SyncImageSettings() used to set per-image attribute.
657 (void) SetImageOption(image_info,option,ArgOption(NULL));
658 (void) CloneString(&image_info->density,ArgOption(NULL));
659 (void) CloneString(&draw_info->density,image_info->density);
662 if (LocaleCompare("depth",option) == 0)
664 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
665 SyncImageSettings() used to set per-image attribute.
667 image_info->depth=IfSetOption?StringToUnsignedLong(arg)
668 :MAGICKCORE_QUANTUM_DEPTH;
671 if (LocaleCompare("direction",option) == 0)
673 /* Image Option is only used to set draw_info */
674 (void) SetImageOption(image_info,option,ArgOption("undefined"));
675 draw_info->direction=(DirectionType) ParseCommandOption(
676 MagickDirectionOptions,MagickFalse,
677 ArgOption("undefined"));
680 if (LocaleCompare("display",option) == 0)
682 (void) CloneString(&image_info->server_name,ArgOption(NULL));
683 (void) CloneString(&draw_info->server_name,image_info->server_name);
686 if (LocaleCompare("dispose",option) == 0)
688 /* only used in setting new images */
689 (void) SetImageOption(image_info,option,ArgOption("undefined"));
692 if (LocaleCompare("dither",option) == 0)
694 /* image_info attr (on/off), quantize_info attr (on/off)
695 but also ImageInfo and quantize_info method!
696 FUTURE: merge the duality of the dithering options
698 image_info->dither = quantize_info->dither = ArgBoolean;
699 (void) SetImageOption(image_info,option,ArgOption("none"));
700 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
701 MagickDitherOptions,MagickFalse,ArgOption("none"));
702 if (quantize_info->dither_method == NoDitherMethod)
703 image_info->dither = quantize_info->dither = MagickFalse;
710 if (LocaleCompare("encoding",option) == 0)
712 (void) CloneString(&draw_info->encoding,ArgOption("undefined"));
713 (void) SetImageOption(image_info,option,draw_info->encoding);
716 if (LocaleCompare("endian",option) == 0)
718 /* Both image_info attr and ImageInfo */
719 (void) SetImageOption(image_info,option,ArgOption("undefined"));
720 image_info->endian=(EndianType) ParseCommandOption(
721 MagickEndianOptions,MagickFalse,ArgOption("undefined"));
724 if (LocaleCompare("extract",option) == 0)
726 (void) CloneString(&image_info->extract,ArgOption(NULL));
733 if (LocaleCompare("family",option) == 0)
735 (void) CloneString(&draw_info->family,ArgOption(NULL));
738 if (LocaleCompare("fill",option) == 0)
740 /* Set "fill" OR "fill-pattern" in draw_info
741 The original fill color is preserved if a fill-pattern is given.
742 That way it does not effect other operations that directly using
743 the fill color and, can be retored using "+tile".
757 value = ArgOption("none");
758 (void) SetImageOption(image_info,option,value);
759 if (draw_info->fill_pattern != (Image *) NULL)
760 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
762 /* is it a color or a image? -- ignore exceptions */
763 sans=AcquireExceptionInfo();
764 status=QueryColorCompliance(value,AllCompliance,&color,sans);
765 sans=DestroyExceptionInfo(sans);
767 if (status == MagickFalse)
768 draw_info->fill_pattern=GetImageCache(image_info,value,exception);
770 draw_info->fill=color;
773 if (LocaleCompare("filter",option) == 0)
775 /* SyncImageSettings() used to set per-image attribute. */
776 (void) SetImageOption(image_info,option,ArgOption("undefined"));
779 if (LocaleCompare("font",option) == 0)
781 (void) CloneString(&draw_info->font,ArgOption(NULL));
782 (void) CloneString(&image_info->font,draw_info->font);
785 if (LocaleCompare("format",option) == 0)
787 /* FUTURE: why the ping test, you could set ping after this! */
792 for (q=strchr(arg,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
793 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
794 image_info->ping=MagickFalse;
796 (void) SetImageOption(image_info,option,ArgOption(NULL));
799 if (LocaleCompare("fuzz",option) == 0)
801 /* Option used to set image fuzz! unless blank canvas (from color)
802 Image attribute used for color compare operations
803 SyncImageSettings() used to set per-image attribute.
805 Can't find anything else using image_info->fuzz directly!
809 image_info->fuzz=StringToDoubleInterval(arg,(double)
811 (void) SetImageOption(image_info,option,arg);
814 image_info->fuzz=0.0;
815 (void) SetImageOption(image_info,option,"0");
822 if (LocaleCompare("gravity",option) == 0)
824 /* SyncImageSettings() used to set per-image attribute. */
825 (void) SetImageOption(image_info,option,ArgOption("none"));
826 draw_info->gravity=(GravityType) ParseCommandOption(
827 MagickGravityOptions,MagickFalse,ArgOption("none"));
830 if (LocaleCompare("green-primary",option) == 0)
832 /* Image chromaticity X,Y NB: Y=X if Y not defined
833 SyncImageSettings() used to set per-image attribute.
834 Used directly by many coders
836 (void) SetImageOption(image_info,option,ArgOption("0.0"));
843 if (LocaleCompare("intent",option) == 0)
845 /* Only used by coders: MIFF, MPC, BMP, PNG
846 and for image profile call to AcquireTransformThreadSet()
847 SyncImageSettings() used to set per-image attribute.
849 (void) SetImageOption(image_info,option,ArgOption("undefined"));
852 if (LocaleCompare("interlace",option) == 0)
854 /* image_info is directly used by coders (so why an image setting?)
855 SyncImageSettings() used to set per-image attribute.
857 (void) SetImageOption(image_info,option,ArgOption("undefined"));
858 image_info->interlace=(InterlaceType) ParseCommandOption(
859 MagickInterlaceOptions,MagickFalse,ArgOption("undefined"));
862 if (LocaleCompare("interline-spacing",option) == 0)
864 (void) SetImageOption(image_info,option, ArgOption(NULL));
865 draw_info->interline_spacing=StringToDouble(ArgOption("0"),
869 if (LocaleCompare("interpolate",option) == 0)
871 /* SyncImageSettings() used to set per-image attribute. */
872 (void) SetImageOption(image_info,option,ArgOption("undefined"));
875 if (LocaleCompare("interword-spacing",option) == 0)
877 (void) SetImageOption(image_info,option, ArgOption(NULL));
878 draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
885 if (LocaleCompare("kerning",option) == 0)
887 (void) SetImageOption(image_info,option,ArgOption(NULL));
888 draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
895 if (LocaleCompare("label",option) == 0)
897 /* only used for new images - not in SyncImageOptions() */
898 (void) SetImageOption(image_info,option,ArgOption(NULL));
901 if (LocaleCompare("list",option) == 0)
906 /* FUTURE: This is not really a Setting Option, but a Special
907 * The bulk of this should be turned into a MagickCore function
909 list=ParseCommandOption(MagickListOptions,MagickFalse,
913 case MagickCoderOptions:
915 (void) ListCoderInfo((FILE *) NULL,exception);
918 case MagickColorOptions:
920 (void) ListColorInfo((FILE *) NULL,exception);
923 case MagickConfigureOptions:
925 (void) ListConfigureInfo((FILE *) NULL,exception);
928 case MagickDelegateOptions:
930 (void) ListDelegateInfo((FILE *) NULL,exception);
933 case MagickFontOptions:
935 (void) ListTypeInfo((FILE *) NULL,exception);
938 case MagickFormatOptions:
940 (void) ListMagickInfo((FILE *) NULL,exception);
943 case MagickLocaleOptions:
945 (void) ListLocaleInfo((FILE *) NULL,exception);
948 case MagickLogOptions:
950 (void) ListLogInfo((FILE *) NULL,exception);
953 case MagickMagicOptions:
955 (void) ListMagicInfo((FILE *) NULL,exception);
958 case MagickMimeOptions:
960 (void) ListMimeInfo((FILE *) NULL,exception);
963 case MagickModuleOptions:
965 (void) ListModuleInfo((FILE *) NULL,exception);
968 case MagickPolicyOptions:
970 (void) ListPolicyInfo((FILE *) NULL,exception);
973 case MagickResourceOptions:
975 (void) ListMagickResourceInfo((FILE *) NULL,exception);
978 case MagickThresholdOptions:
980 (void) ListThresholdMaps((FILE *) NULL,exception);
985 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
992 if (LocaleCompare("log",option) == 0)
995 (void) SetLogFormat(arg);
998 if (LocaleCompare("loop",option) == 0)
1000 /* SyncImageSettings() used to set per-image attribute. */
1001 (void) SetImageOption(image_info,option,ArgOption("0"));
1008 if (LocaleCompare("mattecolor",option) == 0)
1010 /* SyncImageSettings() used to set per-image attribute. */
1011 (void) SetImageOption(image_info,option,ArgOption(NULL));
1012 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
1013 &image_info->matte_color,exception);
1016 if (LocaleCompare("monitor",option) == 0)
1018 (void) SetImageInfoProgressMonitor(image_info, IfSetOption?
1019 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
1022 if (LocaleCompare("monochrome",option) == 0)
1024 /* Setting (for some input coders)
1025 But also a special 'type' operator
1027 image_info->monochrome= ArgBoolean;
1034 if (LocaleCompare("orient",option) == 0)
1036 /* Is not used when defining for new images.
1037 This makes it more of a 'operation' than a setting
1038 FUTURE: make set meta-data operator instead.
1039 SyncImageSettings() used to set per-image attribute.
1041 (void) SetImageOption(image_info,option, ArgOption(NULL));
1042 image_info->orientation=(InterlaceType) ParseCommandOption(
1043 MagickOrientationOptions,MagickFalse,ArgOption("undefined"));
1049 if (LocaleCompare("page",option) == 0)
1051 /* Only used for new images and image generators
1052 SyncImageSettings() used to set per-image attribute. ?????
1053 That last is WRONG!!!!
1057 page[MaxTextExtent];
1070 (void) DeleteImageOption(image_info,option);
1071 (void) CloneString(&image_info->page,(char *) NULL);
1074 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1075 image_option=GetImageOption(image_info,"page");
1076 if (image_option != (const char *) NULL)
1077 flags=ParseAbsoluteGeometry(image_option,&geometry);
1078 canonical_page=GetPageGeometry(arg);
1079 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1080 canonical_page=DestroyString(canonical_page);
1081 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1082 (unsigned long) geometry.width,(unsigned long) geometry.height);
1083 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1084 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1085 (unsigned long) geometry.width,(unsigned long) geometry.height,
1086 (long) geometry.x,(long) geometry.y);
1087 (void) SetImageOption(image_info,option,page);
1088 (void) CloneString(&image_info->page,page);
1091 if (LocaleCompare("ping",option) == 0)
1093 image_info->ping = ArgBoolean;
1096 if (LocaleCompare("pointsize",option) == 0)
1098 image_info->pointsize=draw_info->pointsize=
1099 StringToDouble(ArgOption("12"),(char **) NULL);
1102 if (LocaleCompare("precision",option) == 0)
1104 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
1107 /* FUTURE: Only the 'preview' coder appears to use this
1108 * Depreciate the coder? Leaving only the 'preview' operator.
1109 if (LocaleCompare("preview",option) == 0)
1111 image_info->preview_type=UndefinedPreview;
1113 image_info->preview_type=(PreviewType) ParseCommandOption(
1114 MagickPreviewOptions,MagickFalse,arg);
1122 if (LocaleCompare("quality",option) == 0)
1124 (void) SetImageOption(image_info,option,ArgOption(NULL));
1125 image_info->quality=UndefinedCompressionQuality;
1127 image_info->quality=StringToUnsignedLong(arg);
1130 if (LocaleCompare("quantize",option) == 0)
1132 /* Just a set direct in quantize_info */
1133 quantize_info->colorspace=UndefinedColorspace;
1135 quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
1136 MagickColorspaceOptions,MagickFalse,arg);
1139 if (LocaleCompare("quiet",option) == 0)
1141 /* FUTURE: if two -quiet is performed you can not do +quiet! */
1142 static WarningHandler
1143 warning_handler = (WarningHandler) NULL;
1146 tmp = SetWarningHandler((WarningHandler) NULL);
1148 if ( tmp != (WarningHandler) NULL)
1149 warning_handler = tmp; /* remember the old handler */
1150 if (!IfSetOption) /* set the old handler */
1151 warning_handler=SetWarningHandler(warning_handler);
1158 if (LocaleCompare("red-primary",option) == 0)
1160 /* Image chromaticity X,Y NB: Y=X if Y not defined
1162 SyncImageSettings() used to set per-image attribute.
1164 (void) SetImageOption(image_info,option,ArgOption("0.0"));
1167 if (LocaleCompare("render",option) == 0)
1169 /* draw_info only setting */
1170 draw_info->render= IfSetOption ? MagickFalse : MagickTrue;
1177 if (LocaleCompare("sampling-factor",option) == 0)
1179 /* FUTURE: should be converted to jpeg:sampling_factor */
1180 (void) CloneString(&image_info->sampling_factor,ArgOption(NULL));
1183 if (LocaleCompare("scene",option) == 0)
1185 /* SyncImageSettings() used to set per-image attribute.
1188 (void) SetImageOption(image_info,option,ArgOption(NULL));
1189 image_info->scene=StringToUnsignedLong(ArgOption("0"));
1192 if (LocaleCompare("seed",option) == 0)
1194 SeedPseudoRandomGenerator(
1195 IfSetOption ? (size_t) StringToUnsignedLong(arg)
1196 : (size_t) time((time_t *) NULL) );
1199 if (LocaleCompare("size",option) == 0)
1201 /* FUTURE: string in image_info -- convert to Option ???
1202 Look at the special handling for "size" in SetImageOption()
1204 (void) CloneString(&image_info->size,ArgOption(NULL));
1207 if (LocaleCompare("stretch",option) == 0)
1209 draw_info->stretch=(StretchType) ParseCommandOption(
1210 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
1213 if (LocaleCompare("stroke",option) == 0)
1215 /* set stroke color OR stroke-pattern
1216 UPDATE: ensure stroke color is not destroyed is a pattern
1217 is given. Just in case the color is also used for other purposes.
1231 value = ArgOption("none");
1232 (void) SetImageOption(image_info,option,value);
1233 if (draw_info->stroke_pattern != (Image *) NULL)
1234 draw_info->stroke_pattern=DestroyImage(draw_info->stroke_pattern);
1236 /* is it a color or a image? -- ignore exceptions */
1237 sans=AcquireExceptionInfo();
1238 status=QueryColorCompliance(value,AllCompliance,&color,sans);
1239 sans=DestroyExceptionInfo(sans);
1241 if (status == MagickFalse)
1242 draw_info->stroke_pattern=GetImageCache(image_info,value,exception);
1244 draw_info->stroke=color;
1247 if (LocaleCompare("strokewidth",option) == 0)
1249 (void) SetImageOption(image_info,option,ArgOption(NULL));
1250 draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1254 if (LocaleCompare("style",option) == 0)
1256 draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1257 MagickFalse,ArgOption("undefined"));
1260 if (LocaleCompare("synchronize",option) == 0)
1262 image_info->synchronize = ArgBoolean;
1269 if (LocaleCompare("taint",option) == 0)
1271 /* SyncImageSettings() used to set per-image attribute. */
1272 (void) SetImageOption(image_info,option,
1273 IfSetOption ? "true" : "false");
1276 if (LocaleCompare("texture",option) == 0)
1278 /* FUTURE: move image_info string to option splay-tree */
1279 (void) CloneString(&image_info->texture,ArgOption(NULL));
1282 if (LocaleCompare("tile",option) == 0)
1284 draw_info->fill_pattern=IfSetOption
1285 ?GetImageCache(image_info,arg,exception)
1286 :DestroyImage(draw_info->fill_pattern);
1289 if (LocaleCompare("tile-offset",option) == 0)
1291 /* SyncImageSettings() used to set per-image attribute. ??? */
1292 (void) SetImageOption(image_info,option,ArgOption("0"));
1295 if (LocaleCompare("transparent-color",option) == 0)
1297 /* FUTURE: both image_info attribute & ImageOption in use!
1298 image_info only used for generating new images.
1299 SyncImageSettings() used to set per-image attribute.
1301 Note that +transparent-color, means fall-back to image
1302 attribute so ImageOption is deleted, not set to a default.
1304 (void) SetImageOption(image_info,option,ArgOption(NULL));
1305 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1306 &image_info->transparent_color,exception);
1309 if (LocaleCompare("treedepth",option) == 0)
1311 (void) SetImageOption(image_info,option,ArgOption(NULL));
1312 quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1315 if (LocaleCompare("type",option) == 0)
1317 /* SyncImageSettings() used to set per-image attribute. */
1318 (void) SetImageOption(image_info,option,ArgOption(NULL));
1319 image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1320 MagickFalse,ArgOption("undefined"));
1327 if (LocaleCompare("undercolor",option) == 0)
1329 (void) SetImageOption(image_info,option,ArgOption(NULL));
1330 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1331 &draw_info->undercolor,exception);
1334 if (LocaleCompare("units",option) == 0)
1336 /* SyncImageSettings() used to set per-image attribute.
1337 Should this effect draw_info X and Y resolution?
1338 FUTURE: this probably should be part of the density setting
1340 (void) SetImageOption(image_info,option,ArgOption(NULL));
1341 image_info->units=(ResolutionType) ParseCommandOption(
1342 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
1349 if (LocaleCompare("verbose",option) == 0)
1351 /* FUTURE: Also an image artifact, set in Simple Operators.
1352 But artifact is only used in verbose output.
1354 (void) SetImageOption(image_info,option,ArgOption(NULL));
1355 image_info->verbose= ArgBoolean;
1356 image_info->ping=MagickFalse; /* verbose can't be a ping */
1359 if (LocaleCompare("view",option) == 0)
1361 /* FUTURE: Convert from image_info to ImageOption
1362 Only used by coder FPX
1364 (void) CloneString(&image_info->view,ArgOption(NULL));
1367 if (LocaleCompare("virtual-pixel",option) == 0)
1369 /* SyncImageSettings() used to set per-image attribute.
1370 This is VERY deep in the image caching structure.
1372 (void) SetImageOption(image_info,option,ArgOption(NULL));
1379 if (LocaleCompare("weight",option) == 0)
1381 /* Just what does using a font 'weight' do ???
1382 There is no "-list weight" output (reference manual says there is)
1386 draw_info->weight=StringToUnsignedLong(arg);
1387 if (LocaleCompare(arg,"all") == 0)
1388 draw_info->weight=0;
1389 if (LocaleCompare(arg,"bold") == 0)
1390 draw_info->weight=700;
1391 if (LocaleCompare(arg,"bolder") == 0)
1392 if (draw_info->weight <= 800)
1393 draw_info->weight+=100;
1394 if (LocaleCompare(arg,"lighter") == 0)
1395 if (draw_info->weight >= 100)
1396 draw_info->weight-=100;
1397 if (LocaleCompare(arg,"normal") == 0)
1398 draw_info->weight=400;
1401 if (LocaleCompare("white-point",option) == 0)
1403 /* Used as a image chromaticity setting
1404 SyncImageSettings() used to set per-image attribute.
1406 (void) SetImageOption(image_info,option,ArgOption("0.0"));
1416 #undef quantize_info
1426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1430 + W a n d S i m p l e O p e r a t o r I m a g e s %
1434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436 % WandSimpleOperatorImages() applys one simple image operation given to all
1437 % the images in the current wand, with the settings that are saved in the
1440 % It is assumed that any per-image settings are up-to-date with respect to
1441 % extra settings that have been saved in the wand.
1443 % The format of the WandSimpleOperatorImage method is:
1445 % void WandSimpleOperatorImages(MagickWand *wand,
1446 % const MagickBooleanType plus_alt_op, const char *option,
1447 % const char *arg1, const char *arg2)
1449 % A description of each parameter follows:
1451 % o wand: structure holding settings to be applied
1453 % o plus_alt_op: request the 'plus' or alturnative form of the operation
1455 % o option: The option string for the operation
1457 % o arg1, arg2: optional argument strings to the operation
1459 % Any problems will be added to the 'exception' entry of the given wand.
1463 % WandSimpleOperatorImages(wand, MagickFalse,"crop","100x100+20+30",NULL);
1464 % WandSimpleOperatorImages(wand, MagickTrue, "repage",NULL,NULL);
1465 % WandSimpleOperatorImages(wand, MagickTrue, "distort","SRT","45");
1466 % if ( wand->exception->severity != UndefinedException ) {
1467 % CatchException(exception);
1471 % Or for handling command line arguments EG: +/-option ["arg"]
1476 % count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
1477 % flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
1478 % if ( (flags & SimpleOperatorOptionFlag) != 0 )
1479 % WandSimpleOperatorImages(wand,
1480 % ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
1481 % count>=1 ? argv[i+1] : (char *)NULL,
1482 % count>=2 ? argv[i+2] : (char *)NULL );
1488 Internal subrountine to apply one simple image operation to the current
1489 image pointed to by the wand.
1491 The image in the list may be modified in three different ways...
1492 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1493 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1494 * one image replace by a list of images (-separate and -crop only!)
1496 In each case the result replaces the original image in the list, as well as
1497 the pointer to the modified image (last image added if replaced by a list
1498 of images) is returned.
1500 As the image pointed to may be replaced, the first image in the list may
1501 also change. GetFirstImageInList() should be used by caller if they wish
1502 return the Image pointer to the first image in list.
1504 static void WandSimpleOperatorImage(MagickWand *wand,
1505 const MagickBooleanType plus_alt_op, const char *option,
1506 const char *arg1, const char *arg2)
1520 #define image_info (wand->image_info)
1521 #define draw_info (wand->draw_info)
1522 #define quantize_info (wand->quantize_info)
1523 #define image (wand->images)
1524 #define exception (wand->exception)
1525 #define normal_op (plus_alt_op?MagickFalse:MagickTrue)
1527 assert(image_info != (const ImageInfo *) NULL);
1528 assert(image_info->signature == MagickSignature);
1529 assert(draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
1530 assert(image != (Image *) NULL); /* there is an image */
1531 assert(image->signature == MagickSignature); /* and is a valid image */
1533 if (wand->debug != MagickFalse)
1534 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1536 SetGeometryInfo(&geometry_info);
1538 new_image = (Image *)NULL; /* the replacement image, if not null at end */
1540 /* FUTURE: We may need somthing a little more optimized than this!
1541 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1543 (void) SyncImageSettings(image_info,image,exception);
1549 if (LocaleCompare("adaptive-blur",option) == 0)
1551 flags=ParseGeometry(arg1,&geometry_info);
1552 if ((flags & SigmaValue) == 0)
1553 geometry_info.sigma=1.0;
1554 if ((flags & XiValue) == 0)
1555 geometry_info.xi=0.0;
1556 new_image=AdaptiveBlurImage(image,geometry_info.rho,
1557 geometry_info.sigma,geometry_info.xi,exception);
1560 if (LocaleCompare("adaptive-resize",option) == 0)
1562 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
1563 new_image=AdaptiveResizeImage(image,geometry.width,geometry.height,
1567 if (LocaleCompare("adaptive-sharpen",option) == 0)
1569 flags=ParseGeometry(arg1,&geometry_info);
1570 if ((flags & SigmaValue) == 0)
1571 geometry_info.sigma=1.0;
1572 if ((flags & XiValue) == 0)
1573 geometry_info.xi=0.0;
1574 new_image=AdaptiveSharpenImage(image,geometry_info.rho,
1575 geometry_info.sigma,geometry_info.xi,exception);
1578 if (LocaleCompare("alpha",option) == 0)
1583 alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
1585 (void) SetImageAlphaChannel(image,alpha_type,exception);
1588 if (LocaleCompare("annotate",option) == 0)
1592 geometry[MaxTextExtent];
1594 SetGeometryInfo(&geometry_info);
1595 flags=ParseGeometry(arg1,&geometry_info);
1596 if ((flags & SigmaValue) == 0)
1597 geometry_info.sigma=geometry_info.rho;
1598 text=InterpretImageProperties(image_info,image,arg2,
1600 if (text == (char *) NULL)
1602 (void) CloneString(&draw_info->text,text);
1603 text=DestroyString(text);
1604 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1605 geometry_info.xi,geometry_info.psi);
1606 (void) CloneString(&draw_info->geometry,geometry);
1607 draw_info->affine.sx=cos(DegreesToRadians(
1608 fmod(geometry_info.rho,360.0)));
1609 draw_info->affine.rx=sin(DegreesToRadians(
1610 fmod(geometry_info.rho,360.0)));
1611 draw_info->affine.ry=(-sin(DegreesToRadians(
1612 fmod(geometry_info.sigma,360.0))));
1613 draw_info->affine.sy=cos(DegreesToRadians(
1614 fmod(geometry_info.sigma,360.0)));
1615 (void) AnnotateImage(image,draw_info,exception);
1616 GetAffineMatrix(&draw_info->affine);
1619 if (LocaleCompare("auto-gamma",option) == 0)
1621 (void) AutoGammaImage(image,exception);
1624 if (LocaleCompare("auto-level",option) == 0)
1626 (void) AutoLevelImage(image,exception);
1629 if (LocaleCompare("auto-orient",option) == 0)
1631 switch (image->orientation)
1633 case TopRightOrientation:
1635 new_image=FlopImage(image,exception);
1638 case BottomRightOrientation:
1640 new_image=RotateImage(image,180.0,exception);
1643 case BottomLeftOrientation:
1645 new_image=FlipImage(image,exception);
1648 case LeftTopOrientation:
1650 new_image=TransposeImage(image,exception);
1653 case RightTopOrientation:
1655 new_image=RotateImage(image,90.0,exception);
1658 case RightBottomOrientation:
1660 new_image=TransverseImage(image,exception);
1663 case LeftBottomOrientation:
1665 new_image=RotateImage(image,270.0,exception);
1671 if (new_image != (Image *) NULL)
1672 new_image->orientation=TopLeftOrientation;
1679 if (LocaleCompare("black-threshold",option) == 0)
1681 (void) BlackThresholdImage(image,arg1,exception);
1684 if (LocaleCompare("blue-shift",option) == 0)
1686 geometry_info.rho=1.5;
1687 if (plus_alt_op == MagickFalse)
1688 flags=ParseGeometry(arg1,&geometry_info);
1689 new_image=BlueShiftImage(image,geometry_info.rho,exception);
1692 if (LocaleCompare("blur",option) == 0)
1694 /* FUTURE: use of "bias" in a blur is non-sensible */
1695 flags=ParseGeometry(arg1,&geometry_info);
1696 if ((flags & SigmaValue) == 0)
1697 geometry_info.sigma=1.0;
1698 if ((flags & XiValue) == 0)
1699 geometry_info.xi=0.0;
1700 new_image=BlurImage(image,geometry_info.rho,
1701 geometry_info.sigma,geometry_info.xi,exception);
1704 if (LocaleCompare("border",option) == 0)
1712 value=GetImageOption(image_info,"compose");
1713 if (value != (const char *) NULL)
1714 compose=(CompositeOperator) ParseCommandOption(
1715 MagickComposeOptions,MagickFalse,value);
1717 compose=OverCompositeOp; /* use Over not image->compose */
1719 flags=ParsePageGeometry(image,arg1,&geometry,exception);
1720 if ((flags & SigmaValue) == 0)
1721 geometry.height=geometry.width;
1722 new_image=BorderImage(image,&geometry,compose,exception);
1725 if (LocaleCompare("brightness-contrast",option) == 0)
1737 flags=ParseGeometry(arg1,&geometry_info);
1738 brightness=geometry_info.rho;
1740 if ((flags & SigmaValue) != 0)
1741 contrast=geometry_info.sigma;
1742 (void) BrightnessContrastImage(image,brightness,contrast,
1750 if (LocaleCompare("cdl",option) == 0)
1753 *color_correction_collection;
1756 Color correct with a color decision list.
1758 color_correction_collection=FileToString(arg1,~0,exception);
1759 if (color_correction_collection == (char *) NULL)
1761 (void) ColorDecisionListImage(image,color_correction_collection,
1765 if (LocaleCompare("channel",option) == 0)
1767 /* The "channel" setting has already been set
1768 FUTURE: This probably should be part of WandSettingOptionInfo()
1769 or SyncImageSettings().
1771 SetPixelChannelMapMask(image,image_info->channel);
1774 if (LocaleCompare("charcoal",option) == 0)
1776 flags=ParseGeometry(arg1,&geometry_info);
1777 if ((flags & SigmaValue) == 0)
1778 geometry_info.sigma=1.0;
1779 if ((flags & XiValue) == 0)
1780 geometry_info.xi=1.0;
1781 new_image=CharcoalImage(image,geometry_info.rho,
1782 geometry_info.sigma,geometry_info.xi,exception);
1785 if (LocaleCompare("chop",option) == 0)
1787 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
1788 new_image=ChopImage(image,&geometry,exception);
1791 if (LocaleCompare("clamp",option) == 0)
1793 (void) ClampImage(image,exception);
1796 if (LocaleCompare("clip",option) == 0)
1798 if (plus_alt_op == MagickFalse)
1799 (void) ClipImage(image,exception);
1800 else /* "+clip" remove the write mask */
1801 (void) SetImageMask(image,(Image *) NULL,exception);
1804 if (LocaleCompare("clip-mask",option) == 0)
1821 if (plus_alt_op != MagickFalse)
1822 { /* "+clip-mask" Remove the write mask */
1823 (void) SetImageMask(image,(Image *) NULL,exception);
1826 mask_image=GetImageCache(image_info,arg1,exception);
1827 if (mask_image == (Image *) NULL)
1829 if (SetImageStorageClass(mask_image,DirectClass,exception)
1832 /* Create a write mask from clip-mask image */
1833 /* FUTURE: use Alpha operations instead and create a Grey Image */
1834 mask_view=AcquireCacheView(mask_image);
1835 for (y=0; y < (ssize_t) mask_image->rows; y++)
1837 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1839 if (q == (Quantum *) NULL)
1841 for (x=0; x < (ssize_t) mask_image->columns; x++)
1843 if (mask_image->matte == MagickFalse)
1844 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1845 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1846 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1847 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1848 q+=GetPixelChannels(mask_image);
1850 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1853 /* clean up and set the write mask */
1854 mask_view=DestroyCacheView(mask_view);
1855 mask_image->matte=MagickTrue;
1856 (void) SetImageMask(image,mask_image,exception);
1857 mask_image=DestroyImage(mask_image);
1860 if (LocaleCompare("clip-path",option) == 0)
1862 (void) ClipImagePath(image,arg1,
1863 (MagickBooleanType)(!(int)plus_alt_op),exception);
1866 if (LocaleCompare("colorize",option) == 0)
1868 new_image=ColorizeImage(image,arg1,&draw_info->fill,exception);
1871 if (LocaleCompare("color-matrix",option) == 0)
1876 kernel=AcquireKernelInfo(arg1);
1877 if (kernel == (KernelInfo *) NULL)
1879 new_image=ColorMatrixImage(image,kernel,exception);
1880 kernel=DestroyKernelInfo(kernel);
1883 if (LocaleCompare("colors",option) == 0)
1885 /* Reduce the number of colors in the image.
1886 FUTURE: also provide 'plus version with image 'color counts'
1888 quantize_info->number_colors=StringToUnsignedLong(arg1);
1889 if (quantize_info->number_colors == 0)
1891 if ((image->storage_class == DirectClass) ||
1892 image->colors > quantize_info->number_colors)
1893 (void) QuantizeImage(quantize_info,image,exception);
1895 (void) CompressImageColormap(image,exception);
1898 if (LocaleCompare("colorspace",option) == 0)
1900 /* WARNING: this is both a image_info setting (already done)
1901 and a operator to change image colorspace.
1903 FUTURE: default colorspace should be sRGB!
1904 Unless some type of 'linear colorspace' mode is set.
1906 Note that +colorspace sets "undefined" or no effect on
1907 new images, but forces images already in memory back to RGB!
1908 That seems to be a little strange!
1910 (void) TransformImageColorspace(image,
1911 plus_alt_op ? RGBColorspace : image_info->colorspace,
1915 if (LocaleCompare("contrast",option) == 0)
1917 (void) ContrastImage(image,
1918 (MagickBooleanType)(!(int)plus_alt_op),exception);
1921 if (LocaleCompare("contrast-stretch",option) == 0)
1930 flags=ParseGeometry(arg1,&geometry_info);
1931 black_point=geometry_info.rho;
1932 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
1934 if ((flags & PercentValue) != 0)
1936 black_point*=(double) image->columns*image->rows/100.0;
1937 white_point*=(double) image->columns*image->rows/100.0;
1939 white_point=(MagickRealType) image->columns*image->rows-
1941 (void) ContrastStretchImage(image,black_point,white_point,
1945 if (LocaleCompare("convolve",option) == 0)
1950 kernel_info=AcquireKernelInfo(arg1);
1951 if (kernel_info == (KernelInfo *) NULL)
1953 kernel_info->bias=image->bias;
1954 new_image=ConvolveImage(image,kernel_info,exception);
1955 kernel_info=DestroyKernelInfo(kernel_info);
1958 if (LocaleCompare("crop",option) == 0)
1960 /* WARNING: This can generate multiple images! */
1961 new_image=CropImageToTiles(image,arg1,exception);
1964 if (LocaleCompare("cycle",option) == 0)
1966 (void) CycleColormapImage(image,(ssize_t) StringToLong(arg1),
1974 if (LocaleCompare("decipher",option) == 0)
1979 passkey=FileToStringInfo(arg1,~0,exception);
1980 if (passkey != (StringInfo *) NULL)
1982 (void) PasskeyDecipherImage(image,passkey,exception);
1983 passkey=DestroyStringInfo(passkey);
1987 if (LocaleCompare("depth",option) == 0)
1989 /* The image_info->depth setting has already been set
1990 We just need to apply it to all images in current sequence
1992 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
1993 That is it really is an operation, not a setting! Arrgghhh
1995 FUTURE: this should not be an operator!!!
1997 (void) SetImageDepth(image,image_info->depth,exception);
2000 if (LocaleCompare("deskew",option) == 0)
2005 if (plus_alt_op != MagickFalse)
2006 threshold=40.0*QuantumRange/100.0;
2008 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
2009 new_image=DeskewImage(image,threshold,exception);
2012 if (LocaleCompare("despeckle",option) == 0)
2014 new_image=DespeckleImage(image,exception);
2017 if (LocaleCompare("distort",option) == 0)
2021 token[MaxTextExtent];
2038 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
2040 if (method == ResizeDistortion)
2044 /* Special Case - Argument is actually a resize geometry!
2045 ** Convert that to an appropriate distortion argument array.
2046 ** FUTURE: make a separate special resize operator
2048 (void) ParseRegionGeometry(image,arg2,&geometry,
2050 resize_args[0]=(double) geometry.width;
2051 resize_args[1]=(double) geometry.height;
2052 new_image=DistortImage(image,method,(size_t)2,
2053 resize_args,MagickTrue,exception);
2056 /* handle percent arguments */
2057 args=InterpretImageProperties(image_info,image,arg2,
2059 if (args == (char *) NULL)
2061 /* convert arguments into an array of doubles
2062 FUTURE: make this a separate function.
2063 Also make use of new 'sentinal' feature to avoid need for
2067 for (x=0; *p != '\0'; x++)
2069 GetMagickToken(p,&p,token);
2071 GetMagickToken(p,&p,token);
2073 number_arguments=(size_t) x;
2074 arguments=(double *) AcquireQuantumMemory(number_arguments,
2075 sizeof(*arguments));
2076 if (arguments == (double *) NULL)
2077 ThrowWandFatalException(ResourceLimitFatalError,
2078 "MemoryAllocationFailed",image->filename);
2079 (void) ResetMagickMemory(arguments,0,number_arguments*
2080 sizeof(*arguments));
2082 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2084 GetMagickToken(p,&p,token);
2086 GetMagickToken(p,&p,token);
2087 arguments[x]=StringToDouble(token,(char **) NULL);
2089 args=DestroyString(args);
2090 new_image=DistortImage(image,method,number_arguments,arguments,
2091 plus_alt_op,exception);
2092 arguments=(double *) RelinquishMagickMemory(arguments);
2095 if (LocaleCompare("draw",option) == 0)
2097 (void) CloneString(&draw_info->primitive,arg1);
2098 (void) DrawImage(image,draw_info,exception);
2099 (void) CloneString(&draw_info->primitive,(char *)NULL);
2106 if (LocaleCompare("edge",option) == 0)
2108 flags=ParseGeometry(arg1,&geometry_info);
2109 if ((flags & SigmaValue) == 0)
2110 geometry_info.sigma=1.0;
2111 new_image=EdgeImage(image,geometry_info.rho,
2112 geometry_info.sigma,exception);
2115 if (LocaleCompare("emboss",option) == 0)
2117 flags=ParseGeometry(arg1,&geometry_info);
2118 if ((flags & SigmaValue) == 0)
2119 geometry_info.sigma=1.0;
2120 new_image=EmbossImage(image,geometry_info.rho,
2121 geometry_info.sigma,exception);
2124 if (LocaleCompare("encipher",option) == 0)
2129 passkey=FileToStringInfo(arg1,~0,exception);
2130 if (passkey != (StringInfo *) NULL)
2132 (void) PasskeyEncipherImage(image,passkey,exception);
2133 passkey=DestroyStringInfo(passkey);
2137 if (LocaleCompare("enhance",option) == 0)
2139 new_image=EnhanceImage(image,exception);
2142 if (LocaleCompare("equalize",option) == 0)
2144 (void) EqualizeImage(image,exception);
2147 if (LocaleCompare("evaluate",option) == 0)
2152 MagickEvaluateOperator
2155 op=(MagickEvaluateOperator) ParseCommandOption(
2156 MagickEvaluateOptions,MagickFalse,arg1);
2157 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
2158 (void) EvaluateImage(image,op,constant,exception);
2161 if (LocaleCompare("extent",option) == 0)
2163 flags=ParseGravityGeometry(image,arg1,&geometry,exception);
2164 if (geometry.width == 0)
2165 geometry.width=image->columns;
2166 if (geometry.height == 0)
2167 geometry.height=image->rows;
2168 new_image=ExtentImage(image,&geometry,exception);
2175 if (LocaleCompare("features",option) == 0)
2177 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
2178 if (plus_alt_op != MagickFalse)
2180 (void) DeleteImageArtifact(image,"identify:features");
2183 (void) SetImageArtifact(image,"identify:features","true");
2184 (void) SetImageArtifact(image,"verbose","true");
2187 if (LocaleCompare("flip",option) == 0)
2189 new_image=FlipImage(image,exception);
2192 if (LocaleCompare("flop",option) == 0)
2194 new_image=FlopImage(image,exception);
2197 if (LocaleCompare("floodfill",option) == 0)
2202 (void) ParsePageGeometry(image,arg1,&geometry,exception);
2203 (void) QueryColorCompliance(arg2,AllCompliance,&target,exception);
2204 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
2205 geometry.y,plus_alt_op,exception);
2208 if (LocaleCompare("frame",option) == 0)
2219 value=GetImageOption(image_info,"compose");
2220 if (value != (const char *) NULL)
2221 compose=(CompositeOperator) ParseCommandOption(
2222 MagickComposeOptions,MagickFalse,value);
2224 compose=OverCompositeOp; /* use Over not image->compose */
2226 flags=ParsePageGeometry(image,arg1,&geometry,exception);
2227 frame_info.width=geometry.width;
2228 frame_info.height=geometry.height;
2229 if ((flags & HeightValue) == 0)
2230 frame_info.height=geometry.width;
2231 frame_info.outer_bevel=geometry.x;
2232 frame_info.inner_bevel=geometry.y;
2233 frame_info.x=(ssize_t) frame_info.width;
2234 frame_info.y=(ssize_t) frame_info.height;
2235 frame_info.width=image->columns+2*frame_info.width;
2236 frame_info.height=image->rows+2*frame_info.height;
2237 new_image=FrameImage(image,&frame_info,compose,exception);
2240 if (LocaleCompare("function",option) == 0)
2244 token[MaxTextExtent];
2262 Function Modify Image Values
2263 FUTURE: code should be almost a duplicate of that is "distort"
2265 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
2267 arguments=InterpretImageProperties(image_info,image,arg2,
2269 if (arguments == (char *) NULL)
2271 p=(char *) arguments;
2272 for (x=0; *p != '\0'; x++)
2274 GetMagickToken(p,&p,token);
2276 GetMagickToken(p,&p,token);
2278 number_parameters=(size_t) x;
2279 parameters=(double *) AcquireQuantumMemory(number_parameters,
2280 sizeof(*parameters));
2281 if (parameters == (double *) NULL)
2282 ThrowWandFatalException(ResourceLimitFatalError,
2283 "MemoryAllocationFailed",image->filename);
2284 (void) ResetMagickMemory(parameters,0,number_parameters*
2285 sizeof(*parameters));
2286 p=(char *) arguments;
2287 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2289 GetMagickToken(p,&p,token);
2291 GetMagickToken(p,&p,token);
2292 parameters[x]=StringToDouble(token,(char **) NULL);
2294 arguments=DestroyString(arguments);
2295 (void) FunctionImage(image,function,number_parameters,parameters,
2297 parameters=(double *) RelinquishMagickMemory(parameters);
2304 if (LocaleCompare("gamma",option) == 0)
2306 if (plus_alt_op != MagickFalse)
2307 image->gamma=StringToDouble(arg1,(char **) NULL);
2309 (void) GammaImage(image,StringToDouble(arg1,(char **) NULL),
2313 if ((LocaleCompare("gaussian-blur",option) == 0) ||
2314 (LocaleCompare("gaussian",option) == 0))
2316 flags=ParseGeometry(arg1,&geometry_info);
2317 if ((flags & SigmaValue) == 0)
2318 geometry_info.sigma=1.0;
2319 new_image=GaussianBlurImage(image,geometry_info.rho,
2320 geometry_info.sigma,exception);
2323 if (LocaleCompare("geometry",option) == 0)
2326 Record Image offset for composition. (A Setting)
2327 Resize last image. (ListOperator)
2328 FUTURE: Why if no 'offset' does this resize ALL images?
2329 Also why is the setting recorded in the IMAGE non-sense!
2331 if (plus_alt_op != MagickFalse)
2332 { /* remove the previous composition geometry offset! */
2333 if (image->geometry != (char *) NULL)
2334 image->geometry=DestroyString(image->geometry);
2337 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
2338 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2339 (void) CloneString(&image->geometry,arg1);
2341 new_image=ResizeImage(image,geometry.width,geometry.height,
2342 image->filter,image->blur,exception);
2349 if (LocaleCompare("highlight-color",option) == 0)
2351 (void) SetImageArtifact(image,option,arg1);
2358 if (LocaleCompare("identify",option) == 0)
2364 format=GetImageOption(image_info,"format");
2365 if (format == (char *) NULL)
2367 (void) IdentifyImage(image,stdout,image_info->verbose,
2371 text=InterpretImageProperties(image_info,image,format,exception);
2372 if (text == (char *) NULL)
2374 (void) fputs(text,stdout);
2375 (void) fputc('\n',stdout);
2376 text=DestroyString((char *)text);
2379 if (LocaleCompare("implode",option) == 0)
2381 (void) ParseGeometry(arg1,&geometry_info);
2382 new_image=ImplodeImage(image,geometry_info.rho,
2383 image->interpolate,exception);
2386 if (LocaleCompare("interpolative-resize",option) == 0)
2388 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2389 new_image=InterpolativeResizeImage(image,geometry.width,
2390 geometry.height,image->interpolate,exception);
2397 if (LocaleCompare("lat",option) == 0)
2399 flags=ParseGeometry(arg1,&geometry_info);
2400 if ((flags & PercentValue) != 0)
2401 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2402 new_image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
2403 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2407 if (LocaleCompare("level",option) == 0)
2417 flags=ParseGeometry(arg1,&geometry_info);
2418 black_point=geometry_info.rho;
2419 white_point=(MagickRealType) QuantumRange;
2420 if ((flags & SigmaValue) != 0)
2421 white_point=geometry_info.sigma;
2423 if ((flags & XiValue) != 0)
2424 gamma=geometry_info.xi;
2425 if ((flags & PercentValue) != 0)
2427 black_point*=(MagickRealType) (QuantumRange/100.0);
2428 white_point*=(MagickRealType) (QuantumRange/100.0);
2430 if ((flags & SigmaValue) == 0)
2431 white_point=(MagickRealType) QuantumRange-black_point;
2432 if (plus_alt_op || ((flags & AspectValue) != 0))
2433 (void) LevelizeImage(image,black_point,white_point,gamma,
2436 (void) LevelImage(image,black_point,white_point,gamma,
2440 if (LocaleCompare("level-colors",option) == 0)
2443 token[MaxTextExtent];
2452 p=(const char *) arg1;
2453 GetMagickToken(p,&p,token); /* get black point color */
2454 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2455 (void) QueryColorCompliance(token,AllCompliance,
2456 &black_point,exception);
2458 (void) QueryColorCompliance("#000000",AllCompliance,
2459 &black_point,exception);
2460 if (isalpha((int) token[0]) || (token[0] == '#'))
2461 GetMagickToken(p,&p,token);
2463 white_point=black_point; /* set everything to that color */
2466 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2467 GetMagickToken(p,&p,token); /* Get white point color. */
2468 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2469 (void) QueryColorCompliance(token,AllCompliance,
2470 &white_point,exception);
2472 (void) QueryColorCompliance("#ffffff",AllCompliance,
2473 &white_point,exception);
2475 (void) LevelImageColors(image,&black_point,&white_point,
2476 plus_alt_op,exception);
2479 if (LocaleCompare("linear-stretch",option) == 0)
2488 flags=ParseGeometry(arg1,&geometry_info);
2489 black_point=geometry_info.rho;
2490 white_point=(MagickRealType) image->columns*image->rows;
2491 if ((flags & SigmaValue) != 0)
2492 white_point=geometry_info.sigma;
2493 if ((flags & PercentValue) != 0)
2495 black_point*=(double) image->columns*image->rows/100.0;
2496 white_point*=(double) image->columns*image->rows/100.0;
2498 if ((flags & SigmaValue) == 0)
2499 white_point=(MagickRealType) image->columns*image->rows-
2501 (void) LinearStretchImage(image,black_point,white_point,exception);
2504 if (LocaleCompare("liquid-rescale",option) == 0)
2506 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
2507 if ((flags & XValue) == 0)
2509 if ((flags & YValue) == 0)
2511 new_image=LiquidRescaleImage(image,geometry.width,
2512 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2515 if (LocaleCompare("lowlight-color",option) == 0)
2517 (void) SetImageArtifact(image,option,arg1);
2524 if (LocaleCompare("map",option) == 0)
2529 /* DEPRECIATED use -remap */
2530 remap_image=GetImageCache(image_info,arg1,exception);
2531 if (remap_image == (Image *) NULL)
2533 (void) RemapImage(quantize_info,image,remap_image,exception);
2534 remap_image=DestroyImage(remap_image);
2537 if (LocaleCompare("mask",option) == 0)
2542 if (plus_alt_op != MagickFalse)
2543 { /* Remove a mask. */
2544 (void) SetImageMask(image,(Image *) NULL,exception);
2547 /* Set the image mask. */
2548 mask=GetImageCache(image_info,arg1,exception);
2549 if (mask == (Image *) NULL)
2551 (void) SetImageMask(image,mask,exception);
2552 mask=DestroyImage(mask);
2555 if (LocaleCompare("matte",option) == 0)
2558 (void) SetImageAlphaChannel(image,plus_alt_op ?
2559 DeactivateAlphaChannel:SetAlphaChannel ,exception);
2562 if (LocaleCompare("mode",option) == 0)
2564 flags=ParseGeometry(arg1,&geometry_info);
2565 if ((flags & SigmaValue) == 0)
2566 geometry_info.sigma=geometry_info.rho;
2567 new_image=StatisticImage(image,ModeStatistic,(size_t)
2568 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2571 if (LocaleCompare("modulate",option) == 0)
2573 (void) ModulateImage(image,arg1,exception);
2576 if (LocaleCompare("monitor",option) == 0)
2578 (void) SetImageProgressMonitor(image, plus_alt_op?
2579 (MagickProgressMonitor) NULL:MonitorProgress,(void *) NULL);
2582 if (LocaleCompare("monochrome",option) == 0)
2584 (void) SetImageType(image,BilevelType,exception);
2587 if (LocaleCompare("morphology",option) == 0)
2590 token[MaxTextExtent];
2605 GetMagickToken(p,&p,token);
2606 method=(MorphologyMethod) ParseCommandOption(
2607 MagickMorphologyOptions,MagickFalse,token);
2609 GetMagickToken(p,&p,token);
2610 if ((*p == ':') || (*p == ','))
2611 GetMagickToken(p,&p,token);
2613 iterations=(ssize_t) StringToLong(p);
2614 kernel=AcquireKernelInfo(arg2);
2615 if (kernel == (KernelInfo *) NULL)
2617 (void) ThrowMagickException(exception,GetMagickModule(),
2618 OptionError,"UnabletoParseKernel","morphology");
2621 new_image=MorphologyImage(image,method,iterations,kernel,exception);
2622 kernel=DestroyKernelInfo(kernel);
2625 if (LocaleCompare("motion-blur",option) == 0)
2627 flags=ParseGeometry(arg1,&geometry_info);
2628 if ((flags & SigmaValue) == 0)
2629 geometry_info.sigma=1.0;
2630 new_image=MotionBlurImage(image,geometry_info.rho,
2631 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2639 if (LocaleCompare("negate",option) == 0)
2641 (void) NegateImage(image, plus_alt_op, exception);
2644 if (LocaleCompare("noise",option) == 0)
2646 if (plus_alt_op == MagickFalse)
2648 flags=ParseGeometry(arg1,&geometry_info);
2649 if ((flags & SigmaValue) == 0)
2650 geometry_info.sigma=geometry_info.rho;
2651 new_image=StatisticImage(image,NonpeakStatistic,(size_t)
2652 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2665 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
2668 value=GetImageOption(image_info,"attenuate");
2669 if (value != (const char *) NULL)
2670 attenuate=StringToDouble(value,(char **) NULL);
2674 new_image=AddNoiseImage(image,noise,attenuate,exception);
2678 if (LocaleCompare("normalize",option) == 0)
2680 (void) NormalizeImage(image,exception);
2687 if (LocaleCompare("opaque",option) == 0)
2692 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
2693 (void) OpaquePaintImage(image,&target,&draw_info->fill,plus_alt_op,
2697 if (LocaleCompare("ordered-dither",option) == 0)
2699 (void) OrderedPosterizeImage(image,arg1,exception);
2706 if (LocaleCompare("paint",option) == 0)
2708 (void) ParseGeometry(arg1,&geometry_info);
2709 new_image=OilPaintImage(image,geometry_info.rho,geometry_info.sigma,
2713 if (LocaleCompare("polaroid",option) == 0)
2721 if (plus_alt_op != MagickFalse)
2726 random_info=AcquireRandomInfo();
2727 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2728 random_info=DestroyRandomInfo(random_info);
2732 SetGeometryInfo(&geometry_info);
2733 flags=ParseGeometry(arg1,&geometry_info);
2734 angle=geometry_info.rho;
2736 caption=GetImageProperty(image,"caption",exception);
2737 new_image=PolaroidImage(image,draw_info,caption,angle,
2738 image->interpolate,exception);
2741 if (LocaleCompare("posterize",option) == 0)
2743 (void) ParseGeometry(arg1,&geometry_info);
2744 (void) PosterizeImage(image,(size_t) geometry_info.rho,
2745 quantize_info->dither,exception);
2748 if (LocaleCompare("preview",option) == 0)
2753 /* FUTURE: should be a 'Genesis' option?
2754 Option however is also in WandSettingOptionInfo()
2756 preview_type=UndefinedPreview;
2757 if (plus_alt_op == MagickFalse)
2758 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2760 new_image=PreviewImage(image,preview_type,exception);
2763 if (LocaleCompare("profile",option) == 0)
2777 if (plus_alt_op != MagickFalse)
2778 { /* Remove a profile from the image. */
2779 (void) ProfileImage(image,arg1,(const unsigned char *)
2783 /* Associate a profile with the image. */
2784 profile_info=CloneImageInfo(image_info);
2785 profile=GetImageProfile(image,"iptc");
2786 if (profile != (StringInfo *) NULL)
2787 profile_info->profile=(void *) CloneStringInfo(profile);
2788 profile_image=GetImageCache(profile_info,arg1,exception);
2789 profile_info=DestroyImageInfo(profile_info);
2790 if (profile_image == (Image *) NULL)
2795 profile_info=CloneImageInfo(image_info);
2796 (void) CopyMagickString(profile_info->filename,arg1,
2798 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
2799 if (profile != (StringInfo *) NULL)
2801 (void) ProfileImage(image,profile_info->magick,
2802 GetStringInfoDatum(profile),(size_t)
2803 GetStringInfoLength(profile),exception);
2804 profile=DestroyStringInfo(profile);
2806 profile_info=DestroyImageInfo(profile_info);
2809 ResetImageProfileIterator(profile_image);
2810 name=GetNextImageProfile(profile_image);
2811 while (name != (const char *) NULL)
2813 profile=GetImageProfile(profile_image,name);
2814 if (profile != (StringInfo *) NULL)
2815 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
2816 (size_t) GetStringInfoLength(profile),exception);
2817 name=GetNextImageProfile(profile_image);
2819 profile_image=DestroyImage(profile_image);
2826 if (LocaleCompare("radial-blur",option) == 0)
2828 flags=ParseGeometry(arg1,&geometry_info);
2829 new_image=RadialBlurImage(image,geometry_info.rho,
2830 geometry_info.sigma,exception);
2833 if (LocaleCompare("raise",option) == 0)
2835 flags=ParsePageGeometry(image,arg1,&geometry,exception);
2836 if ((flags & SigmaValue) == 0)
2837 geometry.height=geometry.width;
2838 (void) RaiseImage(image,&geometry,normal_op,exception);
2841 if (LocaleCompare("random-threshold",option) == 0)
2843 (void) RandomThresholdImage(image,arg1,exception);
2846 if (LocaleCompare("remap",option) == 0)
2851 remap_image=GetImageCache(image_info,arg1,exception);
2852 if (remap_image == (Image *) NULL)
2854 (void) RemapImage(quantize_info,image,remap_image,exception);
2855 remap_image=DestroyImage(remap_image);
2858 if (LocaleCompare("repage",option) == 0)
2860 if (plus_alt_op == MagickFalse)
2861 (void) ResetImagePage(image,arg1);
2863 (void) ParseAbsoluteGeometry("0x0+0+0",&image->page);
2866 if (LocaleCompare("resample",option) == 0)
2868 /* FUTURE: remove blur arguemnt - no longer used */
2869 flags=ParseGeometry(arg1,&geometry_info);
2870 if ((flags & SigmaValue) == 0)
2871 geometry_info.sigma=geometry_info.rho;
2872 new_image=ResampleImage(image,geometry_info.rho,
2873 geometry_info.sigma,image->filter,image->blur,exception);
2876 if (LocaleCompare("resize",option) == 0)
2878 /* FUTURE: remove blur argument - no longer used */
2879 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2880 new_image=ResizeImage(image,geometry.width,geometry.height,
2881 image->filter,image->blur,exception);
2884 if (LocaleCompare("roll",option) == 0)
2886 (void) ParsePageGeometry(image,arg1,&geometry,exception);
2887 new_image=RollImage(image,geometry.x,geometry.y,exception);
2890 if (LocaleCompare("rotate",option) == 0)
2892 if (strchr(arg1,'>') != (char *) NULL)
2893 if (image->columns <= image->rows)
2895 if (strchr(arg1,'<') != (char *) NULL)
2896 if (image->columns >= image->rows)
2899 (void) ParseGeometry(arg1,&geometry_info);
2900 new_image=RotateImage(image,geometry_info.rho,exception);
2907 if (LocaleCompare("sample",option) == 0)
2909 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2910 new_image=SampleImage(image,geometry.width,geometry.height,
2914 if (LocaleCompare("scale",option) == 0)
2916 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2917 new_image=ScaleImage(image,geometry.width,geometry.height,
2921 if (LocaleCompare("selective-blur",option) == 0)
2923 flags=ParseGeometry(arg1,&geometry_info);
2924 if ((flags & PercentValue) != 0)
2925 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2926 new_image=SelectiveBlurImage(image,geometry_info.rho,
2927 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
2930 if (LocaleCompare("separate",option) == 0)
2932 /* WARNING: This can generate multiple images! */
2933 new_image=SeparateImages(image,exception);
2936 if (LocaleCompare("sepia-tone",option) == 0)
2941 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
2942 new_image=SepiaToneImage(image,threshold,exception);
2945 if (LocaleCompare("segment",option) == 0)
2947 flags=ParseGeometry(arg1,&geometry_info);
2948 if ((flags & SigmaValue) == 0)
2949 geometry_info.sigma=1.0;
2950 (void) SegmentImage(image,image->colorspace,
2951 image_info->verbose,geometry_info.rho,geometry_info.sigma,
2955 if (LocaleCompare("set",option) == 0)
2960 if (plus_alt_op != MagickFalse)
2962 if (LocaleNCompare(arg1,"registry:",9) == 0)
2963 (void) DeleteImageRegistry(arg1+9);
2965 if (LocaleNCompare(arg1,"option:",7) == 0)
2967 (void) DeleteImageOption(image_info,arg1+7);
2968 (void) DeleteImageArtifact(image,arg1+7);
2971 (void) DeleteImageProperty(image,arg1);
2974 value=InterpretImageProperties(image_info,image,arg2,
2976 if (value == (char *) NULL)
2978 if (LocaleNCompare(arg1,"registry:",9) == 0)
2979 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
2982 if (LocaleNCompare(arg1,"option:",7) == 0)
2984 (void) SetImageOption(image_info,arg1+7,value);
2985 (void) SetImageArtifact(image,arg1+7,value);
2988 (void) SetImageProperty(image,arg1,value,exception);
2989 value=DestroyString(value);
2992 if (LocaleCompare("shade",option) == 0)
2994 flags=ParseGeometry(arg1,&geometry_info);
2995 if ((flags & SigmaValue) == 0)
2996 geometry_info.sigma=1.0;
2997 new_image=ShadeImage(image,normal_op,geometry_info.rho,
2998 geometry_info.sigma,exception);
3001 if (LocaleCompare("shadow",option) == 0)
3003 flags=ParseGeometry(arg1,&geometry_info);
3004 if ((flags & SigmaValue) == 0)
3005 geometry_info.sigma=1.0;
3006 if ((flags & XiValue) == 0)
3007 geometry_info.xi=4.0;
3008 if ((flags & PsiValue) == 0)
3009 geometry_info.psi=4.0;
3010 new_image=ShadowImage(image,geometry_info.rho,
3011 geometry_info.sigma,image->bias,(ssize_t)
3012 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
3016 if (LocaleCompare("sharpen",option) == 0)
3018 flags=ParseGeometry(arg1,&geometry_info);
3019 if ((flags & SigmaValue) == 0)
3020 geometry_info.sigma=1.0;
3021 if ((flags & XiValue) == 0)
3022 geometry_info.xi=0.0;
3023 new_image=SharpenImage(image,geometry_info.rho,
3024 geometry_info.sigma,geometry_info.xi,exception);
3027 if (LocaleCompare("shave",option) == 0)
3029 flags=ParsePageGeometry(image,arg1,&geometry,exception);
3030 new_image=ShaveImage(image,&geometry,exception);
3033 if (LocaleCompare("shear",option) == 0)
3035 flags=ParseGeometry(arg1,&geometry_info);
3036 if ((flags & SigmaValue) == 0)
3037 geometry_info.sigma=geometry_info.rho;
3038 new_image=ShearImage(image,geometry_info.rho,
3039 geometry_info.sigma,exception);
3042 if (LocaleCompare("sigmoidal-contrast",option) == 0)
3044 flags=ParseGeometry(arg1,&geometry_info);
3045 if ((flags & SigmaValue) == 0)
3046 geometry_info.sigma=(double) QuantumRange/2.0;
3047 if ((flags & PercentValue) != 0)
3048 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3050 (void) SigmoidalContrastImage(image,normal_op,geometry_info.rho,
3051 geometry_info.sigma,
3055 if (LocaleCompare("sketch",option) == 0)
3057 flags=ParseGeometry(arg1,&geometry_info);
3058 if ((flags & SigmaValue) == 0)
3059 geometry_info.sigma=1.0;
3060 new_image=SketchImage(image,geometry_info.rho,
3061 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3064 if (LocaleCompare("solarize",option) == 0)
3066 (void) SolarizeImage(image,StringToDoubleInterval(arg1,(double)
3067 QuantumRange+1.0),exception);
3070 if (LocaleCompare("sparse-color",option) == 0)
3078 method=(SparseColorMethod) ParseCommandOption(
3079 MagickSparseColorOptions,MagickFalse,arg1);
3080 arguments=InterpretImageProperties(image_info,image,arg2,exception);
3081 if (arguments == (char *) NULL)
3083 new_image=SparseColorOption(image,method,arguments,exception);
3084 arguments=DestroyString(arguments);
3087 if (LocaleCompare("splice",option) == 0)
3089 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
3090 new_image=SpliceImage(image,&geometry,exception);
3093 if (LocaleCompare("spread",option) == 0)
3095 (void) ParseGeometry(arg1,&geometry_info);
3096 new_image=SpreadImage(image,geometry_info.rho,image->interpolate,
3100 if (LocaleCompare("statistic",option) == 0)
3105 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
3107 (void) ParseGeometry(arg2,&geometry_info);
3108 new_image=StatisticImage(image,type,(size_t) geometry_info.rho,
3109 (size_t) geometry_info.sigma,exception);
3112 if (LocaleCompare("strip",option) == 0)
3114 (void) StripImage(image,exception);
3117 if (LocaleCompare("swirl",option) == 0)
3119 (void) ParseGeometry(arg1,&geometry_info);
3120 new_image=SwirlImage(image,geometry_info.rho,
3121 image->interpolate,exception);
3128 if (LocaleCompare("threshold",option) == 0)
3133 if (plus_alt_op != MagickFalse)
3134 threshold=(double) QuantumRange/2;
3136 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
3137 (void) BilevelImage(image,threshold,exception);
3140 if (LocaleCompare("thumbnail",option) == 0)
3142 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3143 new_image=ThumbnailImage(image,geometry.width,geometry.height,
3147 if (LocaleCompare("tint",option) == 0)
3149 new_image=TintImage(image,arg1,&draw_info->fill,exception);
3152 if (LocaleCompare("transform",option) == 0)
3155 new_image=AffineTransformImage(image,&draw_info->affine,
3159 if (LocaleCompare("transparent",option) == 0)
3164 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
3165 (void) TransparentPaintImage(image,&target,(Quantum)
3166 TransparentAlpha,plus_alt_op,exception);
3169 if (LocaleCompare("transpose",option) == 0)
3171 new_image=TransposeImage(image,exception);
3174 if (LocaleCompare("transverse",option) == 0)
3176 new_image=TransverseImage(image,exception);
3179 if (LocaleCompare("trim",option) == 0)
3181 new_image=TrimImage(image,exception);
3184 if (LocaleCompare("type",option) == 0)
3186 /* Note that "type" setting should have already been defined */
3187 (void) SetImageType(image,image_info->type,exception);
3194 if (LocaleCompare("unique",option) == 0)
3196 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
3197 if (plus_alt_op != MagickFalse)
3199 (void) DeleteImageArtifact(image,"identify:unique-colors");
3202 (void) SetImageArtifact(image,"identify:unique-colors","true");
3203 (void) SetImageArtifact(image,"verbose","true");
3206 if (LocaleCompare("unique-colors",option) == 0)
3208 new_image=UniqueImageColors(image,exception);
3211 if (LocaleCompare("unsharp",option) == 0)
3213 flags=ParseGeometry(arg1,&geometry_info);
3214 if ((flags & SigmaValue) == 0)
3215 geometry_info.sigma=1.0;
3216 if ((flags & XiValue) == 0)
3217 geometry_info.xi=1.0;
3218 if ((flags & PsiValue) == 0)
3219 geometry_info.psi=0.05;
3220 new_image=UnsharpMaskImage(image,geometry_info.rho,
3221 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3228 if (LocaleCompare("verbose",option) == 0)
3230 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3231 three places! ImageArtifact ImageOption image_info->verbose
3232 Some how new images also get this artifact -- how???
3234 (void) SetImageArtifact(image,option,
3235 (plus_alt_op != MagickFalse) ? "false" : "true" );
3238 if (LocaleCompare("vignette",option) == 0)
3240 flags=ParseGeometry(arg1,&geometry_info);
3241 if ((flags & SigmaValue) == 0)
3242 geometry_info.sigma=1.0;
3243 if ((flags & XiValue) == 0)
3244 geometry_info.xi=0.1*image->columns;
3245 if ((flags & PsiValue) == 0)
3246 geometry_info.psi=0.1*image->rows;
3247 new_image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
3248 image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3249 (ssize_t) ceil(geometry_info.psi-0.5),exception);
3256 if (LocaleCompare("wave",option) == 0)
3258 flags=ParseGeometry(arg1,&geometry_info);
3259 if ((flags & SigmaValue) == 0)
3260 geometry_info.sigma=1.0;
3261 new_image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
3262 image->interpolate,exception);
3265 if (LocaleCompare("white-threshold",option) == 0)
3267 (void) WhiteThresholdImage(image,arg1,exception);
3276 Replace current image with any image that was generated
3277 and set image point to last image (so image->next is correct)
3279 if (new_image != (Image *) NULL)
3280 ReplaceImageInListReturnLast(&image,new_image);
3285 #undef quantize_info
3291 WandExport void WandSimpleOperatorImages(MagickWand *wand,
3292 const MagickBooleanType plus_alt_op, const char *option,
3293 const char *arg1, const char *arg2)
3301 assert(wand->image_info != (const ImageInfo *) NULL);
3302 assert(wand->image_info->signature == MagickSignature);
3303 assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
3304 assert(wand->images != (Image *) NULL); /* there is one image */
3307 n=GetImageListLength(wand->images);
3308 wand->images=GetFirstImageInList(wand->images);
3311 WandSimpleOperatorImage(wand, plus_alt_op, option, arg1, arg2);
3312 if ( wand->images->next == (Image *) NULL )
3314 wand->images=wand->images->next;
3317 wand->images=GetFirstImageInList(wand->images);
3322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3326 + W a n d L i s t O p e r a t o r I m a g e s %
3330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3332 % WandListOperatorImages() applies a single operation that is apply to the
3333 % entire image list as a whole. The result is often a complete replacment
3334 % of the image list with a completely new list, or just a single image.
3336 % The format of the MogrifyImage method is:
3338 % void WandListOperatorImages(MagickWand *wand,
3339 % const MagickBooleanType plus_alt_op,const char *option,
3340 % const char *arg1, const char *arg2)
3342 % A description of each parameter follows:
3344 % o wand: structure holding settings to be applied
3346 % o plus_alt_op: request the 'plus' or alturnative form of the operation
3348 % o option: The option string for the operation
3350 % o arg1, arg2: optional argument strings to the operation
3352 % NOTE: only "limit" currently uses two arguments.
3356 % WandListOperatorImages(wand,MagickFalse,"duplicate", "3", NULL);
3357 % WandListOperatorImages(wand,MagickTrue, "append", NULL, NULL);
3358 % if ( wand->exception->severity != UndefinedException ) {
3359 % CatchException(exception);
3363 % Or for handling command line arguments EG: +/-option ["arg"]
3368 % count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
3369 % flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
3370 % if ( (flags & ListOperatorOptionFlag) != 0 )
3371 % WandListOperatorImages(wand,
3372 % ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
3373 % count>=1 ? argv[i+1] : (char *)NULL,
3374 % count>=2 ? argv[i+2] : (char *)NULL );
3378 WandExport void WandListOperatorImages(MagickWand *wand,
3379 const MagickBooleanType plus_alt_op,const char *option,
3380 const char *arg1, const char *arg2)
3385 #define image_info (wand->image_info)
3386 #define draw_info (wand->draw_info)
3387 #define quantize_info (wand->quantize_info)
3388 #define images (wand->images)
3389 #define exception (wand->exception)
3390 #define normal_op (plus_alt_op?MagickFalse:MagickTrue)
3392 assert(image_info != (const ImageInfo *) NULL);
3393 assert(image_info->signature == MagickSignature);
3394 assert(draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
3395 assert(images != (Image *) NULL); /* there is an image */
3396 assert(images->signature == MagickSignature); /* and is a valid image */
3398 if (wand->debug != MagickFalse)
3399 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3401 (void) SyncImagesSettings(image_info,images,exception);
3403 new_images=NewImageList();
3409 if (LocaleCompare("append",option) == 0)
3411 new_images=AppendImages(images,normal_op,exception);
3414 if (LocaleCompare("average",option) == 0)
3416 /* DEPRECIATED - use -evaluate-sequence Mean */
3417 WandListOperatorImages(wand,plus_alt_op,"evaluate-sequence","Mean",
3425 if (LocaleCompare("clut",option) == 0)
3427 /* FUTURE - make this a compose option (and thus layers compose )
3428 or perhaps compose last image over all other images.
3433 new_images=RemoveFirstImageFromList(&images);
3434 clut_image=RemoveLastImageFromList(&images);
3435 /* FUTURE - produce Exception, rather than silent fail */
3436 if (clut_image == (Image *) NULL)
3438 (void) ClutImage(new_images,clut_image,images->interpolate,exception);
3439 clut_image=DestroyImage(clut_image);
3442 if (LocaleCompare("coalesce",option) == 0)
3444 new_images=CoalesceImages(images,exception);
3447 if (LocaleCompare("combine",option) == 0)
3449 new_images=CombineImages(images,exception);
3452 if (LocaleCompare("composite",option) == 0)
3467 value=GetImageOption(image_info,"compose");
3468 if (value != (const char *) NULL)
3469 compose=(CompositeOperator) ParseCommandOption(
3470 MagickComposeOptions,MagickFalse,value);
3472 compose=OverCompositeOp; /* use Over not source_image->compose */
3474 new_images=RemoveFirstImageFromList(&images);
3475 source_image=RemoveFirstImageFromList(&images);
3476 /* FUTURE - produce Exception, rather than silent fail */
3477 if (source_image == (Image *) NULL)
3480 /* FUTURE - this should not be here! - should be part of -geometry */
3481 (void) TransformImage(&source_image,(char *) NULL,
3482 source_image->geometry,exception);
3484 SetGeometry(source_image,&geometry);
3485 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3486 GravityAdjustGeometry(new_images->columns,new_images->rows,
3487 new_images->gravity, &geometry);
3489 mask_image=RemoveFirstImageFromList(&images);
3490 if (mask_image != (Image *) NULL)
3491 { /* handle a third write mask image */
3492 if ((compose == DisplaceCompositeOp) ||
3493 (compose == DistortCompositeOp))
3494 { /* Merge Y displacement into X displace/distort map. */
3495 (void) CompositeImage(source_image,CopyGreenCompositeOp,
3496 mask_image,0,0,exception);
3497 mask_image=DestroyImage(mask_image);
3502 Set a blending mask for the composition.
3504 (void) NegateImage(mask_image,MagickFalse,exception);
3505 (void) SetImageMask(new_images,mask_image,exception);
3506 mask_image=DestroyImage(mask_image);
3509 (void) CompositeImage(new_images,compose,source_image,geometry.x,
3510 geometry.y,exception);
3511 (void) SetImageMask(new_images,(Image *) NULL,exception);
3512 source_image=DestroyImage(source_image);
3519 if (LocaleCompare("deconstruct",option) == 0)
3521 /* DEPRECIATED - use -layers CompareAny */
3522 WandListOperatorImages(wand,plus_alt_op,"layer","CompareAny",NULL);
3525 if (LocaleCompare("delete",option) == 0)
3527 if (plus_alt_op != MagickFalse)
3528 DeleteImages(&images,"-1",exception);
3530 DeleteImages(&images,arg1,exception);
3533 if (LocaleCompare("duplicate",option) == 0)
3535 if (plus_alt_op != MagickFalse)
3536 new_images=DuplicateImages(images,1,"-1",exception);
3545 number_duplicates=(size_t) StringToLong(arg1);
3547 if (p == (const char *) NULL)
3548 new_images=DuplicateImages(images,number_duplicates,
3551 new_images=DuplicateImages(images,number_duplicates,p,
3554 AppendImageToList(&images, new_images);
3555 new_images=(Image *)NULL;
3562 if (LocaleCompare("evaluate-sequence",option) == 0)
3564 MagickEvaluateOperator
3567 method=(MagickEvaluateOperator) ParseCommandOption(
3568 MagickEvaluateOptions,MagickFalse,arg1);
3569 new_images=EvaluateImages(images,method,exception);
3576 if (LocaleCompare("fft",option) == 0)
3578 new_images=ForwardFourierTransformImage(images,normal_op,exception);
3581 if (LocaleCompare("flatten",option) == 0)
3583 /* DEPRECIATED use -layers mosaic instead */
3584 WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
3587 if (LocaleCompare("fx",option) == 0)
3589 new_images=FxImage(images,arg1,exception);
3596 if (LocaleCompare("hald-clut",option) == 0)
3598 /* FUTURE - make this a compose option (and thus layers compose )
3599 or perhaps compose last image over all other images.
3604 new_images=RemoveFirstImageFromList(&images);
3605 hald_image=RemoveLastImageFromList(&images);
3606 if (hald_image == (Image *) NULL)
3608 (void) HaldClutImage(new_images,hald_image,exception);
3609 hald_image=DestroyImage(hald_image);
3616 if (LocaleCompare("ift",option) == 0)
3622 magnitude_image=RemoveFirstImageFromList(&images);
3623 phase_image=RemoveFirstImageFromList(&images);
3624 /* FUTURE - produce Exception, rather than silent fail */
3625 if (phase_image == (Image *) NULL)
3627 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
3628 normal_op,exception);
3629 magnitude_image=DestroyImage(magnitude_image);
3630 phase_image=DestroyImage(phase_image);
3633 if (LocaleCompare("insert",option) == 0)
3643 insert_image=RemoveLastImageFromList(&images);
3644 if (plus_alt_op == MagickFalse)
3645 index=(ssize_t) StringToLong(arg1);
3647 PrependImageToList(&images,insert_image);
3649 if (index == (ssize_t) GetImageListLength(images))
3650 AppendImageToList(&images,insert_image);
3653 index_image=GetImageFromList(images,index-1);
3654 if (index_image == (Image *) NULL)
3656 (void) ThrowMagickException(exception,GetMagickModule(),
3657 OptionError,"NoSuchImage","`%s'",arg1);
3660 InsertImageInList(&index_image,insert_image);
3662 images=GetFirstImageInList(index_image);
3669 if (LocaleCompare("layers",option) == 0)
3674 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
3680 new_images=CoalesceImages(images,exception);
3683 case CompareAnyLayer:
3684 case CompareClearLayer:
3685 case CompareOverlayLayer:
3688 new_images=CompareImagesLayers(images,method,exception);
3694 case TrimBoundsLayer:
3696 new_images=MergeImageLayers(images,method,exception);
3701 new_images=DisposeImages(images,exception);
3704 case OptimizeImageLayer:
3706 new_images=OptimizeImageLayers(images,exception);
3709 case OptimizePlusLayer:
3711 new_images=OptimizePlusImageLayers(images,exception);
3714 case OptimizeTransLayer:
3716 OptimizeImageTransparency(images,exception);
3719 case RemoveDupsLayer:
3721 RemoveDuplicateLayers(&images,exception);
3724 case RemoveZeroLayer:
3726 RemoveZeroDelayLayers(&images,exception);
3730 { /* General Purpose, GIF Animation Optimizer. */
3731 new_images=CoalesceImages(images,exception);
3732 if (new_images == (Image *) NULL)
3734 images=DestroyImageList(images);
3735 images=OptimizeImageLayers(new_images,exception);
3736 if (images == (Image *) NULL)
3738 new_images=DestroyImageList(new_images);
3739 OptimizeImageTransparency(images,exception);
3740 (void) RemapImages(quantize_info,images,(Image *) NULL,
3744 case CompositeLayer:
3758 value=GetImageOption(image_info,"compose");
3759 compose=OverCompositeOp; /* Default to Over */
3760 if (value != (const char *) NULL)
3761 compose=(CompositeOperator) ParseCommandOption(
3762 MagickComposeOptions,MagickFalse,value);
3764 /* Split image sequence at the first 'NULL:' image. */
3766 while (source != (Image *) NULL)
3768 source=GetNextImageInList(source);
3769 if ((source != (Image *) NULL) &&
3770 (LocaleCompare(source->magick,"NULL") == 0))
3773 if (source != (Image *) NULL)
3775 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3776 (GetNextImageInList(source) == (Image *) NULL))
3777 source=(Image *) NULL;
3779 { /* Separate the two lists, junk the null: image. */
3780 source=SplitImageList(source->previous);
3781 DeleteImageFromList(&source);
3784 if (source == (Image *) NULL)
3786 (void) ThrowMagickException(exception,GetMagickModule(),
3787 OptionError,"MissingNullSeparator","layers Composite");
3790 /* Adjust offset with gravity and virtual canvas. */
3791 SetGeometry(images,&geometry);
3792 (void) ParseAbsoluteGeometry(images->geometry,&geometry);
3793 geometry.width=source->page.width != 0 ?
3794 source->page.width : source->columns;
3795 geometry.height=source->page.height != 0 ?
3796 source->page.height : source->rows;
3797 GravityAdjustGeometry(images->page.width != 0 ?
3798 images->page.width : images->columns,
3799 images->page.height != 0 ? images->page.height :
3800 images->rows,images->gravity,&geometry);
3802 /* Compose the two image sequences together */
3803 CompositeLayers(images,compose,source,geometry.x,geometry.y,
3805 source=DestroyImageList(source);
3811 if (LocaleCompare("limit",option) == 0)
3819 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
3821 limit=MagickResourceInfinity;
3822 if (LocaleCompare("unlimited",arg2) != 0)
3823 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
3824 (void) SetMagickResourceLimit(type,limit);
3831 if (LocaleCompare("map",option) == 0)
3833 /* DEPRECIATED use +remap */
3834 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
3837 if (LocaleCompare("morph",option) == 0)
3842 morph_image=MorphImages(images,StringToUnsignedLong(arg1),
3844 if (morph_image == (Image *) NULL)
3846 images=DestroyImageList(images);
3850 if (LocaleCompare("mosaic",option) == 0)
3852 /* DEPRECIATED use -layers mosaic instead */
3853 WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
3860 if (LocaleCompare("print",option) == 0)
3865 string=InterpretImageProperties(image_info,images,arg1,
3867 if (string == (char *) NULL)
3869 (void) FormatLocaleFile(stdout,"%s",string);
3870 string=DestroyString(string);
3872 if (LocaleCompare("process",option) == 0)
3881 arguments=StringToArgv(arg1,&number_arguments);
3882 if (arguments == (char **) NULL)
3884 if (strchr(arguments[1],'=') != (char *) NULL)
3905 Support old style syntax, filter="-option arg".
3907 length=strlen(arg1);
3908 token=(char *) NULL;
3909 if (~length >= (MaxTextExtent-1))
3910 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
3912 if (token == (char *) NULL)
3916 token_info=AcquireTokenInfo();
3917 status=Tokenizer(token_info,0,token,length,arguments,"","=",
3918 "\"",'\0',&breaker,&next,"e);
3919 token_info=DestroyTokenInfo(token_info);
3925 argv=(&(arguments[next]));
3926 (void) InvokeDynamicImageFilter(token,&images,1,&argv,
3929 token=DestroyString(token);
3932 (void) SubstituteString(&arguments[1],"-","");
3933 (void) InvokeDynamicImageFilter(arguments[1],&images,
3934 number_arguments-2,(const char **) arguments+2,exception);
3935 for (j=0; j < number_arguments; j++)
3936 arguments[j]=DestroyString(arguments[j]);
3937 arguments=(char **) RelinquishMagickMemory(arguments);
3944 if (LocaleCompare("remap",option) == 0)
3946 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
3947 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
3950 if (LocaleCompare("reverse",option) == 0)
3952 ReverseImageList(&images);
3959 if (LocaleCompare("smush",option) == 0)
3967 offset=(ssize_t) StringToLong(arg1);
3968 smush_image=SmushImages(images,normal_op,offset,exception);
3969 if (smush_image == (Image *) NULL)
3971 images=DestroyImageList(images);
3975 if (LocaleCompare("swap",option) == 0)
3988 if (plus_alt_op == MagickFalse)
3997 flags=ParseGeometry(arg1,&geometry_info);
3998 index=(ssize_t) geometry_info.rho;
3999 if ((flags & SigmaValue) != 0)
4000 swap_index=(ssize_t) geometry_info.sigma;
4002 p=GetImageFromList(images,index);
4003 q=GetImageFromList(images,swap_index);
4004 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4006 (void) ThrowMagickException(exception,GetMagickModule(),
4007 OptionError,"NoSuchImage","`%s'",images->filename);
4012 swap=CloneImage(p,0,0,MagickTrue,exception);
4013 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4014 ReplaceImageInList(&q,swap);
4015 images=GetFirstImageInList(q);
4022 if (LocaleCompare("write",option) == 0)
4033 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4034 (void) DeleteImageRegistry(key);
4035 write_images=images;
4036 if (plus_alt_op != MagickFalse)
4037 write_images=CloneImageList(images,exception);
4038 write_info=CloneImageInfo(image_info);
4039 (void) WriteImages(write_info,write_images,arg1,exception);
4040 write_info=DestroyImageInfo(write_info);
4041 if (plus_alt_op != MagickFalse)
4042 write_images=DestroyImageList(write_images);
4050 if (new_images == (Image *) NULL)
4053 if (images != (Image *) NULL)
4054 images=DestroyImageList(images);
4060 #undef quantize_info