]> granicus.if.org Git - imagemagick/blob - MagickWand/operation.c
(no commit message)
[imagemagick] / MagickWand / operation.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %             OOO  PPPP  EEEE RRRR   AA  TTTTTT III  OOO  N   N               %
7 %            O   O P   P E    R   R A  A   TT    I  O   O NN  N               %
8 %            O   O PPPP  EEE  RRRR  AAAA   TT    I  O   O N N N               %
9 %            O   O P     E    R R   A  A   TT    I  O   O N  NN               %
10 %             OOO  P     EEEE R  RR A  A   TT   III  OOO  N   N               %
11 %                                                                             %
12 %                                                                             %
13 %                         MagickWand Module Methods                           %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                               September 2011                                %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
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.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 % Apply the given options (settings, and simple, or sequence operations) to
37 % the given image(s) according to the current "image_info" and "draw_info"
38 % settings.
39 %
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
42 % IMv7.
43 %
44 % Anthony Thyssen, Sept 2011
45 */
46 #if 0
47 \f
48 /*
49   Include declarations.
50 */
51 #include "MagickWand/studio.h"
52 #include "MagickWand/MagickWand.h"
53 #include "MagickWand/mogrify-private.h"
54 #include "MagickCore/monitor-private.h"
55 #include "MagickCore/thread-private.h"
56 #include "MagickCore/string-private.h"
57 \f
58 /*
59   Define declarations.
60 */
61 #define UndefinedCompressionQuality  0UL
62 /*
63   Constant declaration. (temporary exports)
64 */
65 static const char
66   BackgroundColor[] = "#fff",  /* white */
67   BorderColor[] = "#dfdfdf",  /* gray */
68   MatteColor[] = "#bdbdbd";  /* gray */
69 \f
70 /*
71 ** Function to report on the progress of image operations
72 */
73 static MagickBooleanType MonitorProgress(const char *text,
74   const MagickOffsetType offset,const MagickSizeType extent,
75   void *wand_unused(client_data))
76 {
77   char
78     message[MaxTextExtent],
79     tag[MaxTextExtent];
80
81   const char
82     *locale_message;
83
84   register char
85     *p;
86
87   if (extent < 2)
88     return(MagickTrue);
89   (void) CopyMagickMemory(tag,text,MaxTextExtent);
90   p=strrchr(tag,'/');
91   if (p != (char *) NULL)
92     *p='\0';
93   (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
94   locale_message=GetLocaleMessage(message);
95   if (locale_message == message)
96     locale_message=tag;
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)));
101   else
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);
108   return(MagickTrue);
109 }
110
111 /*
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.
114 */
115 static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
116   ExceptionInfo *exception)
117 {
118   char
119     key[MaxTextExtent];
120
121   ExceptionInfo
122     *sans_exception;
123
124   Image
125     *image;
126
127   ImageInfo
128     *read_info;
129
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)
135     return(image);
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);
142   return(image);
143 }
144
145 /*
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
151   setting.
152 */
153 static Image *SparseColorOption(const Image *image,
154   const SparseColorMethod method,const char *arguments,
155   const MagickBooleanType color_from_image,ExceptionInfo *exception)
156 {
157   char
158     token[MaxTextExtent];
159
160   const char
161     *p;
162
163   double
164     *sparse_arguments;
165
166   Image
167     *sparse_image;
168
169   PixelInfo
170     color;
171
172   MagickBooleanType
173     error;
174
175   register size_t
176     x;
177
178   size_t
179     number_arguments,
180     number_colors;
181
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);
188   /*
189     Limit channels according to image - and add up number of color channel.
190   */
191   number_colors=0;
192   if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
193     number_colors++;
194   if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
195     number_colors++;
196   if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
197     number_colors++;
198   if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
199       (image->colorspace == CMYKColorspace))
200     number_colors++;
201   if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
202       (image->matte != MagickFalse))
203     number_colors++;
204
205   /*
206     Read string, to determine number of arguments needed,
207   */
208   p=arguments;
209   x=0;
210   while( *p != '\0' )
211   {
212     GetMagickToken(p,&p,token);
213     if ( token[0] == ',' ) continue;
214     if ( isalpha((int) token[0]) || token[0] == '#' ) {
215       if ( color_from_image ) {
216         (void) ThrowMagickException(exception,GetMagickModule(),
217             OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
218             "Color arg given, when colors are coming from image");
219         return( (Image *)NULL);
220       }
221       x += number_colors;  /* color argument */
222     }
223     else {
224       x++;   /* floating point argument */
225     }
226   }
227   error=MagickTrue;
228   if ( color_from_image ) {
229     /* just the control points are being given */
230     error = ( x % 2 != 0 ) ? MagickTrue : MagickFalse;
231     number_arguments=(x/2)*(2+number_colors);
232   }
233   else {
234     /* control points and color values */
235     error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
236     number_arguments=x;
237   }
238   if ( error ) {
239     (void) ThrowMagickException(exception,GetMagickModule(),
240                OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
241                "Invalid number of Arguments");
242     return( (Image *)NULL);
243   }
244
245   /* Allocate and fill in the floating point arguments */
246   sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
247     sizeof(*sparse_arguments));
248   if (sparse_arguments == (double *) NULL) {
249     (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
250       "MemoryAllocationFailed","%s","SparseColorOption");
251     return( (Image *)NULL);
252   }
253   (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
254     sizeof(*sparse_arguments));
255   p=arguments;
256   x=0;
257   while( *p != '\0' && x < number_arguments ) {
258     /* X coordinate */
259     token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
260     if ( token[0] == '\0' ) break;
261     if ( isalpha((int) token[0]) || token[0] == '#' ) {
262       (void) ThrowMagickException(exception,GetMagickModule(),
263             OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
264             "Color found, instead of X-coord");
265       error = MagickTrue;
266       break;
267     }
268     sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
269     /* Y coordinate */
270     token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
271     if ( token[0] == '\0' ) break;
272     if ( isalpha((int) token[0]) || token[0] == '#' ) {
273       (void) ThrowMagickException(exception,GetMagickModule(),
274             OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
275             "Color found, instead of Y-coord");
276       error = MagickTrue;
277       break;
278     }
279     sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
280     /* color values for this control point */
281 #if 0
282     if ( (color_from_image ) {
283       /* get color from image */
284       /* HOW??? */
285     }
286     else
287 #endif
288     {
289       /* color name or function given in string argument */
290       token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
291       if ( token[0] == '\0' ) break;
292       if ( isalpha((int) token[0]) || token[0] == '#' ) {
293         /* Color string given */
294         (void) QueryColorCompliance(token,AllCompliance,&color,
295                   exception);
296         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
297           sparse_arguments[x++] = QuantumScale*color.red;
298         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
299           sparse_arguments[x++] = QuantumScale*color.green;
300         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
301           sparse_arguments[x++] = QuantumScale*color.blue;
302         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
303             (image->colorspace == CMYKColorspace))
304           sparse_arguments[x++] = QuantumScale*color.black;
305         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
306             (image->matte != MagickFalse))
307           sparse_arguments[x++] = QuantumScale*color.alpha;
308       }
309       else {
310         /* Colors given as a set of floating point values - experimental */
311         /* NB: token contains the first floating point value to use! */
312         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
313           {
314           while ( token[0] == ',' ) GetMagickToken(p,&p,token);
315           if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
316             break;
317           sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
318           token[0] = ','; /* used this token - get another */
319         }
320         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
321           {
322           while ( token[0] == ',' ) GetMagickToken(p,&p,token);
323           if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
324             break;
325           sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
326           token[0] = ','; /* used this token - get another */
327         }
328         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
329           {
330           while ( token[0] == ',' ) GetMagickToken(p,&p,token);
331           if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
332             break;
333           sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
334           token[0] = ','; /* used this token - get another */
335         }
336         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
337             (image->colorspace == CMYKColorspace))
338           {
339           while ( token[0] == ',' ) GetMagickToken(p,&p,token);
340           if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
341             break;
342           sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
343           token[0] = ','; /* used this token - get another */
344         }
345         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
346             (image->matte != MagickFalse))
347           {
348           while ( token[0] == ',' ) GetMagickToken(p,&p,token);
349           if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
350             break;
351           sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
352           token[0] = ','; /* used this token - get another */
353         }
354       }
355     }
356   }
357   if ( number_arguments != x && !error ) {
358     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
359       "InvalidArgument","`%s': %s","sparse-color","Argument Parsing Error");
360     sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
361     return( (Image *)NULL);
362   }
363   if ( error )
364     return( (Image *)NULL);
365
366   /* Call the Interpolation function with the parsed arguments */
367   sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
368     exception);
369   sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
370   return( sparse_image );
371 }
372 \f
373 /*
374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 %                                                                             %
376 %                                                                             %
377 %                                                                             %
378 +   A p p l y S e t t i n g O p t i o n                                       %
379 %                                                                             %
380 %                                                                             %
381 %                                                                             %
382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383 %
384 %  ApplySettingOption() saves the given single settings option into a CLI wand
385 %  holding the image_info, draw_info, quantize_info structures that is later
386 %  used for reading, processing, and writing images.
387 %
388 %  No image in the wand is actually modified (setting options only)
389 %
390 %  The format of the ApplySettingOption method is:
391 %
392 %    MagickBooleanType ApplySettingOption(MagickWand *wand,
393 %        const int argc, const char **argv,ExceptionInfo *exception)
394 %
395 %  A description of each parameter follows:
396 %
397 %    o wand: structure holding settings to be applied
398 %
399 %    o argc: Specifies a pointer to an integer describing the number of
400 %      elements in the argument vector.
401 %
402 %    o argv: Specifies a pointer to a text array containing the command line
403 %      arguments.
404 %
405 %    o exception: return any errors or warnings in this structure.
406 %
407 */
408 WandExport MagickBooleanType ApplySettingsOption(ImageInfo *image_info,
409   const int argc,const char **argv,ExceptionInfo *exception)
410 {
411   GeometryInfo
412     geometry_info;
413
414   ImageInfo
415     *image_info;
416
417   DrawInfo
418     *draw_info;
419
420   const char
421     *option;
422
423   assert(wand != (MagickWand *) NULL);
424   assert(wand->signature == WandSignature);
425   assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
426   assert(wand->quantize_info == (QuantizeInfo *) NULL);
427   if (wand->debug != MagickFalse)
428     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
429   if (argc < 0)
430     return(MagickTrue);
431
432   option=argv[0]+1;
433   image_info=wand->image_info;
434   draw_info=wand->_info;
435
436 #define IfSetOption ((*argv[0])=='-')
437
438   switch (*option)
439   {
440     case 'a':
441     {
442       if (LocaleCompare("adjoin",option) == 0)
443         {
444           image_info->adjoin = IfSetOption ? MagickTrue : MagickFalse;
445           break;
446         }
447       if (LocaleCompare("affine",option) == 0)
448         {
449           if (IfSetOption)
450             (void) ParseAffineGeometry(argv[1],draw_info->affine,
451                exception);
452           else
453             GetAffineMatrix(draw_info->affine);
454           break;
455         }
456       if (LocaleCompare("antialias",option) == 0)
457         {
458           image_info->antialias =
459           draw_info->stroke_antialias =
460           draw_info->text_antialias =
461                IfSetOption ? MagickTrue : MagickFalse;
462           break;
463         }
464       if (LocaleCompare("authenticate",option) == 0)
465       {
466           (void) SetImageOption(image_info,option,
467                IfSetOption ? argv[1] : (const char*)NULL);
468           break;
469         }
470       break;
471     }
472     case 'b':
473     {
474       if (LocaleCompare("background",option) == 0)
475         {
476           /* FUTURE: both image_info attribute & ImageOption in use!
477              Note that +background, means fall-back to image attribute
478              so ImageOption is deleted, not set to a default.
479           */
480           if (IfSetOption)
481             {
482               (void) DeleteImageOption(image_info,option);
483               (void) QueryColorCompliance(BackgroundColor,AllCompliance,
484                     image_info->background_color,exception);
485               break;
486             }
487           (void) SetImageOption(image_info,option,argv[1]);
488           (void) QueryColorCompliance(argv[1],AllCompliance,
489               image_info->background_color,exception);
490           break;
491         }
492       if (LocaleCompare("bias",option) == 0)
493         {
494           /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
495              as it is actually rarely used except in direct convolve
496              Usage outside direct convolve is actally non-sensible!
497           */
498           (void) SetImageOption(image_info,option,
499                IfSetOption ? argv[1] : "0");
500           break;
501         }
502       if (LocaleCompare("black-point-compensation",option) == 0)
503         {
504           (void) SetImageOption(image_info,option,
505                IfSetOption ? "true" : "false" );
506           break;
507         }
508       if (LocaleCompare("blue-primary",option) == 0)
509         {
510           /* Image chromaticity X,Y  NB: Y=X if Y not defined
511              Used by many coders
512           */
513           (void) SetImageOption(image_info,option,
514                IfSetOption ? argv[1] : "0" );
515           break;
516         }
517       if (LocaleCompare("bordercolor",option) == 0)
518         {
519           /* FUTURE: both image_info attribute & ImageOption in use! */
520           if (IfSetOption)
521             {
522               (void) SetImageOption(image_info,option,argv[1]);
523               (void) QueryColorCompliance(argv[1],AllCompliece,
524                   &image_info->border_color,exception);
525               (void) QueryColorCompliance(argv[1],AllCompliance,
526                   &draw_info->border_color,exception);
527               break;
528             }
529           (void) DeleteImageOption(image_info,option);
530           (void) QueryColorCompliance(BorderColor,AllCompliance,
531             &image_info->border_color,exception);
532           (void) QueryColorCompliance(BorderColor,AllCompliance,
533             &draw_info->border_color,exception);
534           break;
535         }
536       if (LocaleCompare("box",option) == 0)
537         {
538           const char
539             *value = IfSetOption ? argv[1] : "none";
540           (void) SetImageOption(image_info,option,value);
541           (void) QueryColorCompliance(value,AllCompliance,
542                &draw_info->undercolor,exception);
543           break;
544         }
545       break;
546     }
547     case 'c':
548     {
549       if (LocaleCompare("cache",option) == 0)
550         {
551           MagickSizeType
552             limit;
553
554           limit=MagickResourceInfinity;
555           if (LocaleCompare("unlimited",argv[1]) != 0)
556             limit=(MagickSizeType) SiPrefixToDouble(argv[1],100.0);
557           (void) SetMagickResourceLimit(MemoryResource,limit);
558           (void) SetMagickResourceLimit(MapResource,2*limit);
559           break;
560         }
561       if (LocaleCompare("caption",option) == 0)
562         {
563           /* Only used for new images via AquireImage() */
564           (void) SetImageOption(image_info,option,
565                IfSetOption ? argv[1] : (const char*)NULL);
566           break;
567         }
568       if (LocaleCompare("channel",option) == 0)
569         {
570           image_info->channel=(ChannelType) (
571                IfSetOption ? ParseChannelOption(argv[1]) : DefaultChannels );
572           /* FUTURE: This is also a SimpleImageOperator!!! */
573           break;
574         }
575       if (LocaleCompare("colorspace",option) == 0)
576         {
577           /* Setting for new images, and for existing images */
578           /* This is also a SimpleImageOperator */
579           /* Undefined colorspace means don't modify images */
580           image_info->colorspace=UndefinedColorspace;
581           if (IfSetOption)
582             image_info->colorspace=(ColorspaceType) ParseCommandOption(
583                  MagickColorspaceOptions,MagickFalse,argv[1])
584           break;
585         }
586       if (LocaleCompare("comment",option) == 0)
587         {
588           /* Only used for new images via AquireImage() */
589           (void) SetImageOption(image_info,option,
590                IfSetOption ? argv[1] : (const char*)NULL);
591           break;
592         }
593       if (LocaleCompare("compose",option) == 0)
594         {
595           /* FUTURE: image_info should be used, Option for escapes
596              This option should NOT be used to set image 'compose'
597              which is used by "-layer" operators is image_info is undefined
598           */
599           (void) SetImageOption(image_info,option,
600                IfSetOption ? argv[1] : (const char*)NULL);
601           image_info->compose=(CompositeOperator) ParseCommandOption(
602                MagickComposeOptions,MagickFalse,
603                IfSetOption ? argv[1] : "undefined");
604           break;
605         }
606       if (LocaleCompare("compress",option) == 0)
607         {
608           /* FUTURE: What should be used?  image_info  or ImageOption ???
609              The former is more efficent, but Crisy prefers the latter!
610
611              The coders appears to use image_info, not Image_Option
612              however the image attribute (for save) is set from the
613              ImageOption!
614           */
615           if (IfSetOption)
616             {
617               image_info->compression=(CompressionType) ParseCommandOption(
618                 MagickCompressOptions,MagickFalse,argv[1]);
619               (void) SetImageOption(image_info,option,argv[1]);
620               break;
621             }
622           image_info->compression=UndefinedCompression;
623           (void) SetImageOption(image_info,option,"undefined");
624           break;
625         }
626       break;
627     }
628     case 'd':
629     {
630       if (LocaleCompare("debug",option) == 0)
631         {
632           if (IfSetOption)
633           (void) SetLogEventMask(IfSetOption?argv[1]:"none");
634           image_info->debug=IsEventLogging(); /* extract logging*/
635           wand->debug=IsEventLogging();
636           break;
637         }
638       if (LocaleCompare("define",option) == 0)
639         {
640           /* FUTURE both -set and -define sets ImageOption
641              But differs in that -set tried to set image properity (attribute)
642           */
643           if (LocaleNCompare(argv[1],"registry:",9) == 0)
644             {
645               if (IfSetOption)
646                 (void) DefineImageRegistry(StringRegistryType,argv[1]+9,
647                     exception);
648               else
649                 (void) DefineImageOption(image_info,argv[1],exception);
650               break;
651             }
652           if (IfSetOption)
653             (void) DefineImageOption(image_info,argv[1],exception);
654           else
655             (void) DeleteImageOption(image_info,argv[1],exception);
656           break;
657         }
658       if (LocaleCompare("delay",option) == 0)
659         {
660           /* Only used for new images via AcquireImage()
661              Option should also be used for "-morph" (color morphong)
662           */
663           (void) SetImageOption(image_info,option,
664                IfSetOption ? argv[1] : "0");
665           break;
666         }
667       if (LocaleCompare("density",option) == 0)
668         {
669           /* Used by both draw_info and in images via SyncImageSettings() */
670           if (IfSetOption)
671             {
672               (void) CloneString(&image_info->density,argv[1]);
673               (void) CloneString(&draw_info->density,argv[1]);
674               (void) SetImageOption(image_info,option,argv[1]);
675               break;
676             }
677           if (image_info->density != (char *) NULL)
678             image_info->density=DestroyString(image_info->density);
679           if (draw_info->density != (char *) NULL)
680             draw_info->density=DestroyString(draw_info->density);
681           (void) SetImageOption(image_info,option,"72");
682           break;
683         }
684       if (LocaleCompare("depth",option) == 0)
685         {
686           /* This is also a SimpleImageOperator! */
687           image_info->depth=IsSetOption?StringToUnsignedLong(argv[1])
688                                        :MAGICKCORE_QUANTUM_DEPTH;
689           break;
690         }
691       if (LocaleCompare("direction",option) == 0)
692         {
693           /* Image Option is only used to set draw_info */
694           (void) SetImageOption(image_info,option,
695                IfSetOption ? argv[1] : "undefined");
696           draw_info->direction=(DirectionType) ParseCommandOption(
697                          MagickDirectionOptions,MagickFalse,
698                          IfSetOption ? argv[1] : "undefined");
699           break;
700         }
701       if (LocaleCompare("display",option) == 0)
702         {
703           if (IfSetOption)
704             (void) CloneString(&image_info->server_name,argv[1]);
705           else
706             if (image_info->server_name != (char *) NULL)
707               image_info->server_name=DestroyString(image_info->server_name);
708           break;
709         }
710       if (LocaleCompare("dispose",option) == 0)
711         {
712           (void) SetImageOption(image_info,option,
713                IfSetOption ? argv[1] : "undefined");
714           break;
715         }
716       if (LocaleCompare("dither",option) == 0)
717         {
718           /* FUTURE: Merge boolean image_info->dither with Dither type */
719           (void) SetImageOption(image_info,option,
720                        IfSetOption ? argv[1] : "none");
721           image_info->dither = quantize_info->dither =
722                     IfSetOption ? MagickTrue : MagickFalse;
723           quantize_info->dither_method=(DitherMethod) ParseCommandOption(
724                     MagickDitherOptions,MagickFalse,
725                     IfSetOption ? argv[1] : "none");
726           if (quantize_info->dither_method == NoDitherMethod)
727                 image_info->dither = quantize_info->dither = MagickFalse;
728           break;
729         }
730       break;
731     }
732     case 'e':
733     {
734       if (LocaleCompare("encoding",option) == 0)
735         {
736           (void) CloneString(&draw_info->encoding,
737                        IfSetOption ? argv[1] : "undefined");
738           (void) SetImageOption(image_info,option,&draw_info->encoding);
739           break;
740         }
741       if (LocaleCompare("endian",option) == 0)
742         {
743           const char
744             value;
745
746           value=IfSetOption?argv[1]:"undefined";
747           (void) SetImageOption(image_info,option,value);
748           image_info->endian=(EndianType) ParseCommandOption(
749               MagickEndianOptions,MagickFalse,value);
750           break;
751         }
752       if (LocaleCompare("extract",option) == 0)
753         {
754           (void) CloneString(&image_info->extract,
755                IfSetOption?argv[1]:(const char *) NULL);
756           break;
757         }
758       break;
759     }
760     case 'f':
761     {
762       if (LocaleCompare("family",argv[0]+1) == 0)
763         {
764           (void) CloneString(&draw_info->family,
765                IfSetOption ? argv[1] : (const char *) NULL);
766           break;
767         }
768       if (LocaleCompare("fill",option) == 0)
769         {
770           /* set fill OR a fill-pattern */
771           /* FUTURE: tile is only set in draw_info, not in image_info ! */
772           const char
773             value;
774
775           ExceptionInfo
776             *sans;
777
778           value = IfSetOption ? argv[1] : "none";
779           (void) SetImageOption(image_info,option,value);
780
781           sans=AcquireExceptionInfo();
782           status=QueryColorCompliance(value,AllCompliance,&draw_info->fill,sans);
783           sans=DestroyExceptionInfo(sans);
784
785           if (draw_info->fill_pattern != (Image *) NULL)
786             draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
787           if (status == MagickFalse)
788             draw_info->fill_pattern=GetImageCache(image_info,value,
789               exception);
790           break;
791         }
792       if (LocaleCompare("filter",option) == 0)
793         {
794           (void) SetImageOption(image_info,option,
795                 IfSetOption ? argv[1] : "undefined");
796           break;
797         }
798       if (LocaleCompare("font",option) == 0)
799         {
800           (void) CloneString(&draw_info->font,
801                IfSetOption ? argv[1] : (const char *) NULL);
802           (void) CloneString(&image_info->font,draw_info->font);
803           break;
804         }
805       if (LocaleCompare("format",option) == 0)
806         {
807           /* FUTURE: why the ping test, you could set ping after this! */
808           /*
809           register const char
810             *q;
811
812           for (q=strchr(argv[1],'%'); q != (char *) NULL; q=strchr(q+1,'%'))
813             if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
814               image_info->ping=MagickFalse;
815           */
816           (void) SetImageOption(image_info,option,
817                IfSetOption ? argv[1] : (const char *) NULL);
818           break;
819         }
820       if (LocaleCompare("fuzz",option) == 0)
821         {
822           /* FUTURE: image_info and ImageOption!
823              Option used to set image fuzz! unless blank canvas (from color)
824              Image attribute used for color compare operations
825              image->fuzz is being set by SyncImageSettings()
826              Can't find anything making use of image_info->fuzz
827           */
828           (void) SetImageOption(image_info,option,
829                IfSetOption ? argv[1] : (const char *) NULL);
830           if (IfSetOption)
831             image_info->fuzz=SiPrefixToDouble(argv[1],(double) QuantumRange+1.0);
832           else
833             image_info->fuzz=0.0;
834           break;
835         }
836       break;
837     }
838     case 'g':
839     {
840       if (LocaleCompare("gravity",option) == 0)
841         {
842           /* FUTURE gravity also set in image via SyncImageSettings() */
843           const char
844             value;
845
846           value = IfSetOption ? argv[1] : "none";
847           (void) SetImageOption(image_info,option,value);
848           draw_info->gravity=(GravityType) ParseCommandOption(
849                            MagickGravityOptions,MagickFalse,value);
850           break;
851         }
852       if (LocaleCompare("green-primary",option) == 0)
853         {
854           /* Image chromaticity X,Y  NB: Y=X if Y not defined
855              Used by many coders
856           */
857           (void) SetImageOption(image_info,option,
858                IfSetOption ? argv[1] : "0.0");
859           break;
860         }
861       break;
862     }
863     case 'i':
864     {
865       if (LocaleCompare("intent",option) == 0)
866         {
867           /* FUTURE: this should also set image->rendering_intent
868              Which is only used by coders: MIFF, MPC, BMP, PNG
869              and for image profile call to AcquireTransformThreadSet()
870           */
871           (void) SetImageOption(image_info,option,
872                IfSetOption ? argv[1] : "undefined");
873           break;
874         }
875       if (LocaleCompare("interlace",option) == 0)
876         {
877           /* sets image attibute interlace via SyncImageSettings()
878              Also image_info is directly used by coders
879           */
880           const char
881             value;
882
883           value = IfSetOption ? argv[1] : "undefined";
884           (void) SetImageOption(image_info,option, value);
885           image_info->interlace=(InterlaceType) ParseCommandOption(
886             MagickInterlaceOptions,MagickFalse,value);
887           break;
888         }
889       if (LocaleCompare("interline-spacing",option) == 0)
890         {
891           const char
892             value;
893
894           value = IfSetOption ? argv[1] : "0"; /* undefined? */
895           (void) SetImageOption(image_info,option, value);
896           draw_info->interline_spacing=InterpretLocaleValue(value,
897                (char **) NULL);
898           break;
899         }
900       if (LocaleCompare("interpolate",option) == 0)
901         {
902           /* FUTURE: sets image interpolate value via SyncImageSettings()
903              It is NOT used by coders, only in image processing,
904              so shoud really be a image_info attribute.
905           */
906           (void) SetImageOption(image_info,option,
907                IfSetOption ? argv[1] : "undefined");
908           break;
909         }
910       if (LocaleCompare("interword-spacing",argv[0]+1) == 0)
911         {
912           const char
913             value;
914
915           value = IfSetOption ? argv[1] : "0"; /* undefined? */
916           (void) SetImageOption(image_info,option, value);
917           draw_info->interword_spacing=InterpretLocaleValue(value,
918                (char **) NULL);
919           break;
920         }
921       break;
922     }
923     case 'k':
924     {
925       if (LocaleCompare("kerning",option) == 0)
926         {
927           const char
928             value;
929
930           value = IfSetOption ? argv[1] : "0"; /* undefined? */
931           (void) SetImageOption(image_info,option, value);
932           draw_info->kerning=InterpretLocaleValue(value,(char **) NULL);
933           break;
934         }
935       break;
936     }
937     case 'l':
938     {
939       if (LocaleCompare("label",option) == 0)
940         {
941           /* only used for new images */
942           (void) SetImageOption(image_info,option,
943                IfSetOption ? argv[1] : (char *)NULL);
944           break;
945         }
946       if (LocaleCompare("limit",option) == 0)
947         {
948           MagickSizeType
949             limit;
950
951           ResourceType
952             type;
953
954           if (!IsSetOption)
955             break;
956           type=(ResourceType) ParseCommandOption(MagickResourceOptions,
957             MagickFalse,argv[1]);
958           limit=MagickResourceInfinity;
959           if (LocaleCompare("unlimited",argv[2]) != 0)
960             limit=(MagickSizeType) SiPrefixToDouble(argv[2],100.0);
961           (void) SetMagickResourceLimit(type,limit);
962           break;
963         }
964       if (LocaleCompare("linewidth",argv[0]+1) == 0)
965         {
966           /* FUTURE: obsoleted by stroke-width setting */
967           draw_info->stroke_width=InterpretLocaleValue(argv[1],
968             (char **) NULL);
969           break;
970         }
971       if (LocaleCompare("list",option) == 0)
972         {
973           ssize_t
974             list;
975
976           list=ParseCommandOption(MagickListOptions,MagickFalse,argv[1]);
977           switch (list)
978           {
979             case MagickCoderOptions:
980             {
981               (void) ListCoderInfo((FILE *) NULL,exception);
982               break;
983             }
984             case MagickColorOptions:
985             {
986               (void) ListColorInfo((FILE *) NULL,exception);
987               break;
988             }
989             case MagickConfigureOptions:
990             {
991               (void) ListConfigureInfo((FILE *) NULL,exception);
992               break;
993             }
994             case MagickDelegateOptions:
995             {
996               (void) ListDelegateInfo((FILE *) NULL,exception);
997               break;
998             }
999             case MagickFontOptions:
1000             {
1001               (void) ListTypeInfo((FILE *) NULL,exception);
1002               break;
1003             }
1004             case MagickFormatOptions:
1005             {
1006               (void) ListMagickInfo((FILE *) NULL,exception);
1007               break;
1008             }
1009             case MagickLocaleOptions:
1010             {
1011               (void) ListLocaleInfo((FILE *) NULL,exception);
1012               break;
1013             }
1014             case MagickLogOptions:
1015             {
1016               (void) ListLogInfo((FILE *) NULL,exception);
1017               break;
1018             }
1019             case MagickMagicOptions:
1020             {
1021               (void) ListMagicInfo((FILE *) NULL,exception);
1022               break;
1023             }
1024             case MagickMimeOptions:
1025             {
1026               (void) ListMimeInfo((FILE *) NULL,exception);
1027               break;
1028             }
1029             case MagickModuleOptions:
1030             {
1031               (void) ListModuleInfo((FILE *) NULL,exception);
1032               break;
1033             }
1034             case MagickPolicyOptions:
1035             {
1036               (void) ListPolicyInfo((FILE *) NULL,exception);
1037               break;
1038             }
1039             case MagickResourceOptions:
1040             {
1041               (void) ListMagickResourceInfo((FILE *) NULL,exception);
1042               break;
1043             }
1044             case MagickThresholdOptions:
1045             {
1046               (void) ListThresholdMaps((FILE *) NULL,exception);
1047               break;
1048             }
1049             default:
1050             {
1051               (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
1052                 exception);
1053               break;
1054             }
1055           }
1056           break;
1057         }
1058       if (LocaleCompare("log",option) == 0)
1059         {
1060           if (IsSetOption)
1061             (void) SetLogFormat(argv[1]);
1062           break;
1063         }
1064       if (LocaleCompare("loop",option) == 0)
1065         {
1066           /* Sets image attibutes iterations via SyncImageSettings() */
1067           (void) SetImageOption(image_info,option,
1068                IfSetOption ? argv[1] : "0");
1069           break;
1070         }
1071       break;
1072     }
1073     case 'm':
1074     {
1075       if (LocaleCompare("mattecolor",option) == 0)
1076         {
1077           (void) SetImageOption(image_info,option,argv[1]);
1078           (void) QueryColorCompliance(argv[1],AllCompliance,
1079             &image_info->matte_color,exception);
1080           break;
1081         }
1082       if (LocaleCompare("monitor",option) == 0)
1083         {
1084           (void) SetImageInfoProgressMonitor(image_info,MonitorProgress,
1085             (void *) NULL);
1086           break;
1087         }
1088       if (LocaleCompare("monochrome",option) == 0)
1089         {
1090           /* Setting (for input coders) and a 'type' operation */
1091           image_info->monochrome=IsSetOption ? MagickTrue : MagickFalse;
1092           break;
1093         }
1094       break;
1095     }
1096     case 'o':
1097     {
1098       if (LocaleCompare("orient",option) == 0)
1099         {
1100           /* Sets image attribute orientation via SyncImageSettings()
1101              Is not used when defining for new images.
1102              This makes it more of a 'operation' than a setting
1103           */
1104           const char
1105             value;
1106
1107           value = IfSetOption ? argv[1] : "undefined";
1108           (void) SetImageOption(image_info,option, value);
1109           image_info->orientation=(InterlaceType) ParseCommandOption(
1110             MagickOrientationOptions,MagickFalse,value);
1111           break;
1112         }
1113     }
1114     case 'p':
1115     {
1116       if (LocaleCompare("page",option) == 0)
1117         {
1118           /* Only used for new images and image generators */
1119           char
1120             *canonical_page,
1121             page[MaxTextExtent];
1122
1123           const char
1124             *image_option;
1125
1126           MagickStatusType
1127             flags;
1128
1129           RectangleInfo
1130             geometry;
1131
1132           if (!IsSetOption)
1133             {
1134               (void) DeleteImageOption(image_info,option);
1135               (void) CloneString(&image_info->page,(char *) NULL);
1136               break;
1137             }
1138           (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1139           image_option=GetImageOption(image_info,"page");
1140           if (image_option != (const char *) NULL)
1141             flags=ParseAbsoluteGeometry(image_option,&geometry);
1142           canonical_page=GetPageGeometry(argv[1]);
1143           flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1144           canonical_page=DestroyString(canonical_page);
1145           (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1146             (unsigned long) geometry.width,(unsigned long) geometry.height);
1147           if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1148             (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1149               (unsigned long) geometry.width,(unsigned long) geometry.height,
1150               (long) geometry.x,(long) geometry.y);
1151           (void) SetImageOption(image_info,option,page);
1152           (void) CloneString(&image_info->page,page);
1153           break;
1154         }
1155       if (LocaleCompare("ping",option) == 0)
1156         {
1157           image_info->ping=(*argv[0] == '-') ? MagickTrue : MagickFalse;
1158           break;
1159         }
1160       if (LocaleCompare("pointsize",option) == 0)
1161         {
1162           double
1163             value=12.0;
1164
1165           if (IfSetOption)
1166             InterpretLocaleValue(argv[1],(char **) NULL);
1167           image_info->pointsize=draw_info->pointsize=value;
1168           break;
1169         }
1170       if (LocaleCompare("precision",option) == 0)
1171         {
1172           (void) SetMagickPrecision(StringToInteger(argv[1]));
1173           break;
1174         }
1175       /* FUTURE: Only the 'preview' coder appears to use this
1176        * Depreciate the coder?  Leaving only the 'preview' operator.
1177       if (LocaleCompare("preview",option) == 0)
1178         {
1179           image_info->preview_type=UndefinedPreview;
1180           if (IfSetOption)
1181             image_info->preview_type=(PreviewType) ParseCommandOption(
1182                 MagickPreviewOptions,MagickFalse,argv[1]);
1183           break;
1184         }
1185       */
1186       break;
1187     }
1188     case 'q':
1189     {
1190       if (LocaleCompare("quality",option) == 0)
1191         {
1192           if (IfSetOption)
1193             {
1194               image_info->quality=StringToUnsignedLong(argv[1]);
1195               (void) SetImageOption(image_info,option,argv[1]);
1196               break;
1197             }
1198           image_info->quality=UndefinedCompressionQuality;
1199           (void) SetImageOption(image_info,option,"0");
1200           break;
1201         }
1202       if (LocaleCompare("quantize",option) == 0)
1203         {
1204           /* no image_info setting!  Only set direct in quantize_info */
1205           quantize_info->colorspace=UndefinedColorspace;
1206           if (IfSetOption)
1207             quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
1208               MagickColorspaceOptions,MagickFalse,argv[1]);
1209           break;
1210         }
1211       if (LocaleCompare("quiet",option) == 0)
1212         {
1213           /* FUTURE: if two -quiet is performed you can not do +quiet! */
1214           static WarningHandler
1215             warning_handler = (WarningHandler) NULL;
1216
1217           if (*argv[0] == '+')
1218             {
1219               /* Restore error or warning messages.  */
1220               warning_handler=SetWarningHandler(warning_handler);
1221               break;
1222             }
1223           /* Suppress error or warning messages.  */
1224           warning_handler=SetWarningHandler((WarningHandler) NULL);
1225           break;
1226         }
1227       break;
1228     }
1229     case 'r':
1230     {
1231       if (LocaleCompare("red-primary",option) == 0)
1232         {
1233           /* Image chromaticity X,Y  NB: Y=X if Y not defined
1234              Used by many coders
1235           */
1236           (void) SetImageOption(image_info,option,
1237                IfSetOption ? argv[1] : "0" );
1238           break;
1239         }
1240       break;
1241     }
1242     case 's':
1243     {
1244       if (LocaleCompare("sampling-factor",option) == 0)
1245         {
1246           /*
1247             Set image sampling factor.
1248           */
1249           if (*argv[0] == '+')
1250             {
1251               if (image_info->sampling_factor != (char *) NULL)
1252                 image_info->sampling_factor=DestroyString(
1253                   image_info->sampling_factor);
1254               break;
1255             }
1256           (void) CloneString(&image_info->sampling_factor,argv[1]);
1257           break;
1258         }
1259       if (LocaleCompare("scene",option) == 0)
1260         {
1261           /*
1262             Set image scene.
1263           */
1264           if (*argv[0] == '+')
1265             {
1266               image_info->scene=0;
1267               (void) SetImageOption(image_info,option,"0");
1268               break;
1269             }
1270           image_info->scene=StringToUnsignedLong(argv[1]);
1271           (void) SetImageOption(image_info,option,argv[1]);
1272           break;
1273         }
1274       if (LocaleCompare("seed",option) == 0)
1275         {
1276           size_t
1277             seed;
1278
1279           if (*argv[0] == '+')
1280             {
1281               seed=(size_t) time((time_t *) NULL);
1282               SeedPseudoRandomGenerator(seed);
1283               break;
1284             }
1285           seed=StringToUnsignedLong(argv[1]);
1286           SeedPseudoRandomGenerator(seed);
1287           break;
1288         }
1289       if (LocaleCompare("size",option) == 0)
1290         {
1291           /* FUTURE: convert to ImageOption
1292              Look at special handling for "size" in SetImageOption()
1293            */
1294           if (*argv[0] == '+')
1295             {
1296               if (image_info->size != (char *) NULL)
1297                 image_info->size=DestroyString(image_info->size);
1298               break;
1299             }
1300           (void) CloneString(&image_info->size,argv[1]);
1301           break;
1302         }
1303       if (LocaleCompare("stroke",option) == 0)
1304         {
1305           if (*argv[0] == '+')
1306             {
1307               (void) SetImageOption(image_info,option,"none");
1308               break;
1309             }
1310           (void) SetImageOption(image_info,option,argv[1]);
1311           break;
1312         }
1313       if (LocaleCompare("strokewidth",option) == 0)
1314         {
1315           if (*argv[0] == '+')
1316             {
1317               (void) SetImageOption(image_info,option,"0");
1318               break;
1319             }
1320           (void) SetImageOption(image_info,option,argv[1]);
1321           break;
1322         }
1323       if (LocaleCompare("synchronize",option) == 0)
1324         {
1325           if (*argv[0] == '+')
1326             {
1327               image_info->synchronize=MagickFalse;
1328               break;
1329             }
1330           image_info->synchronize=MagickTrue;
1331           break;
1332         }
1333       break;
1334     }
1335     case 't':
1336     {
1337       if (LocaleCompare("taint",option) == 0)
1338         {
1339           if (*argv[0] == '+')
1340             {
1341               (void) SetImageOption(image_info,option,"false");
1342               break;
1343             }
1344           (void) SetImageOption(image_info,option,"true");
1345           break;
1346         }
1347       if (LocaleCompare("texture",option) == 0)
1348         {
1349           if (*argv[0] == '+')
1350             {
1351               if (image_info->texture != (char *) NULL)
1352                 image_info->texture=DestroyString(image_info->texture);
1353               break;
1354             }
1355           (void) CloneString(&image_info->texture,argv[1]);
1356           break;
1357         }
1358       if (LocaleCompare("tile",option) == 0)
1359         {
1360           draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
1361           if (ISSetOption)
1362             draw_info->fill_pattern=GetImageCache(image_info,argv[1],exception);
1363           break;
1364         }
1365       if (LocaleCompare("tile-offset",option) == 0)
1366         {
1367           if (*argv[0] == '+')
1368             {
1369               (void) SetImageOption(image_info,option,"0");
1370               break;
1371             }
1372           (void) SetImageOption(image_info,option,argv[1]);
1373           break;
1374         }
1375       if (LocaleCompare("transparent-color",option) == 0)
1376         {
1377           if (*argv[0] == '+')
1378             {
1379               (void) QueryColorCompliance("none",AllCompliance,
1380                   &image_info->transparent_color,exception);
1381               (void) SetImageOption(image_info,option,"none");
1382               break;
1383             }
1384               (void) QueryColorCompliance("none",AllCompliance,
1385                   &image_info->transparent_color,exception);
1386           (void) SetImageOption(image_info,option,argv[1]);
1387           break;
1388         }
1389       if (LocaleCompare("type",option) == 0)
1390         {
1391           if (*argv[0] == '+')
1392             {
1393               image_info->type=UndefinedType;
1394               (void) SetImageOption(image_info,option,"undefined");
1395               break;
1396             }
1397           image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1398             MagickFalse,argv[1]);
1399           (void) SetImageOption(image_info,option,argv[1]);
1400           break;
1401         }
1402       break;
1403     }
1404     case 'u':
1405     {
1406       if (LocaleCompare("undercolor",option) == 0)
1407         {
1408           if (*argv[0] == '+')
1409             {
1410               (void) DeleteImageOption(image_info,option);
1411               break;
1412             }
1413           (void) SetImageOption(image_info,option,argv[1]);
1414           break;
1415         }
1416       if (LocaleCompare("units",option) == 0)
1417         {
1418           if (*argv[0] == '+')
1419             {
1420               image_info->units=UndefinedResolution;
1421               (void) SetImageOption(image_info,option,"undefined");
1422               break;
1423             }
1424           image_info->units=(ResolutionType) ParseCommandOption(
1425             MagickResolutionOptions,MagickFalse,argv[1]);
1426           (void) SetImageOption(image_info,option,argv[1]);
1427           break;
1428         }
1429       break;
1430     }
1431     case 'v':
1432     {
1433       if (LocaleCompare("verbose",option) == 0)
1434         {
1435           if (*argv[0] == '+')
1436             {
1437               image_info->verbose=MagickFalse;
1438               break;
1439             }
1440           image_info->verbose=MagickTrue;
1441           image_info->ping=MagickFalse;
1442           break;
1443         }
1444       if (LocaleCompare("view",option) == 0)
1445         {
1446           if (*argv[0] == '+')
1447             {
1448               if (image_info->view != (char *) NULL)
1449                 image_info->view=DestroyString(image_info->view);
1450               break;
1451             }
1452           (void) CloneString(&image_info->view,argv[1]);
1453           break;
1454         }
1455       if (LocaleCompare("virtual-pixel",option) == 0)
1456         {
1457           if (*argv[0] == '+')
1458             {
1459               image_info->virtual_pixel_method=UndefinedVirtualPixelMethod;
1460               (void) SetImageOption(image_info,option,"undefined");
1461               break;
1462             }
1463           image_info->virtual_pixel_method=(VirtualPixelMethod)
1464             ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,argv[1]);
1465           (void) SetImageOption(image_info,option,argv[1]);
1466           break;
1467         }
1468       break;
1469     }
1470     case 'w':
1471     {
1472       if (LocaleCompare("white-point",option) == 0)
1473         {
1474           if (*argv[0] == '+')
1475             {
1476               (void) SetImageOption(image_info,option,"0.0");
1477               break;
1478             }
1479           (void) SetImageOption(image_info,option,argv[1]);
1480           break;
1481         }
1482       break;
1483     }
1484     default:
1485       break;
1486   }
1487   return(MagickTrue);
1488 }
1489 \f
1490 /*
1491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1492 %                                                                             %
1493 %                                                                             %
1494 %                                                                             %
1495 +     A p p l y I m a g e O p e r a t o r                                     %
1496 %                                                                             %
1497 %                                                                             %
1498 %                                                                             %
1499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1500 %
1501 %  ApplyImageOperator() apply one simple image operation to just the current
1502 %  image.
1503 %
1504 %  The image in the list may be modified in three different ways...
1505 %
1506 %    * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1507 %    * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1508 %    * replace by a list of images (-separate and -crop only!)
1509 %
1510 %  In each case the result is returned into the list, and the pointer to the
1511 %  modified image (last image added if replaced by a list of images) is
1512 %  returned.  As the image pointed to may be replaced, the first image in the
1513 %  list may also change.  GetFirstImageInList() should be used by caller if
1514 %  they wish return the Image pointer to the first image in list.
1515 %
1516 %  The format of the ApplyImageOperator method is:
1517 %
1518 %    MagickBooleanType ApplyImageOperator(MagickWand *wand,
1519 %        const int argc,const char **argv)
1520 %
1521 %  A description of each parameter follows:
1522 %
1523 %    o wand: The CLI wand holding all the settings and pointer to image
1524 %
1525 %    o argc: Specifies a pointer to an integer describing the number of
1526 %      elements in the argument vector.
1527 %
1528 %    o argv: Specifies a pointer to a text array containing the command line
1529 %      arguments.
1530 %
1531 %    o exception: return any errors or warnings in this structure.
1532 %
1533 */
1534 MagickExport MagickBooleanType ApplyImageOperator(MagickWand *wand,
1535      const int wand_unused(argc), const char **argv, ExceptionInfo *exception)
1536 {
1537   Image *
1538     new_image;
1539
1540   ChannelType
1541     channel;
1542
1543   ComposeOperation
1544      compose;
1545
1546   const char
1547     *format;
1548
1549   DrawInfo
1550     *draw_info;
1551
1552   GeometryInfo
1553     geometry_info;
1554
1555   RectangleInfo
1556     geometry;
1557
1558   MagickStatusType
1559     status;
1560
1561   PixelInfo
1562     fill;
1563
1564   MagickStatusType
1565     flags;
1566
1567   QuantizeInfo
1568     *quantize_info;
1569
1570   assert(image_info != (const ImageInfo *) NULL);
1571   assert(image_info->signature == MagickSignature);
1572   assert(image != (Image **) NULL);
1573   assert((*image)->signature == MagickSignature);
1574   if ((*image)->debug != MagickFalse)
1575     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1576   if (argc < 0)
1577     return(MagickTrue);
1578   draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
1579   quantize_info=AcquireQuantizeInfo(image_info);
1580   SetGeometryInfo(&geometry_info);
1581   GetPixelInfo(*image,&fill);
1582   SetPixelInfoPacket(*image,&(*image)->background_color,&fill);
1583   channel=image_info->channel;
1584   format=GetImageOption(image_info,"format");
1585
1586   new_image = (Image *)NULL;
1587
1588   switch (*(option))
1589   {
1590     case 'a':
1591     {
1592       if (LocaleCompare("adaptive-blur",option) == 0)
1593         {
1594           (void) SyncImageSettings(image_info,*image);
1595           flags=ParseGeometry(argv[1],&geometry_info);
1596           if ((flags & SigmaValue) == 0)
1597             geometry_info.sigma=1.0;
1598           if ((flags & XiValue) == 0)
1599             geometry_info.xi=0.0;
1600           new_image=AdaptiveBlurImage(*image,geometry_info.rho,
1601             geometry_info.sigma,geometry_info.xi,exception);
1602           break;
1603         }
1604       if (LocaleCompare("adaptive-resize",option) == 0)
1605         {
1606           /* FUTURE: this is really a "interpolate-resize" operator
1607              "adaptive-resize" uses a fixed "Mesh" interpolation
1608           */
1609           (void) SyncImageSettings(image_info,*image);
1610           (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
1611           new_image=AdaptiveResizeImage(*image,geometry.width,
1612             geometry.height,interpolate_method,exception);
1613           break;
1614         }
1615       if (LocaleCompare("adaptive-sharpen",option) == 0)
1616         {
1617           /*
1618             Adaptive sharpen image.
1619           */
1620           (void) SyncImageSettings(image_info,*image);
1621           flags=ParseGeometry(argv[1],&geometry_info);
1622           if ((flags & SigmaValue) == 0)
1623             geometry_info.sigma=1.0;
1624           if ((flags & XiValue) == 0)
1625             geometry_info.xi=0.0;
1626           new_image=AdaptiveSharpenImage(*image,geometry_info.rho,
1627             geometry_info.sigma,geometry_info.xi,exception);
1628           break;
1629         }
1630       if (LocaleCompare("alpha",option) == 0)
1631         {
1632           AlphaChannelType
1633             alpha_type;
1634
1635           (void) SyncImageSettings(image_info,*image);
1636           alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
1637             MagickFalse,argv[1]);
1638           (void) SetImageAlphaChannel(*image,alpha_type,exception);
1639           break;
1640         }
1641       if (LocaleCompare("annotate",option) == 0)
1642         {
1643           char
1644             *text,
1645             geometry[MaxTextExtent];
1646
1647           (void) SyncImageSettings(image_info,*image);
1648           SetGeometryInfo(&geometry_info);
1649           flags=ParseGeometry(argv[1],&geometry_info);
1650           if ((flags & SigmaValue) == 0)
1651             geometry_info.sigma=geometry_info.rho;
1652           text=InterpretImageProperties(image_info,*image,argv[2],
1653             exception);
1654           if (text == (char *) NULL)
1655             break;
1656           (void) CloneString(&draw_info->text,text);
1657           text=DestroyString(text);
1658           (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1659             geometry_info.xi,geometry_info.psi);
1660           (void) CloneString(&draw_info->geometry,geometry);
1661           draw_info->affine.sx=cos(DegreesToRadians(
1662             fmod(geometry_info.rho,360.0)));
1663           draw_info->affine.rx=sin(DegreesToRadians(
1664             fmod(geometry_info.rho,360.0)));
1665           draw_info->affine.ry=(-sin(DegreesToRadians(
1666             fmod(geometry_info.sigma,360.0))));
1667           draw_info->affine.sy=cos(DegreesToRadians(
1668             fmod(geometry_info.sigma,360.0)));
1669           (void) AnnotateImage(*image,draw_info,exception);
1670           break;
1671         }
1672       if (LocaleCompare("auto-gamma",option) == 0)
1673         {
1674           /*
1675             Auto Adjust Gamma of image based on its mean
1676           */
1677           (void) SyncImageSettings(image_info,*image);
1678           (void) AutoGammaImage(*image,exception);
1679           break;
1680         }
1681       if (LocaleCompare("auto-level",option) == 0)
1682         {
1683           /*
1684             Perfectly Normalize (max/min stretch) the image
1685           */
1686           (void) SyncImageSettings(image_info,*image);
1687           (void) AutoLevelImage(*image,exception);
1688           break;
1689         }
1690       if (LocaleCompare("auto-orient",option) == 0)
1691         {
1692           (void) SyncImageSettings(image_info,*image);
1693           switch ((*image)->orientation)
1694           {
1695             case TopRightOrientation:
1696             {
1697               new_image=FlopImage(*image,exception);
1698               break;
1699             }
1700             case BottomRightOrientation:
1701             {
1702               new_image=RotateImage(*image,180.0,exception);
1703               break;
1704             }
1705             case BottomLeftOrientation:
1706             {
1707               new_image=FlipImage(*image,exception);
1708               break;
1709             }
1710             case LeftTopOrientation:
1711             {
1712               new_image=TransposeImage(*image,exception);
1713               break;
1714             }
1715             case RightTopOrientation:
1716             {
1717               new_image=RotateImage(*image,90.0,exception);
1718               break;
1719             }
1720             case RightBottomOrientation:
1721             {
1722               new_image=TransverseImage(*image,exception);
1723               break;
1724             }
1725             case LeftBottomOrientation:
1726             {
1727               new_image=RotateImage(*image,270.0,exception);
1728               break;
1729             }
1730             default:
1731               break;
1732           }
1733           if (new_image != (Image *) NULL)
1734             new_image->orientation=TopLeftOrientation;
1735           break;
1736         }
1737       break;
1738     }
1739     case 'b':
1740     {
1741       if (LocaleCompare("black-threshold",option) == 0)
1742         {
1743           (void) SyncImageSettings(image_info,*image);
1744           (void) BlackThresholdImage(*image,argv[1],exception);
1745           break;
1746         }
1747       if (LocaleCompare("blue-shift",option) == 0)
1748         {
1749           (void) SyncImageSettings(image_info,*image);
1750           geometry_info.rho=1.5;
1751           if (*argv[0] == '-')
1752             flags=ParseGeometry(argv[1],&geometry_info);
1753           new_image=BlueShiftImage(*image,geometry_info.rho,exception);
1754           break;
1755         }
1756       if (LocaleCompare("blur",option) == 0)
1757         {
1758           /* FUTURE: use of "bias" in a blur is non-sensible */
1759           (void) SyncImageSettings(image_info,*image);
1760           flags=ParseGeometry(argv[1],&geometry_info);
1761           if ((flags & SigmaValue) == 0)
1762             geometry_info.sigma=1.0;
1763           if ((flags & XiValue) == 0)
1764             geometry_info.xi=0.0;
1765           new_image=BlurImage(*image,geometry_info.rho,
1766             geometry_info.sigma,geometry_info.xi,exception);
1767           break;
1768         }
1769       if (LocaleCompare("border",option) == 0)
1770         {
1771           ComposeOperator
1772             compose;
1773
1774           const char*
1775           const char*
1776             value;
1777
1778           value=GetImageOption(image_info,"compose");
1779           if (value != (const char *) NULL)
1780             compose=(CompositeOperator) ParseCommandOption(
1781                  MagickComposeOptions,MagickFalse,value);
1782           else
1783             compose=OverCompositeOp;  /* use Over not image->compose */
1784
1785           (void) SyncImageSettings(image_info,*image);
1786           flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
1787           if ((flags & SigmaValue) == 0)
1788             geometry.height=geometry.width;
1789           new_image=BorderImage(*image,&geometry,compose,exception);
1790           break;
1791         }
1792       if (LocaleCompare("brightness-contrast",option) == 0)
1793         {
1794           double
1795             brightness,
1796             contrast;
1797
1798           GeometryInfo
1799             geometry_info;
1800
1801           MagickStatusType
1802             flags;
1803
1804           (void) SyncImageSettings(image_info,*image);
1805           flags=ParseGeometry(argv[1],&geometry_info);
1806           brightness=geometry_info.rho;
1807           contrast=0.0;
1808           if ((flags & SigmaValue) != 0)
1809             contrast=geometry_info.sigma;
1810           (void) BrightnessContrastImage(*image,brightness,contrast,
1811             exception);
1812           break;
1813         }
1814       break;
1815     }
1816     case 'c':
1817     {
1818       if (LocaleCompare("cdl",option) == 0)
1819         {
1820           char
1821             *color_correction_collection;
1822
1823           /*
1824             Color correct with a color decision list.
1825           */
1826           (void) SyncImageSettings(image_info,*image);
1827           color_correction_collection=FileToString(argv[1],~0,exception);
1828           if (color_correction_collection == (char *) NULL)
1829             break;
1830           (void) ColorDecisionListImage(*image,color_correction_collection,
1831             exception);
1832           break;
1833         }
1834       if (LocaleCompare("channel",option) == 0)
1835         {
1836           /* The "channel" setting has already been set */
1837           SetPixelChannelMap(*image,image_info->channel);
1838           break;
1839         }
1840       if (LocaleCompare("charcoal",option) == 0)
1841         {
1842           (void) SyncImageSettings(image_info,*image);
1843           flags=ParseGeometry(argv[1],&geometry_info);
1844           if ((flags & SigmaValue) == 0)
1845             geometry_info.sigma=1.0;
1846           if ((flags & XiValue) == 0)
1847             geometry_info.xi=1.0;
1848           new_image=CharcoalImage(*image,geometry_info.rho,
1849             geometry_info.sigma,geometry_info.xi,exception);
1850           break;
1851         }
1852       if (LocaleCompare("chop",option) == 0)
1853         {
1854           (void) SyncImageSettings(image_info,*image);
1855           (void) ParseGravityGeometry(*image,argv[1],&geometry,exception);
1856           new_image=ChopImage(*image,&geometry,exception);
1857           break;
1858         }
1859       if (LocaleCompare("clamp",option) == 0)
1860         {
1861           (void) SyncImageSettings(image_info,*image);
1862           (void) ClampImage(*image,exception);
1863           break;
1864         }
1865       if (LocaleCompare("clip",option) == 0)
1866         {
1867           (void) SyncImageSettings(image_info,*image);
1868           if (*argv[0] == '+')
1869             {
1870               (void) SetImageClipMask(*image,(Image *) NULL,exception);
1871               break;
1872             }
1873           (void) ClipImage(*image,exception);
1874           break;
1875         }
1876       if (LocaleCompare("clip-mask",option) == 0)
1877         {
1878           CacheView
1879             *mask_view;
1880
1881           Image
1882             *mask_image;
1883
1884           register Quantum
1885             *restrict q;
1886
1887           register ssize_t
1888             x;
1889
1890           ssize_t
1891             y;
1892
1893           (void) SyncImageSettings(image_info,*image);
1894           if (*argv[0] == '+')
1895             {
1896               /* Remove the write mask */
1897               (void) SetImageMask(*image,(Image *) NULL,exception);
1898               break;
1899             }
1900           mask_image=GetImageCache(image_info,argv[1],exception);
1901           if (mask_image == (Image *) NULL)
1902             break;
1903           if (SetImageStorageClass(mask_image,DirectClass,exception) == MagickFalse)
1904             return(MagickFalse);
1905           /* create a write mask from clip-mask image */
1906           /* FUTURE: use Alpha operations instead */
1907           mask_view=AcquireCacheView(mask_image);
1908           for (y=0; y < (ssize_t) mask_image->rows; y++)
1909           {
1910             q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1911               exception);
1912             if (q == (Quantum *) NULL)
1913               break;
1914             for (x=0; x < (ssize_t) mask_image->columns; x++)
1915             {
1916               if (mask_image->matte == MagickFalse)
1917                 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1918               SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1919               SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1920               SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1921               q+=GetPixelChannels(mask_image);
1922             }
1923             if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1924               break;
1925           }
1926           /* set the write mask */
1927           mask_view=DestroyCacheView(mask_view);
1928           mask_image->matte=MagickTrue;
1929           (void) SetImageClipMask(*image,mask_image,exception);
1930           mask_image=DestroyImage(mask_image);
1931           break;
1932         }
1933       if (LocaleCompare("clip-path",option) == 0)
1934         {
1935           (void) SyncImageSettings(image_info,*image);
1936           (void) ClipImagePath(*image,argv[1],*argv[0] == '-' ? MagickTrue :
1937             MagickFalse,exception);
1938           break;
1939         }
1940       if (LocaleCompare("colorize",option) == 0)
1941         {
1942           (void) SyncImageSettings(image_info,*image);
1943           new_image=ColorizeImage(*image,argv[1],draw_info->fill,
1944             exception);
1945           break;
1946         }
1947       if (LocaleCompare("color-matrix",option) == 0)
1948         {
1949           KernelInfo
1950             *kernel;
1951
1952           (void) SyncImageSettings(image_info,*image);
1953           kernel=AcquireKernelInfo(argv[1]);
1954           if (kernel == (KernelInfo *) NULL)
1955             break;
1956           new_image=ColorMatrixImage(*image,kernel,exception);
1957           kernel=DestroyKernelInfo(kernel);
1958           break;
1959         }
1960       if (LocaleCompare("colors",option) == 0)
1961         {
1962           /* Reduce the number of colors in the image.  */
1963           (void) SyncImageSettings(image_info,*image);
1964           quantize_info->number_colors=StringToUnsignedLong(argv[1]);
1965           if (quantize_info->number_colors == 0)
1966             break;
1967           if (((*image)->storage_class == DirectClass) ||
1968               (*image)->colors > quantize_info->number_colors)
1969             (void) QuantizeImage(quantize_info,*image,exception);
1970           else
1971             (void) CompressImageColormap(*image,exception);
1972           break;
1973         }
1974       if (LocaleCompare("colorspace",option) == 0)
1975         {
1976           /* This is a Image Setting, which should already been set */
1977           /* FUTURE: default colorspace should be sRGB!
1978              Unless some type of 'linear colorspace' mode is set.
1979              Note that +colorspace sets "undefined" or no effect on
1980              new images, but forces images already in memory back to RGB!
1981           */
1982           (void) SyncImageSettings(image_info,*image);
1983           (void) TransformImageColorspace(*image,
1984                     IfSetOption ? image_info->colorspace : RGBColorspace,
1985                     exception);
1986           break;
1987         }
1988       if (LocaleCompare("contrast",option) == 0)
1989         {
1990           (void) SyncImageSettings(image_info,*image);
1991           (void) ContrastImage(*image,(*argv[0] == '-') ? MagickTrue :
1992             MagickFalse,exception);
1993           break;
1994         }
1995       if (LocaleCompare("contrast-stretch",option) == 0)
1996         {
1997           double
1998             black_point,
1999             white_point;
2000
2001           MagickStatusType
2002             flags;
2003
2004           /*
2005             Contrast stretch image.
2006           */
2007           (void) SyncImageSettings(image_info,*image);
2008           flags=ParseGeometry(argv[1],&geometry_info);
2009           black_point=geometry_info.rho;
2010           white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2011             black_point;
2012           if ((flags & PercentValue) != 0)
2013             {
2014               black_point*=(double) (*image)->columns*(*image)->rows/100.0;
2015               white_point*=(double) (*image)->columns*(*image)->rows/100.0;
2016             }
2017           white_point=(MagickRealType) (*image)->columns*(*image)->rows-
2018             white_point;
2019           (void) ContrastStretchImage(*image,black_point,white_point,
2020             exception);
2021           break;
2022         }
2023       if (LocaleCompare("convolve",option) == 0)
2024         {
2025           KernelInfo
2026             *kernel_info;
2027
2028           (void) SyncImageSettings(image_info,*image);
2029           kernel_info=AcquireKernelInfo(argv[1]);
2030           if (kernel_info == (KernelInfo *) NULL)
2031             break;
2032           kernel_info->bias=(*image)->bias;
2033           new_image=ConvolveImage(*image,kernel_info,exception);
2034           kernel_info=DestroyKernelInfo(kernel_info);
2035           break;
2036         }
2037       if (LocaleCompare("crop",option) == 0)
2038         {
2039           /*
2040             Crop a image to a smaller size
2041           */
2042           (void) SyncImageSettings(image_info,*image);
2043           new_image=CropImageToTiles(*image,argv[1],exception);
2044           break;
2045         }
2046       if (LocaleCompare("cycle",option) == 0)
2047         {
2048           /*
2049             Cycle an image colormap.
2050           */
2051           (void) SyncImageSettings(image_info,*image);
2052           (void) CycleColormapImage(*image,(ssize_t) StringToLong(argv[1]),
2053             exception);
2054           break;
2055         }
2056       break;
2057     }
2058     case 'd':
2059     {
2060       if (LocaleCompare("decipher",option) == 0)
2061         {
2062           StringInfo
2063             *passkey;
2064
2065           /*
2066             Decipher pixels.
2067           */
2068           (void) SyncImageSettings(image_info,*image);
2069           passkey=FileToStringInfo(argv[1],~0,exception);
2070           if (passkey != (StringInfo *) NULL)
2071             {
2072               (void) PasskeyDecipherImage(*image,passkey,exception);
2073               passkey=DestroyStringInfo(passkey);
2074             }
2075           break;
2076         }
2077       if (LocaleCompare("depth",option) == 0)
2078         {
2079           /* the image_info->depth setting has already bee set
2080            * We just need to apply it to all images in current sequence */
2081           (void) SyncImageSettings(image_info,*image);
2082           (void) SetImageDepth(*image,image_info->depth);
2083           break;
2084         }
2085       if (LocaleCompare("deskew",option) == 0)
2086         {
2087           double
2088             threshold;
2089
2090           /*
2091             Straighten the image.
2092           */
2093           (void) SyncImageSettings(image_info,*image);
2094           if (*argv[0] == '+')
2095             threshold=40.0*QuantumRange/100.0;
2096           else
2097             threshold=SiPrefixToDouble(argv[1],QuantumRange);
2098           new_image=DeskewImage(*image,threshold,exception);
2099           break;
2100         }
2101       if (LocaleCompare("despeckle",option) == 0)
2102         {
2103           /*
2104             Reduce the speckles within an image.
2105           */
2106           (void) SyncImageSettings(image_info,*image);
2107           new_image=DespeckleImage(*image,exception);
2108           break;
2109         }
2110       if (LocaleCompare("display",option) == 0)
2111         {
2112           (void) CloneString(&draw_info->server_name,argv[1]);
2113           break;
2114         }
2115       if (LocaleCompare("distort",option) == 0)
2116         {
2117           char
2118             *args,
2119             token[MaxTextExtent];
2120
2121           const char
2122             *p;
2123
2124           DistortImageMethod
2125             method;
2126
2127           double
2128             *arguments;
2129
2130           register ssize_t
2131             x;
2132
2133           size_t
2134             number_arguments;
2135
2136           /*
2137             Distort image.
2138           */
2139           (void) SyncImageSettings(image_info,*image);
2140           method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
2141             MagickFalse,argv[1]);
2142           if ( method == ResizeDistortion )
2143             {
2144                /* Special Case - Argument is actually a resize geometry!
2145                ** Convert that to an appropriate distortion argument array.
2146                */
2147                double
2148                  resize_args[2];
2149                (void) ParseRegionGeometry(*image,argv[2],&geometry,
2150                     exception);
2151                resize_args[0]=(double)geometry.width;
2152                resize_args[1]=(double)geometry.height;
2153                new_image=DistortImage(*image,method,(size_t)2,
2154                     resize_args,MagickTrue,exception);
2155                break;
2156             }
2157           args=InterpretImageProperties(image_info,*image,argv[2],
2158             exception);
2159           if (args == (char *) NULL)
2160             break;
2161           p=(char *) args;
2162           for (x=0; *p != '\0'; x++)
2163           {
2164             GetMagickToken(p,&p,token);
2165             if (*token == ',')
2166               GetMagickToken(p,&p,token);
2167           }
2168           number_arguments=(size_t) x;
2169           arguments=(double *) AcquireQuantumMemory(number_arguments,
2170             sizeof(*arguments));
2171           if (arguments == (double *) NULL)
2172             ThrowWandFatalException(ResourceLimitFatalError,
2173               "MemoryAllocationFailed",(*image)->filename);
2174           (void) ResetMagickMemory(arguments,0,number_arguments*
2175             sizeof(*arguments));
2176           p=(char *) args;
2177           for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2178           {
2179             GetMagickToken(p,&p,token);
2180             if (*token == ',')
2181               GetMagickToken(p,&p,token);
2182             arguments[x]=InterpretLocaleValue(token,(char **) NULL);
2183           }
2184           args=DestroyString(args);
2185           new_image=DistortImage(*image,method,number_arguments,arguments,
2186             (*argv[0] == '+') ? MagickTrue : MagickFalse,exception);
2187           arguments=(double *) RelinquishMagickMemory(arguments);
2188           break;
2189         }
2190       if (LocaleCompare("draw",option) == 0)
2191         {
2192           (void) SyncImageSettings(image_info,*image);
2193           (void) CloneString(&draw_info->primitive,argv[1]);
2194           (void) DrawImage(*image,draw_info,exception);
2195           break;
2196         }
2197       break;
2198     }
2199     case 'e':
2200     {
2201       if (LocaleCompare("edge",option) == 0)
2202         {
2203           (void) SyncImageSettings(image_info,*image);
2204           flags=ParseGeometry(argv[1],&geometry_info);
2205           if ((flags & SigmaValue) == 0)
2206             geometry_info.sigma=1.0;
2207           new_image=EdgeImage(*image,geometry_info.rho,
2208             geometry_info.sigma,exception);
2209           break;
2210         }
2211       if (LocaleCompare("emboss",option) == 0)
2212         {
2213           (void) SyncImageSettings(image_info,*image);
2214           flags=ParseGeometry(argv[1],&geometry_info);
2215           if ((flags & SigmaValue) == 0)
2216             geometry_info.sigma=1.0;
2217           new_image=EmbossImage(*image,geometry_info.rho,
2218             geometry_info.sigma,exception);
2219           break;
2220         }
2221       if (LocaleCompare("encipher",option) == 0)
2222         {
2223           StringInfo
2224             *passkey;
2225
2226           (void) SyncImageSettings(image_info,*image);
2227           passkey=FileToStringInfo(argv[1],~0,exception);
2228           if (passkey != (StringInfo *) NULL)
2229             {
2230               (void) PasskeyEncipherImage(*image,passkey,exception);
2231               passkey=DestroyStringInfo(passkey);
2232             }
2233           break;
2234         }
2235       if (LocaleCompare("enhance",option) == 0)
2236         {
2237           (void) SyncImageSettings(image_info,*image);
2238           new_image=EnhanceImage(*image,exception);
2239           break;
2240         }
2241       if (LocaleCompare("equalize",option) == 0)
2242         {
2243           (void) SyncImageSettings(image_info,*image);
2244           (void) EqualizeImage(*image,exception);
2245           break;
2246         }
2247       if (LocaleCompare("evaluate",option) == 0)
2248         {
2249           double
2250             constant;
2251
2252           MagickEvaluateOperator
2253             op;
2254
2255           (void) SyncImageSettings(image_info,*image);
2256           op=(MagickEvaluateOperator) ParseCommandOption(
2257             MagickEvaluateOptions,MagickFalse,argv[1]);
2258           constant=SiPrefixToDouble(argv[2],QuantumRange);
2259           (void) EvaluateImage(*image,op,constant,exception);
2260           break;
2261         }
2262       if (LocaleCompare("extent",option) == 0)
2263         {
2264           (void) SyncImageSettings(image_info,*image);
2265           flags=ParseGravityGeometry(*image,argv[1],&geometry,exception);
2266           if (geometry.width == 0)
2267             geometry.width=(*image)->columns;
2268           if (geometry.height == 0)
2269             geometry.height=(*image)->rows;
2270           new_image=ExtentImage(*image,&geometry,exception);
2271           break;
2272         }
2273       break;
2274     }
2275     case 'f':
2276     {
2277       if (LocaleCompare("features",option) == 0)
2278         {
2279           /* FUTURE: Assign Artifact to all images -- really a setting */
2280           (void) SetImageArtifact(*image,"identify:features",
2281               IfSetOption ? argv[1] : (const char *) NULL);
2282           break;
2283         }
2284       if (LocaleCompare("flip",option) == 0)
2285         {
2286           (void) SyncImageSettings(image_info,*image);
2287           new_image=FlipImage(*image,exception);
2288           break;
2289         }
2290       if (LocaleCompare("flop",option) == 0)
2291         {
2292           (void) SyncImageSettings(image_info,*image);
2293           new_image=FlopImage(*image,exception);
2294           break;
2295         }
2296       if (LocaleCompare("floodfill",option) == 0)
2297         {
2298           PixelInfo
2299             target;
2300
2301           (void) SyncImageSettings(image_info,*image);
2302           (void) ParsePageGeometry(*image,argv[1],&geometry,exception);
2303           (void) QueryColorCompliance(argv[2],AllCompliance,&target,
2304                         exception);
2305           (void) FloodfillPaintImage(*image,draw_info,&target,geometry.x,
2306             geometry.y,*argv[0] == '-' ? MagickFalse : MagickTrue,exception);
2307           break;
2308         }
2309       if (LocaleCompare("frame",option) == 0)
2310         {
2311           FrameInfo
2312             frame_info;
2313
2314           (void) SyncImageSettings(image_info,*image);
2315           flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
2316           frame_info.width=geometry.width;
2317           frame_info.height=geometry.height;
2318           if ((flags & HeightValue) == 0)
2319             frame_info.height=geometry.width;
2320           frame_info.outer_bevel=geometry.x;
2321           frame_info.inner_bevel=geometry.y;
2322           frame_info.x=(ssize_t) frame_info.width;
2323           frame_info.y=(ssize_t) frame_info.height;
2324           frame_info.width=(*image)->columns+2*frame_info.width;
2325           frame_info.height=(*image)->rows+2*frame_info.height;
2326           new_image=FrameImage(*image,&frame_info,COMPOSE,exception);
2327           break;
2328         }
2329       if (LocaleCompare("function",option) == 0)
2330         {
2331           char
2332             *arguments,
2333             token[MaxTextExtent];
2334
2335           const char
2336             *p;
2337
2338           double
2339             *parameters;
2340
2341           MagickFunction
2342             function;
2343
2344           register ssize_t
2345             x;
2346
2347           size_t
2348             number_parameters;
2349
2350           (void) SyncImageSettings(image_info,*image);
2351           function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
2352             MagickFalse,argv[1]);
2353           arguments=InterpretImageProperties(image_info,*image,argv[2],
2354             exception);
2355           if (arguments == (char *) NULL)
2356             break;
2357           p=(char *) arguments;
2358           for (x=0; *p != '\0'; x++)
2359           {
2360             GetMagickToken(p,&p,token);
2361             if (*token == ',')
2362               GetMagickToken(p,&p,token);
2363           }
2364           number_parameters=(size_t) x;
2365           parameters=(double *) AcquireQuantumMemory(number_parameters,
2366             sizeof(*parameters));
2367           if (parameters == (double *) NULL)
2368             ThrowWandFatalException(ResourceLimitFatalError,
2369               "MemoryAllocationFailed",(*image)->filename);
2370           (void) ResetMagickMemory(parameters,0,number_parameters*
2371             sizeof(*parameters));
2372           p=(char *) arguments;
2373           for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2374           {
2375             GetMagickToken(p,&p,token);
2376             if (*token == ',')
2377               GetMagickToken(p,&p,token);
2378             parameters[x]=InterpretLocaleValue(token,(char **) NULL);
2379           }
2380           arguments=DestroyString(arguments);
2381           (void) FunctionImage(*image,function,number_parameters,parameters,
2382             exception);
2383           parameters=(double *) RelinquishMagickMemory(parameters);
2384           break;
2385         }
2386       break;
2387     }
2388     case 'g':
2389     {
2390       if (LocaleCompare("gamma",option) == 0)
2391         {
2392           (void) SyncImageSettings(image_info,*image);
2393           if (*argv[0] == '+')
2394             (*image)->gamma=InterpretLocaleValue(argv[1],(char **) NULL);
2395           else
2396             (void) GammaImage(*image,InterpretLocaleValue(argv[1],
2397               (char **) NULL),exception);
2398           break;
2399         }
2400       if ((LocaleCompare("gaussian-blur",option) == 0) ||
2401           (LocaleCompare("gaussian",option) == 0))
2402         {
2403           (void) SyncImageSettings(image_info,*image);
2404           flags=ParseGeometry(argv[1],&geometry_info);
2405           if ((flags & SigmaValue) == 0)
2406             geometry_info.sigma=1.0;
2407           if ((flags & XiValue) == 0)
2408             geometry_info.xi=0.0;
2409           new_image=GaussianBlurImage(*image,geometry_info.rho,
2410             geometry_info.sigma,geometry_info.xi,exception);
2411           break;
2412         }
2413       if (LocaleCompare("geometry",option) == 0)
2414         {
2415             /*
2416               Record Image offset for composition,
2417               Resize last image. -- FUTURE depreciate this aspect
2418             */
2419           (void) SyncImageSettings(image_info,*image);
2420           if (*argv[0] == '+')
2421             {
2422               if ((*image)->geometry != (char *) NULL)
2423                 (*image)->geometry=DestroyString((*image)->geometry);
2424               break;
2425             }
2426           flags=ParseRegionGeometry(*image,argv[1],&geometry,exception);
2427           if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2428             (void) CloneString(&(*image)->geometry,argv[1]);
2429           else
2430             new_image=ResizeImage(*image,geometry.width,geometry.height,
2431               (*image)->filter,(*image)->blur,exception);
2432           break;
2433         }
2434       break;
2435     }
2436     case 'h':
2437     {
2438       if (LocaleCompare("highlight-color",option) == 0)
2439         {
2440           (void) SetImageArtifact(*image,option,argv[1]);
2441           break;
2442         }
2443       break;
2444     }
2445     case 'i':
2446     {
2447       if (LocaleCompare("identify",option) == 0)
2448         {
2449           char
2450             *text;
2451
2452           (void) SyncImageSettings(image_info,*image);
2453           if (format == (char *) NULL)
2454             {
2455               (void) IdentifyImage(*image,stdout,image_info->verbose,
2456                 exception);
2457               break;
2458             }
2459           text=InterpretImageProperties(image_info,*image,format,
2460             exception);
2461           if (text == (char *) NULL)
2462             break;
2463           (void) fputs(text,stdout);
2464           (void) fputc('\n',stdout);
2465           text=DestroyString(text);
2466           break;
2467         }
2468       if (LocaleCompare("implode",option) == 0)
2469         {
2470           (void) SyncImageSettings(image_info,*image);
2471           (void) ParseGeometry(argv[1],&geometry_info);
2472           new_image=ImplodeImage(*image,geometry_info.rho,
2473             interpolate_method,exception);
2474           break;
2475         }
2476       break;
2477     }
2478     case 'l':
2479     {
2480       if (LocaleCompare("lat",option) == 0)
2481         {
2482           /*
2483             Local adaptive threshold image.
2484           */
2485           (void) SyncImageSettings(image_info,*image);
2486           flags=ParseGeometry(argv[1],&geometry_info);
2487           if ((flags & PercentValue) != 0)
2488             geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2489           new_image=AdaptiveThresholdImage(*image,(size_t)
2490             geometry_info.rho,(size_t) geometry_info.sigma,(double)
2491             geometry_info.xi,exception);
2492           break;
2493         }
2494       if (LocaleCompare("level",option) == 0)
2495         {
2496           MagickRealType
2497             black_point,
2498             gamma,
2499             white_point;
2500
2501           MagickStatusType
2502             flags;
2503
2504           (void) SyncImageSettings(image_info,*image);
2505           flags=ParseGeometry(argv[1],&geometry_info);
2506           black_point=geometry_info.rho;
2507           white_point=(MagickRealType) QuantumRange;
2508           if ((flags & SigmaValue) != 0)
2509             white_point=geometry_info.sigma;
2510           gamma=1.0;
2511           if ((flags & XiValue) != 0)
2512             gamma=geometry_info.xi;
2513           if ((flags & PercentValue) != 0)
2514             {
2515               black_point*=(MagickRealType) (QuantumRange/100.0);
2516               white_point*=(MagickRealType) (QuantumRange/100.0);
2517             }
2518           if ((flags & SigmaValue) == 0)
2519             white_point=(MagickRealType) QuantumRange-black_point;
2520           if ((*argv[0] == '+') || ((flags & AspectValue) != 0))
2521             (void) LevelizeImage(*image,black_point,white_point,gamma,
2522               exception);
2523           else
2524             (void) LevelImage(*image,black_point,white_point,gamma,
2525               exception);
2526           break;
2527         }
2528       if (LocaleCompare("level-colors",option) == 0)
2529         {
2530           char
2531             token[MaxTextExtent];
2532
2533           const char
2534             *p;
2535
2536           PixelInfo
2537             black_point,
2538             white_point;
2539
2540           p=(const char *) argv[1];
2541           GetMagickToken(p,&p,token);  /* get black point color */
2542           if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2543             (void) QueryColorCompliance(token,AllCompliance,
2544                       &black_point,exception);
2545           else
2546             (void) QueryColorCompliance("#000000",AllCompliance,
2547                       &black_point,exception);
2548           if (isalpha((int) token[0]) || (token[0] == '#'))
2549             GetMagickToken(p,&p,token);
2550           if (*token == '\0')
2551             white_point=black_point; /* set everything to that color */
2552           else
2553             {
2554               if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2555                 GetMagickToken(p,&p,token); /* Get white point color. */
2556               if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2557                 (void) QueryColorCompliance(token,AllCompliance,
2558                            &white_point,exception);
2559               else
2560                 (void) QueryColorCompliance("#ffffff",AllCompliance,
2561                            &white_point,exception);
2562             }
2563           (void) LevelImageColors(*image,&black_point,&white_point,
2564             *argv[0] == '+' ? MagickTrue : MagickFalse,exception);
2565           break;
2566         }
2567       if (LocaleCompare("linear-stretch",option) == 0)
2568         {
2569           double
2570             black_point,
2571             white_point;
2572
2573           MagickStatusType
2574             flags;
2575
2576           (void) SyncImageSettings(image_info,*image);
2577           flags=ParseGeometry(argv[1],&geometry_info);
2578           black_point=geometry_info.rho;
2579           white_point=(MagickRealType) (*image)->columns*(*image)->rows;
2580           if ((flags & SigmaValue) != 0)
2581             white_point=geometry_info.sigma;
2582           if ((flags & PercentValue) != 0)
2583             {
2584               black_point*=(double) (*image)->columns*(*image)->rows/100.0;
2585               white_point*=(double) (*image)->columns*(*image)->rows/100.0;
2586             }
2587           if ((flags & SigmaValue) == 0)
2588             white_point=(MagickRealType) (*image)->columns*(*image)->rows-
2589               black_point;
2590           (void) LinearStretchImage(*image,black_point,white_point,exception);
2591           break;
2592         }
2593       if (LocaleCompare("liquid-rescale",option) == 0)
2594         {
2595           /*
2596             Liquid rescale image.
2597           */
2598           (void) SyncImageSettings(image_info,*image);
2599           flags=ParseRegionGeometry(*image,argv[1],&geometry,exception);
2600           if ((flags & XValue) == 0)
2601             geometry.x=1;
2602           if ((flags & YValue) == 0)
2603             geometry.y=0;
2604           new_image=LiquidRescaleImage(*image,geometry.width,
2605             geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2606           break;
2607         }
2608       if (LocaleCompare("lowlight-color",option) == 0)
2609         {
2610           (void) SetImageArtifact(*image,option,argv[1]);
2611           break;
2612         }
2613       break;
2614     }
2615     case 'm':
2616     {
2617       if (LocaleCompare("map",option) == 0)
2618         {
2619           Image
2620             *remap_image;
2621
2622           (void) SyncImageSettings(image_info,*image);
2623           if (*argv[0] == '+')
2624             break;
2625           remap_image=GetImageCache(image_info,argv[1],exception);
2626           if (remap_image == (Image *) NULL)
2627             break;
2628           (void) RemapImage(quantize_info,*image,remap_image,exception);
2629           remap_image=DestroyImage(remap_image);
2630           break;
2631         }
2632       if (LocaleCompare("mask",option) == 0)
2633         {
2634           Image
2635             *mask;
2636
2637           (void) SyncImageSettings(image_info,*image);
2638           if (*argv[0] == '+')
2639             {
2640               (void) SetImageMask(*image,(Image *) NULL,exception);
2641               break;
2642             }
2643           mask=GetImageCache(image_info,argv[1],exception);
2644           if (mask == (Image *) NULL)
2645             break;
2646           (void) SetImageMask(*image,mask,exception);
2647           mask=DestroyImage(mask);
2648           break;
2649         }
2650       if (LocaleCompare("matte",option) == 0)
2651         {
2652           /* FUTURE: Obsoleted by -alpha not used by anything */
2653           (void) SetImageAlphaChannel(*image,IfSetOption ?
2654                SetAlphaChannel : DeactivateAlphaChannel,exception);
2655           break;
2656         }
2657       if (LocaleCompare("median",option) == 0)
2658         {
2659           (void) SyncImageSettings(image_info,*image);
2660           flags=ParseGeometry(argv[1],&geometry_info);
2661           if ((flags & SigmaValue) == 0)
2662             geometry_info.sigma=geometry_info.rho;
2663           new_image=StatisticImage(*image,MedianStatistic,(size_t)
2664             geometry_info.rho,(size_t) geometry_info.sigma,exception);
2665           break;
2666         }
2667       if (LocaleCompare("mode",option) == 0)
2668         {
2669           /*
2670             Statistical Mode image
2671           */
2672           (void) SyncImageSettings(image_info,*image);
2673           flags=ParseGeometry(argv[1],&geometry_info);
2674           if ((flags & SigmaValue) == 0)
2675             geometry_info.sigma=geometry_info.rho;
2676           new_image=StatisticImage(*image,ModeStatistic,(size_t)
2677             geometry_info.rho,(size_t) geometry_info.sigma,exception);
2678           break;
2679         }
2680       if (LocaleCompare("modulate",option) == 0)
2681         {
2682           (void) SyncImageSettings(image_info,*image);
2683           (void) ModulateImage(*image,argv[1],exception);
2684           break;
2685         }
2686       if (LocaleCompare("monitor",option) == 0)
2687         {
2688           if (*argv[0] == '+')
2689             {
2690               (void) SetImageProgressMonitor(*image,
2691                 (MagickProgressMonitor) NULL,(void *) NULL);
2692               break;
2693             }
2694           (void) SetImageProgressMonitor(*image,MonitorProgress,
2695             (void *) NULL);
2696           break;
2697         }
2698       if (LocaleCompare("monochrome",option) == 0)
2699         {
2700           /* A setting (for input coders) and a 'type' operation */
2701           (void) SyncImageSettings(image_info,*image);
2702           (void) SetImageType(*image,BilevelType,exception);
2703           break;
2704         }
2705       if (LocaleCompare("morphology",option) == 0)
2706         {
2707           char
2708             token[MaxTextExtent];
2709
2710           const char
2711             *p;
2712
2713           KernelInfo
2714             *kernel;
2715
2716           MorphologyMethod
2717             method;
2718
2719           ssize_t
2720             iterations;
2721
2722           /*
2723             Morphological Image Operation
2724           */
2725           (void) SyncImageSettings(image_info,*image);
2726           p=argv[1];
2727           GetMagickToken(p,&p,token);
2728           method=(MorphologyMethod) ParseCommandOption(
2729             MagickMorphologyOptions,MagickFalse,token);
2730           iterations=1L;
2731           GetMagickToken(p,&p,token);
2732           if ((*p == ':') || (*p == ','))
2733             GetMagickToken(p,&p,token);
2734           if ((*p != '\0'))
2735             iterations=(ssize_t) StringToLong(p);
2736           kernel=AcquireKernelInfo(argv[2]);
2737           if (kernel == (KernelInfo *) NULL)
2738             {
2739               (void) ThrowMagickException(exception,GetMagickModule(),
2740                 OptionError,"UnabletoParseKernel","morphology");
2741               status=MagickFalse;
2742               break;
2743             }
2744           new_image=MorphologyImage(*image,method,iterations,kernel,
2745             exception);
2746           kernel=DestroyKernelInfo(kernel);
2747           break;
2748         }
2749       if (LocaleCompare("motion-blur",option) == 0)
2750         {
2751           (void) SyncImageSettings(image_info,*image);
2752           flags=ParseGeometry(argv[1],&geometry_info);
2753           if ((flags & SigmaValue) == 0)
2754             geometry_info.sigma=1.0;
2755           new_image=MotionBlurImage(*image,geometry_info.rho,
2756             geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2757             exception);
2758           break;
2759         }
2760       break;
2761     }
2762     case 'n':
2763     {
2764       if (LocaleCompare("negate",option) == 0)
2765         {
2766           (void) SyncImageSettings(image_info,*image);
2767           (void) NegateImage(*image,*argv[0] == '+' ? MagickTrue :
2768             MagickFalse,exception);
2769           break;
2770         }
2771       if (LocaleCompare("noise",option) == 0)
2772         {
2773           (void) SyncImageSettings(image_info,*image);
2774           if (*argv[0] == '-')
2775             {
2776               flags=ParseGeometry(argv[1],&geometry_info);
2777               if ((flags & SigmaValue) == 0)
2778                 geometry_info.sigma=geometry_info.rho;
2779               new_image=StatisticImage(*image,NonpeakStatistic,(size_t)
2780                 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2781             }
2782           else
2783             {
2784               NoiseType
2785                 noise;
2786
2787               noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
2788                 MagickFalse,argv[1]);
2789               new_image=AddNoiseImage(*image,noise,exception);
2790             }
2791           break;
2792         }
2793       if (LocaleCompare("normalize",option) == 0)
2794         {
2795           (void) SyncImageSettings(image_info,*image);
2796           (void) NormalizeImage(*image,exception);
2797           break;
2798         }
2799       break;
2800     }
2801     case 'o':
2802     {
2803       if (LocaleCompare("opaque",option) == 0)
2804         {
2805           PixelInfo
2806             target;
2807
2808           (void) SyncImageSettings(image_info,*image);
2809           (void) QueryColorCompliance(argv[1],AllCompliance,&target,
2810                        exception);
2811           (void) OpaquePaintImage(*image,&target,&fill,*argv[0] == '-' ?
2812             MagickFalse : MagickTrue,exception);
2813           break;
2814         }
2815       if (LocaleCompare("ordered-dither",option) == 0)
2816         {
2817           (void) SyncImageSettings(image_info,*image);
2818           (void) OrderedPosterizeImage(*image,argv[1],exception);
2819           break;
2820         }
2821       break;
2822     }
2823     case 'p':
2824     {
2825       if (LocaleCompare("paint",option) == 0)
2826         {
2827           (void) SyncImageSettings(image_info,*image);
2828           (void) ParseGeometry(argv[1],&geometry_info);
2829           new_image=OilPaintImage(*image,geometry_info.rho,
2830             geometry_info.sigma,exception);
2831           break;
2832         }
2833       if (LocaleCompare("polaroid",option) == 0)
2834         {
2835           double
2836             angle;
2837
2838           RandomInfo
2839             *random_info;
2840
2841           (void) SyncImageSettings(image_info,*image);
2842           random_info=AcquireRandomInfo();
2843           angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2844           random_info=DestroyRandomInfo(random_info);
2845           if (*argv[0] == '-')
2846             {
2847               SetGeometryInfo(&geometry_info);
2848               flags=ParseGeometry(argv[1],&geometry_info);
2849               angle=geometry_info.rho;
2850             }
2851           new_image=PolaroidImage(*image,draw_info,angle,
2852             interpolate_method,exception);
2853           break;
2854         }
2855       if (LocaleCompare("posterize",option) == 0)
2856         {
2857           (void) SyncImageSettings(image_info,*image);
2858           (void) PosterizeImage(*image,StringToUnsignedLong(argv[1]),
2859             quantize_info->dither,exception);
2860           break;
2861         }
2862       if (LocaleCompare("preview",option) == 0)
2863         {
2864           PreviewType
2865             preview_type=UndefinedPreview;
2866
2867           (void) SyncImageSettings(image_info,*image);
2868           if (IfSetOption)
2869             preview_type=(PreviewType) ParseCommandOption(
2870               MagickPreviewOptions,MagickFalse,argv[1]);
2871           new_image=PreviewImage(*image,preview_type,exception);
2872           break;
2873         }
2874       if (LocaleCompare("profile",option) == 0)
2875         {
2876           const char
2877             *name;
2878
2879           const StringInfo
2880             *profile;
2881
2882           Image
2883             *profile_image;
2884
2885           ImageInfo
2886             *profile_info;
2887
2888           (void) SyncImageSettings(image_info,*image);
2889           if (!IfSetOption)
2890             {
2891               (void) ProfileImage(*image,argv[1],(const unsigned char *)
2892                 NULL,0,exception);
2893               break;
2894             }
2895           profile_info=CloneImageInfo(image_info);
2896           profile=GetImageProfile(*image,"iptc");
2897           if (profile != (StringInfo *) NULL)
2898             profile_info->profile=(void *) CloneStringInfo(profile);
2899           profile_image=GetImageCache(profile_info,argv[1],exception);
2900           profile_info=DestroyImageInfo(profile_info);
2901           if (profile_image == (Image *) NULL)
2902             {
2903               StringInfo
2904                 *profile;
2905
2906               profile_info=CloneImageInfo(image_info);
2907               (void) CopyMagickString(profile_info->filename,argv[1],
2908                 MaxTextExtent);
2909               profile=FileToStringInfo(profile_info->filename,~0UL,exception);
2910               if (profile != (StringInfo *) NULL)
2911                 {
2912                   (void) ProfileImage(*image,profile_info->magick,
2913                     GetStringInfoDatum(profile),(size_t)
2914                     GetStringInfoLength(profile),exception);
2915                   profile=DestroyStringInfo(profile);
2916                 }
2917               profile_info=DestroyImageInfo(profile_info);
2918               break;
2919             }
2920           ResetImageProfileIterator(profile_image);
2921           name=GetNextImageProfile(profile_image);
2922           while (name != (const char *) NULL)
2923           {
2924             profile=GetImageProfile(profile_image,name);
2925             if (profile != (StringInfo *) NULL)
2926               (void) ProfileImage(*image,name,GetStringInfoDatum(profile),
2927                 (size_t) GetStringInfoLength(profile),exception);
2928             name=GetNextImageProfile(profile_image);
2929           }
2930           profile_image=DestroyImage(profile_image);
2931           break;
2932         }
2933       break;
2934     }
2935     case 'r':
2936     {
2937       if (LocaleCompare("radial-blur",option) == 0)
2938         {
2939           /*
2940             Radial blur image.
2941           */
2942           (void) SyncImageSettings(image_info,*image);
2943           flags=ParseGeometry(argv[1],&geometry_info);
2944           new_image=RadialBlurImage(*image,geometry_info.rho,
2945             geometry_info.sigma,exception);
2946           break;
2947         }
2948       if (LocaleCompare("raise",option) == 0)
2949         {
2950           /*
2951             Surround image with a raise of solid color.
2952           */
2953           flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
2954           if ((flags & SigmaValue) == 0)
2955             geometry.height=geometry.width;
2956           (void) RaiseImage(*image,&geometry,*argv[0] == '-' ? MagickTrue :
2957             MagickFalse,exception);
2958           break;
2959         }
2960       if (LocaleCompare("random-threshold",option) == 0)
2961         {
2962           /*
2963             Threshold image.
2964           */
2965           (void) SyncImageSettings(image_info,*image);
2966           (void) RandomThresholdImage(*image,argv[1],exception);
2967           break;
2968         }
2969       if (LocaleCompare("recolor",option) == 0)
2970         {
2971           KernelInfo
2972             *kernel;
2973
2974           (void) SyncImageSettings(image_info,*image);
2975           kernel=AcquireKernelInfo(argv[1]);
2976           if (kernel == (KernelInfo *) NULL)
2977             break;
2978           new_image=ColorMatrixImage(*image,kernel,exception);
2979           kernel=DestroyKernelInfo(kernel);
2980           break;
2981         }
2982       if (LocaleCompare("render",option) == 0)
2983         {
2984           (void) SyncImageSettings(image_info,*image);
2985           draw_info->render=(*argv[0] == '+') ? MagickTrue : MagickFalse;
2986           break;
2987         }
2988       if (LocaleCompare("remap",option) == 0)
2989         {
2990           Image
2991             *remap_image;
2992
2993           /*
2994             Transform image colors to match this set of colors.
2995           */
2996           (void) SyncImageSettings(image_info,*image);
2997           if (*argv[0] == '+')
2998             break;
2999           remap_image=GetImageCache(image_info,argv[1],exception);
3000           if (remap_image == (Image *) NULL)
3001             break;
3002           (void) RemapImage(quantize_info,*image,remap_image,exception);
3003           remap_image=DestroyImage(remap_image);
3004           break;
3005         }
3006       if (LocaleCompare("repage",option) == 0)
3007         {
3008           if (*argv[0] == '+')
3009             {
3010               (void) ParseAbsoluteGeometry("0x0+0+0",&(*image)->page);
3011               break;
3012             }
3013           (void) ResetImagePage(*image,argv[1]);
3014           break;
3015         }
3016       if (LocaleCompare("resample",option) == 0)
3017         {
3018           /*
3019             Resample image.
3020           */
3021           (void) SyncImageSettings(image_info,*image);
3022           flags=ParseGeometry(argv[1],&geometry_info);
3023           if ((flags & SigmaValue) == 0)
3024             geometry_info.sigma=geometry_info.rho;
3025           new_image=ResampleImage(*image,geometry_info.rho,
3026             geometry_info.sigma,(*image)->filter,(*image)->blur,exception);
3027           break;
3028         }
3029       if (LocaleCompare("resize",option) == 0)
3030         {
3031           /*
3032             Resize image.
3033           */
3034           (void) SyncImageSettings(image_info,*image);
3035           (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3036           new_image=ResizeImage(*image,geometry.width,geometry.height,
3037             (*image)->filter,(*image)->blur,exception);
3038           break;
3039         }
3040       if (LocaleCompare("roll",option) == 0)
3041         {
3042           /*
3043             Roll image.
3044           */
3045           (void) SyncImageSettings(image_info,*image);
3046           (void) ParsePageGeometry(*image,argv[1],&geometry,exception);
3047           new_image=RollImage(*image,geometry.x,geometry.y,exception);
3048           break;
3049         }
3050       if (LocaleCompare("rotate",option) == 0)
3051         {
3052           char
3053             *geometry;
3054
3055           /*
3056             Check for conditional image rotation.
3057           */
3058           (void) SyncImageSettings(image_info,*image);
3059           if (strchr(argv[1],'>') != (char *) NULL)
3060             if ((*image)->columns <= (*image)->rows)
3061               break;
3062           if (strchr(argv[1],'<') != (char *) NULL)
3063             if ((*image)->columns >= (*image)->rows)
3064               break;
3065           /*
3066             Rotate image.
3067           */
3068           geometry=ConstantString(argv[1]);
3069           (void) SubstituteString(&geometry,">","");
3070           (void) SubstituteString(&geometry,"<","");
3071           (void) ParseGeometry(geometry,&geometry_info);
3072           geometry=DestroyString(geometry);
3073           new_image=RotateImage(*image,geometry_info.rho,exception);
3074           break;
3075         }
3076       break;
3077     }
3078     case 's':
3079     {
3080       if (LocaleCompare("sample",option) == 0)
3081         {
3082           /*
3083             Sample image with pixel replication.
3084           */
3085           (void) SyncImageSettings(image_info,*image);
3086           (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3087           new_image=SampleImage(*image,geometry.width,geometry.height,
3088             exception);
3089           break;
3090         }
3091       if (LocaleCompare("scale",option) == 0)
3092         {
3093           /*
3094             Resize image.
3095           */
3096           (void) SyncImageSettings(image_info,*image);
3097           (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3098           new_image=ScaleImage(*image,geometry.width,geometry.height,
3099             exception);
3100           break;
3101         }
3102       if (LocaleCompare("selective-blur",option) == 0)
3103         {
3104           /*
3105             Selectively blur pixels within a contrast threshold.
3106           */
3107           (void) SyncImageSettings(image_info,*image);
3108           flags=ParseGeometry(argv[1],&geometry_info);
3109           if ((flags & PercentValue) != 0)
3110             geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3111           new_image=SelectiveBlurImage(*image,geometry_info.rho,
3112             geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3113           break;
3114         }
3115       if (LocaleCompare("separate",option) == 0)
3116         {
3117           /*
3118             Break channels into separate images.
3119             WARNING: This can generate multiple images!
3120           */
3121           (void) SyncImageSettings(image_info,*image);
3122           new_image=SeparateImages(*image,exception);
3123           break;
3124         }
3125       if (LocaleCompare("sepia-tone",option) == 0)
3126         {
3127           double
3128             threshold;
3129
3130           /*
3131             Sepia-tone image.
3132           */
3133           (void) SyncImageSettings(image_info,*image);
3134           threshold=SiPrefixToDouble(argv[1],QuantumRange);
3135           new_image=SepiaToneImage(*image,threshold,exception);
3136           break;
3137         }
3138       if (LocaleCompare("segment",option) == 0)
3139         {
3140           /*
3141             Segment image.
3142           */
3143           (void) SyncImageSettings(image_info,*image);
3144           flags=ParseGeometry(argv[1],&geometry_info);
3145           if ((flags & SigmaValue) == 0)
3146             geometry_info.sigma=1.0;
3147           (void) SegmentImage(*image,(*image)->colorspace,
3148             image_info->verbose,geometry_info.rho,geometry_info.sigma,
3149             exception);
3150           break;
3151         }
3152       if (LocaleCompare("set",option) == 0)
3153         {
3154           char
3155             *value;
3156
3157           if (*argv[0] == '+')
3158             {
3159               if (LocaleNCompare(argv[1],"registry:",9) == 0)
3160                 (void) DeleteImageRegistry(argv[1]+9);
3161               else
3162                 if (LocaleNCompare(argv[1],"argv[0]:",7) == 0)
3163                   {
3164                     (void) DeleteImageOption(image_info,argv[1]+7);
3165                     (void) DeleteImageArtifact(*image,argv[1]+7);
3166                   }
3167                 else
3168                   (void) DeleteImageProperty(*image,argv[1]);
3169               break;
3170             }
3171           value=InterpretImageProperties(image_info,*image,argv[2],
3172             exception);
3173           if (value == (char *) NULL)
3174             break;
3175           if (LocaleNCompare(argv[1],"registry:",9) == 0)
3176             (void) SetImageRegistry(StringRegistryType,argv[1]+9,value,
3177               exception);
3178           else
3179             if (LocaleNCompare(argv[1],"option:",7) == 0)
3180               {
3181                 (void) SetImageOption(image_info,argv[1]+7,value);
3182                 (void) SetImageArtifact(*image,argv[1]+7,value);
3183               }
3184             else
3185               (void) SetImageProperty(*image,argv[1],value,exception);
3186           value=DestroyString(value);
3187           break;
3188         }
3189       if (LocaleCompare("shade",option) == 0)
3190         {
3191           /*
3192             Shade image.
3193           */
3194           (void) SyncImageSettings(image_info,*image);
3195           flags=ParseGeometry(argv[1],&geometry_info);
3196           if ((flags & SigmaValue) == 0)
3197             geometry_info.sigma=1.0;
3198           new_image=ShadeImage(*image,(*argv[0] == '-') ? MagickTrue :
3199             MagickFalse,geometry_info.rho,geometry_info.sigma,exception);
3200           break;
3201         }
3202       if (LocaleCompare("shadow",option) == 0)
3203         {
3204           /*
3205             Shadow image.
3206           */
3207           (void) SyncImageSettings(image_info,*image);
3208           flags=ParseGeometry(argv[1],&geometry_info);
3209           if ((flags & SigmaValue) == 0)
3210             geometry_info.sigma=1.0;
3211           if ((flags & XiValue) == 0)
3212             geometry_info.xi=4.0;
3213           if ((flags & PsiValue) == 0)
3214             geometry_info.psi=4.0;
3215           new_image=ShadowImage(*image,geometry_info.rho,
3216             geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3217             ceil(geometry_info.psi-0.5),exception);
3218           break;
3219         }
3220       if (LocaleCompare("sharpen",option) == 0)
3221         {
3222           /*
3223             Sharpen image.
3224           */
3225           (void) SyncImageSettings(image_info,*image);
3226           flags=ParseGeometry(argv[1],&geometry_info);
3227           if ((flags & SigmaValue) == 0)
3228             geometry_info.sigma=1.0;
3229           if ((flags & XiValue) == 0)
3230             geometry_info.xi=0.0;
3231           new_image=SharpenImage(*image,geometry_info.rho,
3232             geometry_info.sigma,geometry_info.xi,exception);
3233           break;
3234         }
3235       if (LocaleCompare("shave",option) == 0)
3236         {
3237           /*
3238             Shave the image edges.
3239           */
3240           (void) SyncImageSettings(image_info,*image);
3241           flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
3242           new_image=ShaveImage(*image,&geometry,exception);
3243           break;
3244         }
3245       if (LocaleCompare("shear",option) == 0)
3246         {
3247           /*
3248             Shear image.
3249           */
3250           (void) SyncImageSettings(image_info,*image);
3251           flags=ParseGeometry(argv[1],&geometry_info);
3252           if ((flags & SigmaValue) == 0)
3253             geometry_info.sigma=geometry_info.rho;
3254           new_image=ShearImage(*image,geometry_info.rho,
3255             geometry_info.sigma,exception);
3256           break;
3257         }
3258       if (LocaleCompare("sigmoidal-contrast",option) == 0)
3259         {
3260           /*
3261             Sigmoidal non-linearity contrast control.
3262           */
3263           (void) SyncImageSettings(image_info,*image);
3264           flags=ParseGeometry(argv[1],&geometry_info);
3265           if ((flags & SigmaValue) == 0)
3266             geometry_info.sigma=(double) QuantumRange/2.0;
3267           if ((flags & PercentValue) != 0)
3268             geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3269               100.0;
3270           (void) SigmoidalContrastImage(*image,(*argv[0] == '-') ?
3271             MagickTrue : MagickFalse,geometry_info.rho,geometry_info.sigma,
3272             exception);
3273           break;
3274         }
3275       if (LocaleCompare("sketch",option) == 0)
3276         {
3277           /*
3278             Sketch image.
3279           */
3280           (void) SyncImageSettings(image_info,*image);
3281           flags=ParseGeometry(argv[1],&geometry_info);
3282           if ((flags & SigmaValue) == 0)
3283             geometry_info.sigma=1.0;
3284           new_image=SketchImage(*image,geometry_info.rho,
3285             geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3286           break;
3287         }
3288       if (LocaleCompare("solarize",option) == 0)
3289         {
3290           double
3291             threshold;
3292
3293           (void) SyncImageSettings(image_info,*image);
3294           threshold=SiPrefixToDouble(argv[1],QuantumRange);
3295           (void) SolarizeImage(*image,threshold,exception);
3296           break;
3297         }
3298       if (LocaleCompare("sparse-color",option) == 0)
3299         {
3300           SparseColorMethod
3301             method;
3302
3303           char
3304             *arguments;
3305
3306           /*
3307             Sparse Color Interpolated Gradient
3308           */
3309           (void) SyncImageSettings(image_info,*image);
3310           method=(SparseColorMethod) ParseCommandOption(
3311             MagickSparseColorOptions,MagickFalse,argv[1]);
3312           arguments=InterpretImageProperties(image_info,*image,argv[2],
3313             exception);
3314           if (arguments == (char *) NULL)
3315             break;
3316           new_image=SparseColorOption(*image,method,arguments,
3317             argv[0][0] == '+' ? MagickTrue : MagickFalse,exception);
3318           arguments=DestroyString(arguments);
3319           break;
3320         }
3321       if (LocaleCompare("splice",option) == 0)
3322         {
3323           /*
3324             Splice a solid color into the image.
3325           */
3326           (void) SyncImageSettings(image_info,*image);
3327           (void) ParseGravityGeometry(*image,argv[1],&geometry,exception);
3328           new_image=SpliceImage(*image,&geometry,exception);
3329           break;
3330         }
3331       if (LocaleCompare("spread",option) == 0)
3332         {
3333           /*
3334             Spread an image.
3335           */
3336           (void) SyncImageSettings(image_info,*image);
3337           (void) ParseGeometry(argv[1],&geometry_info);
3338           new_image=SpreadImage(*image,geometry_info.rho,
3339             interpolate_method,exception);
3340           break;
3341         }
3342       if (LocaleCompare("statistic",option) == 0)
3343         {
3344           StatisticType
3345             type;
3346
3347           (void) SyncImageSettings(image_info,*image);
3348           type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
3349             MagickFalse,argv[1]);
3350           (void) ParseGeometry(argv[2],&geometry_info);
3351           new_image=StatisticImage(*image,type,(size_t) geometry_info.rho,
3352             (size_t) geometry_info.sigma,exception);
3353           break;
3354         }
3355       if (LocaleCompare("stretch",option) == 0)
3356         {
3357           if (*argv[0] == '+')
3358             {
3359               draw_info->stretch=UndefinedStretch;
3360               break;
3361             }
3362           draw_info->stretch=(StretchType) ParseCommandOption(
3363             MagickStretchOptions,MagickFalse,argv[1]);
3364           break;
3365         }
3366       if (LocaleCompare("strip",option) == 0)
3367         {
3368           /*
3369             Strip image of profiles and comments.
3370           */
3371           (void) SyncImageSettings(image_info,*image);
3372           (void) StripImage(*image,exception);
3373           break;
3374         }
3375       if (LocaleCompare("stroke",option) == 0)
3376         {
3377           ExceptionInfo
3378             *sans;
3379
3380           if (*argv[0] == '+')
3381             {
3382               (void) QueryColorCompliance("none",AllCompliance,&draw_info->stroke,
3383                 exception);
3384               if (draw_info->stroke_pattern != (Image *) NULL)
3385                 draw_info->stroke_pattern=DestroyImage(
3386                   draw_info->stroke_pattern);
3387               break;
3388             }
3389           sans=AcquireExceptionInfo();
3390           status=QueryColorCompliance(argv[1],AllCompliance,&draw_info->stroke,sans);
3391           sans=DestroyExceptionInfo(sans);
3392           if (status == MagickFalse)
3393             draw_info->stroke_pattern=GetImageCache(image_info,argv[1],
3394               exception);
3395           break;
3396         }
3397       if (LocaleCompare("strokewidth",option) == 0)
3398         {
3399           draw_info->stroke_width=InterpretLocaleValue(argv[1],
3400             (char **) NULL);
3401           break;
3402         }
3403       if (LocaleCompare("style",option) == 0)
3404         {
3405           if (*argv[0] == '+')
3406             {
3407               draw_info->style=UndefinedStyle;
3408               break;
3409             }
3410           draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
3411             MagickFalse,argv[1]);
3412           break;
3413         }
3414       if (LocaleCompare("swirl",option) == 0)
3415         {
3416           /*
3417             Swirl image.
3418           */
3419           (void) SyncImageSettings(image_info,*image);
3420           (void) ParseGeometry(argv[1],&geometry_info);
3421           new_image=SwirlImage(*image,geometry_info.rho,
3422             interpolate_method,exception);
3423           break;
3424         }
3425       break;
3426     }
3427     case 't':
3428     {
3429       if (LocaleCompare("threshold",option) == 0)
3430         {
3431           double
3432             threshold;
3433
3434           /*
3435             Threshold image.
3436           */
3437           (void) SyncImageSettings(image_info,*image);
3438           if (*argv[0] == '+')
3439             threshold=(double) QuantumRange/2;
3440           else
3441             threshold=SiPrefixToDouble(argv[1],QuantumRange);
3442           (void) BilevelImage(*image,threshold,exception);
3443           break;
3444         }
3445       if (LocaleCompare("thumbnail",option) == 0)
3446         {
3447           /*
3448             Thumbnail image.
3449           */
3450           (void) SyncImageSettings(image_info,*image);
3451           (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3452           new_image=ThumbnailImage(*image,geometry.width,geometry.height,
3453             exception);
3454           break;
3455         }
3456       if (LocaleCompare("tint",option) == 0)
3457         {
3458           /*
3459             Tint the image.
3460           */
3461           (void) SyncImageSettings(image_info,*image);
3462           new_image=TintImage(*image,argv[1],&fill,exception);
3463           break;
3464         }
3465       if (LocaleCompare("transform",option) == 0)
3466         {
3467           /*
3468             Affine transform image.
3469           */
3470           (void) SyncImageSettings(image_info,*image);
3471           new_image=AffineTransformImage(*image,&draw_info->affine,
3472             exception);
3473           break;
3474         }
3475       if (LocaleCompare("transparent",option) == 0)
3476         {
3477           PixelInfo
3478             target;
3479
3480           (void) SyncImageSettings(image_info,*image);
3481           (void) QueryColorCompliance(argv[1],AllCompliance,&target,
3482                        exception);
3483           (void) TransparentPaintImage(*image,&target,(Quantum)
3484             TransparentAlpha,*argv[0] == '-' ? MagickFalse : MagickTrue,
3485             exception);
3486           break;
3487         }
3488       if (LocaleCompare("transpose",option) == 0)
3489         {
3490           /*
3491             Transpose image scanlines.
3492           */
3493           (void) SyncImageSettings(image_info,*image);
3494           new_image=TransposeImage(*image,exception);
3495           break;
3496         }
3497       if (LocaleCompare("transverse",option) == 0)
3498         {
3499           /*
3500             Transverse image scanlines.
3501           */
3502           (void) SyncImageSettings(image_info,*image);
3503           new_image=TransverseImage(*image,exception);
3504           break;
3505         }
3506       if (LocaleCompare("treedepth",option) == 0)
3507         {
3508           quantize_info->tree_depth=StringToUnsignedLong(argv[1]);
3509           break;
3510         }
3511       if (LocaleCompare("trim",option) == 0)
3512         {
3513           /*
3514             Trim image.
3515           */
3516           (void) SyncImageSettings(image_info,*image);
3517           new_image=TrimImage(*image,exception);
3518           break;
3519         }
3520       if (LocaleCompare("type",option) == 0)
3521         {
3522           ImageType
3523             type;
3524
3525           (void) SyncImageSettings(image_info,*image);
3526           if (*argv[0] == '+')
3527             type=UndefinedType;
3528           else
3529             type=(ImageType) ParseCommandOption(MagickTypeOptions,MagickFalse,
3530               argv[1]);
3531           (*image)->type=UndefinedType;
3532           (void) SetImageType(*image,type,exception);
3533           break;
3534         }
3535       break;
3536     }
3537     case 'u':
3538     {
3539       if (LocaleCompare("undercolor",option) == 0)
3540         {
3541           (void) QueryColorCompliance(argv[1],AllCompliance,&draw_info->undercolor,
3542             exception);
3543           break;
3544         }
3545       if (LocaleCompare("unique",option) == 0)
3546         {
3547           if (*argv[0] == '+')
3548             {
3549               (void) DeleteImageArtifact(*image,"identify:unique-colors");
3550               break;
3551             }
3552           (void) SetImageArtifact(*image,"identify:unique-colors","true");
3553           (void) SetImageArtifact(*image,"verbose","true");
3554           break;
3555         }
3556       if (LocaleCompare("unique-colors",option) == 0)
3557         {
3558           /*
3559             Unique image colors.
3560           */
3561           (void) SyncImageSettings(image_info,*image);
3562           new_image=UniqueImageColors(*image,exception);
3563           break;
3564         }
3565       if (LocaleCompare("unsharp",option) == 0)
3566         {
3567           /*
3568             Unsharp mask image.
3569           */
3570           (void) SyncImageSettings(image_info,*image);
3571           flags=ParseGeometry(argv[1],&geometry_info);
3572           if ((flags & SigmaValue) == 0)
3573             geometry_info.sigma=1.0;
3574           if ((flags & XiValue) == 0)
3575             geometry_info.xi=1.0;
3576           if ((flags & PsiValue) == 0)
3577             geometry_info.psi=0.05;
3578           new_image=UnsharpMaskImage(*image,geometry_info.rho,
3579             geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3580           break;
3581         }
3582       break;
3583     }
3584     case 'v':
3585     {
3586       if (LocaleCompare("verbose",option) == 0)
3587         {
3588           (void) SetImageArtifact(*image,option,
3589             *argv[0] == '+' ? "false" : "true");
3590           break;
3591         }
3592       if (LocaleCompare("vignette",option) == 0)
3593         {
3594           /*
3595             Vignette image.
3596           */
3597           (void) SyncImageSettings(image_info,*image);
3598           flags=ParseGeometry(argv[1],&geometry_info);
3599           if ((flags & SigmaValue) == 0)
3600             geometry_info.sigma=1.0;
3601           if ((flags & XiValue) == 0)
3602             geometry_info.xi=0.1*(*image)->columns;
3603           if ((flags & PsiValue) == 0)
3604             geometry_info.psi=0.1*(*image)->rows;
3605           new_image=VignetteImage(*image,geometry_info.rho,
3606             geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3607             ceil(geometry_info.psi-0.5),exception);
3608           break;
3609         }
3610       if (LocaleCompare("virtual-pixel",option) == 0)
3611         {
3612           if (*argv[0] == '+')
3613             {
3614               (void) SetImageVirtualPixelMethod(*image,
3615                 UndefinedVirtualPixelMethod);
3616               break;
3617             }
3618           (void) SetImageVirtualPixelMethod(*image,(VirtualPixelMethod)
3619             ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
3620             argv[1]));
3621           break;
3622         }
3623       break;
3624     }
3625     case 'w':
3626     {
3627       if (LocaleCompare("wave",option) == 0)
3628         {
3629           /*
3630             Wave image.
3631           */
3632           (void) SyncImageSettings(image_info,*image);
3633           flags=ParseGeometry(argv[1],&geometry_info);
3634           if ((flags & SigmaValue) == 0)
3635             geometry_info.sigma=1.0;
3636           new_image=WaveImage(*image,geometry_info.rho,
3637             geometry_info.sigma,interpolate_method,exception);
3638           break;
3639         }
3640       if (LocaleCompare("weight",option) == 0)
3641         {
3642           draw_info->weight=StringToUnsignedLong(argv[1]);
3643           if (LocaleCompare(argv[1],"all") == 0)
3644             draw_info->weight=0;
3645           if (LocaleCompare(argv[1],"bold") == 0)
3646             draw_info->weight=700;
3647           if (LocaleCompare(argv[1],"bolder") == 0)
3648             if (draw_info->weight <= 800)
3649               draw_info->weight+=100;
3650           if (LocaleCompare(argv[1],"lighter") == 0)
3651             if (draw_info->weight >= 100)
3652               draw_info->weight-=100;
3653           if (LocaleCompare(argv[1],"normal") == 0)
3654             draw_info->weight=400;
3655           break;
3656         }
3657       if (LocaleCompare("white-threshold",option) == 0)
3658         {
3659           (void) SyncImageSettings(image_info,*image);
3660           (void) WhiteThresholdImage(*image,argv[1],exception);
3661           break;
3662         }
3663       break;
3664     }
3665     default:
3666       break;
3667   }
3668   /*
3669      Replace current image with any image that was generated
3670   */
3671   if (new_image != (Image *) NULL)
3672     ReplaceImageInListReturnLast(image,new_image);
3673
3674   /*
3675     Free resources.
3676   */
3677   quantize_info=DestroyQuantizeInfo(quantize_info);
3678   draw_info=DestroyDrawInfo(draw_info);
3679   status=(MagickStatusType) (exception->severity == UndefinedException ? 1 : 0);
3680   return(status == 0 ? MagickFalse : MagickTrue);
3681 }
3682 \f
3683 /*
3684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3685 %                                                                             %
3686 %                                                                             %
3687 %                                                                             %
3688 +     S e q u e n c e O p e r a t i o n I m a g e s                           %
3689 %                                                                             %
3690 %                                                                             %
3691 %                                                                             %
3692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3693 %
3694 %  SequenceOperationImages() applies a single operation that apply to the
3695 %  entire image list (e.g. -append, -layers, -coalesce, etc.).
3696 %
3697 %  The format of the MogrifyImage method is:
3698 %
3699 %    MagickBooleanType SequenceOperationImages(ImageInfo *image_info,
3700 %        const int argc, const char **argv,Image **images,
3701 %        ExceptionInfo *exception)
3702 %
3703 %  A description of each parameter follows:
3704 %
3705 %    o image_info: the image info..
3706 %
3707 %    o argc: Specifies a pointer to an integer describing the number of
3708 %      elements in the argument vector.
3709 %
3710 %    o argv: Specifies a pointer to a text array containing the command line
3711 %      arguments.
3712 %
3713 %    o images: pointer to pointer of the first image in image list.
3714 %
3715 %    o exception: return any errors or warnings in this structure.
3716 %
3717 */
3718 WandExport MagickBooleanType SequenceOperationImages(ImageInfo *image_info,
3719   const int argc,const char **argv,Image **images,ExceptionInfo *exception)
3720 {
3721
3722   MagickStatusType
3723     status;
3724
3725   QuantizeInfo
3726     *quantize_info;
3727
3728   assert(image_info != (ImageInfo *) NULL);
3729   assert(image_info->signature == MagickSignature);
3730   assert(images != (Image **) NULL);
3731   assert((*images)->previous == (Image *) NULL);
3732   assert((*images)->signature == MagickSignature);
3733   if ((*images)->debug != MagickFalse)
3734     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3735       (*images)->filename);
3736   if ((argc <= 0) || (*argv == (char *) NULL))
3737     return(MagickTrue);
3738   status=MagickTrue;
3739
3740   switch (*(argv[0]+1))
3741   {
3742     case 'a':
3743     {
3744       if (LocaleCompare("affinity",argv[0]+1) == 0)
3745         {
3746           (void) SyncImagesSettings(image_info,*images);
3747           if (*argv[0] == '+')
3748             {
3749               (void) RemapImages(quantize_info,*images,(Image *) NULL,
3750                 exception);
3751               break;
3752             }
3753           break;
3754         }
3755       if (LocaleCompare("append",argv[0]+1) == 0)
3756         {
3757           Image
3758             *append_image;
3759
3760           (void) SyncImagesSettings(image_info,*images);
3761           append_image=AppendImages(*images,*argv[0] == '-' ? MagickTrue :
3762             MagickFalse,exception);
3763           if (append_image == (Image *) NULL)
3764             {
3765               status=MagickFalse;
3766               break;
3767             }
3768           *images=DestroyImageList(*images);
3769           *images=append_image;
3770           break;
3771         }
3772       if (LocaleCompare("average",argv[0]+1) == 0)
3773         {
3774           Image
3775             *average_image;
3776
3777           /*
3778             Average an image sequence (deprecated).
3779           */
3780           (void) SyncImagesSettings(image_info,*images);
3781           average_image=EvaluateImages(*images,MeanEvaluateOperator,
3782             exception);
3783           if (average_image == (Image *) NULL)
3784             {
3785               status=MagickFalse;
3786               break;
3787             }
3788           *images=DestroyImageList(*images);
3789           *images=average_image;
3790           break;
3791         }
3792       break;
3793     }
3794     case 'c':
3795     {
3796       if (LocaleCompare("channel",argv[0]+1) == 0)
3797         {
3798           ChannelType
3799             channel;
3800
3801           if (*argv[0] == '+')
3802             {
3803               channel=DefaultChannels;
3804               break;
3805             }
3806           channel=(ChannelType) ParseChannelOption(argv[1]);
3807           SetPixelChannelMap(*images,channel);
3808           break;
3809         }
3810       if (LocaleCompare("clut",argv[0]+1) == 0)
3811         {
3812           Image
3813             *clut_image,
3814             *image;
3815
3816           (void) SyncImagesSettings(image_info,*images);
3817           image=RemoveFirstImageFromList(images);
3818           clut_image=RemoveFirstImageFromList(images);
3819           if (clut_image == (Image *) NULL)
3820             {
3821               status=MagickFalse;
3822               break;
3823             }
3824           (void) ClutImage(image,clut_image,interpolate_method,exception);
3825           clut_image=DestroyImage(clut_image);
3826           *images=DestroyImageList(*images);
3827           *images=image;
3828           break;
3829         }
3830       if (LocaleCompare("coalesce",argv[0]+1) == 0)
3831         {
3832           Image
3833             *coalesce_image;
3834
3835           (void) SyncImagesSettings(image_info,*images);
3836           coalesce_image=CoalesceImages(*images,exception);
3837           if (coalesce_image == (Image *) NULL)
3838             {
3839               status=MagickFalse;
3840               break;
3841             }
3842           *images=DestroyImageList(*images);
3843           *images=coalesce_image;
3844           break;
3845         }
3846       if (LocaleCompare("combine",argv[0]+1) == 0)
3847         {
3848           Image
3849             *combine_image;
3850
3851           (void) SyncImagesSettings(image_info,*images);
3852           combine_image=CombineImages(*images,exception);
3853           if (combine_image == (Image *) NULL)
3854             {
3855               status=MagickFalse;
3856               break;
3857             }
3858           *images=DestroyImageList(*images);
3859           *images=combine_image;
3860           break;
3861         }
3862       if (LocaleCompare("composite",argv[0]+1) == 0)
3863         {
3864           Image
3865             *mask_image,
3866             *composite_image,
3867             *image;
3868
3869           RectangleInfo
3870             geometry;
3871
3872           ComposeOperator
3873             compose;
3874
3875           const char*
3876             value;
3877
3878           value=GetImageOption(image_info,"compose");
3879           if (value != (const char *) NULL)
3880             compose=(CompositeOperator) ParseCommandOption(
3881                  MagickComposeOptions,MagickFalse,value);
3882           else
3883             compose=OverCompositeOp;  /* use Over not image->compose */
3884
3885           const char*
3886             value=GetImageOption(image_info,"compose");
3887
3888            if (value != (const char *) NULL)
3889              compose=(CompositeOperator) ParseCommandOption(
3890                   MagickComposeOptions,MagickFalse,value);
3891            else
3892              compose=OverCompositeOp;  /* use Over not image->compose */
3893
3894
3895           (void) SyncImagesSettings(image_info,*images);
3896           image=RemoveFirstImageFromList(images);
3897           composite_image=RemoveFirstImageFromList(images);
3898           if (composite_image == (Image *) NULL)
3899             {
3900               status=MagickFalse;
3901               break;
3902             }
3903           (void) TransformImage(&composite_image,(char *) NULL,
3904             composite_image->geometry,exception);
3905           SetGeometry(composite_image,&geometry);
3906           (void) ParseAbsoluteGeometry(composite_image->geometry,&geometry);
3907           GravityAdjustGeometry(image->columns,image->rows,image->gravity,
3908             &geometry);
3909           mask_image=RemoveFirstImageFromList(images);
3910           if (mask_image != (Image *) NULL)
3911             {
3912               if ((compose == DisplaceCompositeOp) ||
3913                   (compose == DistortCompositeOp))
3914                 {
3915                   /*
3916                     Merge Y displacement into X displacement image.
3917                   */
3918                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
3919                     mask_image,0,0,exception);
3920                   mask_image=DestroyImage(mask_image);
3921                 }
3922               else
3923                 {
3924                   /*
3925                     Set a blending mask for the composition.
3926                     Posible error, what if image->mask already set.
3927                   */
3928                   image->mask=mask_image;
3929                   (void) NegateImage(image->mask,MagickFalse,exception);
3930                 }
3931             }
3932           (void) CompositeImage(image,compose,composite_image,
3933             geometry.x,geometry.y,exception);
3934           if (mask_image != (Image *) NULL)
3935             mask_image=image->mask=DestroyImage(image->mask);
3936           composite_image=DestroyImage(composite_image);
3937           *images=DestroyImageList(*images);
3938           *images=image;
3939           break;
3940         }
3941       break;
3942     }
3943     case 'd':
3944     {
3945       if (LocaleCompare("deconstruct",argv[0]+1) == 0)
3946         {
3947           Image
3948             *deconstruct_image;
3949
3950           (void) SyncImagesSettings(image_info,*images);
3951           deconstruct_image=CompareImagesLayers(*images,CompareAnyLayer,
3952             exception);
3953           if (deconstruct_image == (Image *) NULL)
3954             {
3955               status=MagickFalse;
3956               break;
3957             }
3958           *images=DestroyImageList(*images);
3959           *images=deconstruct_image;
3960           break;
3961         }
3962       if (LocaleCompare("delete",argv[0]+1) == 0)
3963         {
3964           if (*argv[0] == '+')
3965             DeleteImages(images,"-1",exception);
3966           else
3967             DeleteImages(images,argv[1],exception);
3968           break;
3969         }
3970       if (LocaleCompare("dither",argv[0]+1) == 0)
3971         {
3972           if (*argv[0] == '+')
3973             {
3974               quantize_info->dither=MagickFalse;
3975               break;
3976             }
3977           quantize_info->dither=MagickTrue;
3978           quantize_info->dither_method=(DitherMethod) ParseCommandOption(
3979             MagickDitherOptions,MagickFalse,argv[1]);
3980           break;
3981         }
3982       if (LocaleCompare("duplicate",argv[0]+1) == 0)
3983         {
3984           Image
3985             *duplicate_images;
3986
3987           if (*argv[0] == '+')
3988             duplicate_images=DuplicateImages(*images,1,"-1",exception);
3989           else
3990             {
3991               const char
3992                 *p;
3993
3994               size_t
3995                 number_duplicates;
3996
3997               number_duplicates=(size_t) StringToLong(argv[1]);
3998               p=strchr(argv[1],',');
3999               if (p == (const char *) NULL)
4000                 duplicate_images=DuplicateImages(*images,number_duplicates,
4001                   "-1",exception);
4002               else
4003                 duplicate_images=DuplicateImages(*images,number_duplicates,p,
4004                   exception);
4005             }
4006           AppendImageToList(images, duplicate_images);
4007           (void) SyncImagesSettings(image_info,*images);
4008           break;
4009         }
4010       break;
4011     }
4012     case 'e':
4013     {
4014       if (LocaleCompare("evaluate-sequence",argv[0]+1) == 0)
4015         {
4016           Image
4017             *evaluate_image;
4018
4019           MagickEvaluateOperator
4020             op;
4021
4022           (void) SyncImageSettings(image_info,*images);
4023           op=(MagickEvaluateOperator) ParseCommandOption(
4024             MagickEvaluateOptions,MagickFalse,argv[1]);
4025           evaluate_image=EvaluateImages(*images,op,exception);
4026           if (evaluate_image == (Image *) NULL)
4027             {
4028               status=MagickFalse;
4029               break;
4030             }
4031           *images=DestroyImageList(*images);
4032           *images=evaluate_image;
4033           break;
4034         }
4035       break;
4036     }
4037     case 'f':
4038     {
4039       if (LocaleCompare("fft",argv[0]+1) == 0)
4040         {
4041           Image
4042             *fourier_image;
4043
4044           /*
4045             Implements the discrete Fourier transform (DFT).
4046           */
4047           (void) SyncImageSettings(image_info,*images);
4048           fourier_image=ForwardFourierTransformImage(*images,*argv[0] == '-' ?
4049             MagickTrue : MagickFalse,exception);
4050           if (fourier_image == (Image *) NULL)
4051             break;
4052           *images=DestroyImage(*images);
4053           *images=fourier_image;
4054           break;
4055         }
4056       if (LocaleCompare("flatten",argv[0]+1) == 0)
4057         {
4058           Image
4059             *flatten_image;
4060
4061           (void) SyncImagesSettings(image_info,*images);
4062           flatten_image=MergeImageLayers(*images,FlattenLayer,exception);
4063           if (flatten_image == (Image *) NULL)
4064             break;
4065           *images=DestroyImageList(*images);
4066           *images=flatten_image;
4067           break;
4068         }
4069       if (LocaleCompare("fx",argv[0]+1) == 0)
4070         {
4071           Image
4072             *fx_image;
4073
4074           (void) SyncImagesSettings(image_info,*images);
4075           fx_image=FxImage(*images,argv[1],exception);
4076           if (fx_image == (Image *) NULL)
4077             {
4078               status=MagickFalse;
4079               break;
4080             }
4081           *images=DestroyImageList(*images);
4082           *images=fx_image;
4083           break;
4084         }
4085       break;
4086     }
4087     case 'h':
4088     {
4089       if (LocaleCompare("hald-clut",argv[0]+1) == 0)
4090         {
4091           Image
4092             *hald_image,
4093             *image;
4094
4095           (void) SyncImagesSettings(image_info,*images);
4096           image=RemoveFirstImageFromList(images);
4097           hald_image=RemoveFirstImageFromList(images);
4098           if (hald_image == (Image *) NULL)
4099             {
4100               status=MagickFalse;
4101               break;
4102             }
4103           (void) HaldClutImage(image,hald_image,exception);
4104           hald_image=DestroyImage(hald_image);
4105           if (*images != (Image *) NULL)
4106             *images=DestroyImageList(*images);
4107           *images=image;
4108           break;
4109         }
4110       break;
4111     }
4112     case 'i':
4113     {
4114       if (LocaleCompare("ift",argv[0]+1) == 0)
4115         {
4116           Image
4117             *fourier_image,
4118             *magnitude_image,
4119             *phase_image;
4120
4121           /*
4122             Implements the inverse fourier discrete Fourier transform (DFT).
4123           */
4124           (void) SyncImagesSettings(image_info,*images);
4125           magnitude_image=RemoveFirstImageFromList(images);
4126           phase_image=RemoveFirstImageFromList(images);
4127           if (phase_image == (Image *) NULL)
4128             {
4129               status=MagickFalse;
4130               break;
4131             }
4132           fourier_image=InverseFourierTransformImage(magnitude_image,
4133             phase_image,*argv[0] == '-' ? MagickTrue : MagickFalse,exception);
4134           if (fourier_image == (Image *) NULL)
4135             break;
4136           if (*images != (Image *) NULL)
4137             *images=DestroyImage(*images);
4138           *images=fourier_image;
4139           break;
4140         }
4141       if (LocaleCompare("insert",argv[0]+1) == 0)
4142         {
4143           Image
4144             *p,
4145             *q;
4146
4147           index=0;
4148           if (*argv[0] != '+')
4149             index=(ssize_t) StringToLong(argv[1]);
4150           p=RemoveLastImageFromList(images);
4151           if (p == (Image *) NULL)
4152             {
4153               (void) ThrowMagickException(exception,GetMagickModule(),
4154                 OptionError,"NoSuchImage","`%s'",argv[1]);
4155               status=MagickFalse;
4156               break;
4157             }
4158           q=p;
4159           if (index == 0)
4160             PrependImageToList(images,q);
4161           else
4162             if (index == (ssize_t) GetImageListLength(*images))
4163               AppendImageToList(images,q);
4164             else
4165               {
4166                  q=GetImageFromList(*images,index-1);
4167                  if (q == (Image *) NULL)
4168                    {
4169                      (void) ThrowMagickException(exception,GetMagickModule(),
4170                        OptionError,"NoSuchImage","`%s'",argv[1]);
4171                      status=MagickFalse;
4172                      break;
4173                    }
4174                 InsertImageInList(&q,p);
4175               }
4176           *images=GetFirstImageInList(q);
4177           break;
4178         }
4179       if (LocaleCompare("interpolate",argv[0]+1) == 0)
4180         {
4181           interpolate_method=(PixelInterpolateMethod) ParseCommandOption(
4182             MagickInterpolateOptions,MagickFalse,argv[1]);
4183           break;
4184         }
4185       break;
4186     }
4187     case 'l':
4188     {
4189       if (LocaleCompare("layers",argv[0]+1) == 0)
4190         {
4191           Image
4192             *layers;
4193
4194           ImageLayerMethod
4195             method;
4196
4197           (void) SyncImagesSettings(image_info,*images);
4198           layers=(Image *) NULL;
4199           method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
4200             MagickFalse,argv[1]);
4201           switch (method)
4202           {
4203             case CoalesceLayer:
4204             {
4205               layers=CoalesceImages(*images,exception);
4206               break;
4207             }
4208             case CompareAnyLayer:
4209             case CompareClearLayer:
4210             case CompareOverlayLayer:
4211             default:
4212             {
4213               layers=CompareImagesLayers(*images,method,exception);
4214               break;
4215             }
4216             case MergeLayer:
4217             case FlattenLayer:
4218             case MosaicLayer:
4219             case TrimBoundsLayer:
4220             {
4221               layers=MergeImageLayers(*images,method,exception);
4222               break;
4223             }
4224             case DisposeLayer:
4225             {
4226               layers=DisposeImages(*images,exception);
4227               break;
4228             }
4229             case OptimizeImageLayer:
4230             {
4231               layers=OptimizeImageLayers(*images,exception);
4232               break;
4233             }
4234             case OptimizePlusLayer:
4235             {
4236               layers=OptimizePlusImageLayers(*images,exception);
4237               break;
4238             }
4239             case OptimizeTransLayer:
4240             {
4241               OptimizeImageTransparency(*images,exception);
4242               break;
4243             }
4244             case RemoveDupsLayer:
4245             {
4246               RemoveDuplicateLayers(images,exception);
4247               break;
4248             }
4249             case RemoveZeroLayer:
4250             {
4251               RemoveZeroDelayLayers(images,exception);
4252               break;
4253             }
4254             case OptimizeLayer:
4255             {
4256               /*
4257                 General Purpose, GIF Animation Optimizer.
4258               */
4259               layers=CoalesceImages(*images,exception);
4260               if (layers == (Image *) NULL)
4261                 {
4262                   status=MagickFalse;
4263                   break;
4264                 }
4265               *images=DestroyImageList(*images);
4266               *images=layers;
4267               layers=OptimizeImageLayers(*images,exception);
4268               if (layers == (Image *) NULL)
4269                 {
4270                   status=MagickFalse;
4271                   break;
4272                 }
4273               *images=DestroyImageList(*images);
4274               *images=layers;
4275               layers=(Image *) NULL;
4276               OptimizeImageTransparency(*images,exception);
4277               (void) RemapImages(quantize_info,*images,(Image *) NULL,
4278                 exception);
4279               break;
4280             }
4281             case CompositeLayer:
4282             {
4283               Image
4284                 *source;
4285
4286               RectangleInfo
4287                 geometry;
4288
4289               ComposeOperator
4290                 compose;
4291
4292               const char*
4293                 value;
4294
4295               value=GetImageOption(image_info,"compose");
4296               if (value != (const char *) NULL)
4297                 compose=(CompositeOperator) ParseCommandOption(
4298                       MagickComposeOptions,MagickFalse,value);
4299               else
4300                 compose=OverCompositeOp;  /* use Over not image->compose */
4301
4302               /*
4303                 Split image sequence at the first 'NULL:' image.
4304               */
4305               source=(*images);
4306               while (source != (Image *) NULL)
4307               {
4308                 source=GetNextImageInList(source);
4309                 if ((source != (Image *) NULL) &&
4310                     (LocaleCompare(source->magick,"NULL") == 0))
4311                   break;
4312               }
4313               if (source != (Image *) NULL)
4314                 {
4315                   if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4316                       (GetNextImageInList(source) == (Image *) NULL))
4317                     source=(Image *) NULL;
4318                   else
4319                     {
4320                       /*
4321                         Separate the two lists, junk the null: image.
4322                       */
4323                       source=SplitImageList(source->previous);
4324                       DeleteImageFromList(&source);
4325                     }
4326                 }
4327               if (source == (Image *) NULL)
4328                 {
4329                   (void) ThrowMagickException(exception,GetMagickModule(),
4330                     OptionError,"MissingNullSeparator","layers Composite");
4331                   status=MagickFalse;
4332                   break;
4333                 }
4334               /*
4335                 Adjust offset with gravity and virtual canvas.
4336               */
4337               SetGeometry(*images,&geometry);
4338               (void) ParseAbsoluteGeometry((*images)->geometry,&geometry);
4339               geometry.width=source->page.width != 0 ?
4340                 source->page.width : source->columns;
4341               geometry.height=source->page.height != 0 ?
4342                source->page.height : source->rows;
4343               GravityAdjustGeometry((*images)->page.width != 0 ?
4344                 (*images)->page.width : (*images)->columns,
4345                 (*images)->page.height != 0 ? (*images)->page.height :
4346                 (*images)->rows,(*images)->gravity,&geometry);
4347
4348               /*
4349                 Compose the two image sequences together
4350               */
4351               CompositeLayers(*images,compose,source,geometry.x,geometry.y,
4352                 exception);
4353               source=DestroyImageList(source);
4354               break;
4355             }
4356           }
4357           if (layers == (Image *) NULL)
4358             break;
4359           *images=DestroyImageList(*images);
4360           *images=layers;
4361           break;
4362         }
4363       break;
4364     }
4365     case 'm':
4366     {
4367       if (LocaleCompare("map",argv[0]+1) == 0)
4368         {
4369           (void) SyncImagesSettings(image_info,*images);
4370           if (*argv[0] == '+')
4371             {
4372               (void) RemapImages(quantize_info,*images,(Image *) NULL,
4373                 exception);
4374               break;
4375             }
4376           break;
4377         }
4378       if (LocaleCompare("maximum",argv[0]+1) == 0)
4379         {
4380           Image
4381             *maximum_image;
4382
4383           /*
4384             Maximum image sequence (deprecated).
4385           */
4386           (void) SyncImagesSettings(image_info,*images);
4387           maximum_image=EvaluateImages(*images,MaxEvaluateOperator,exception);
4388           if (maximum_image == (Image *) NULL)
4389             {
4390               status=MagickFalse;
4391               break;
4392             }
4393           *images=DestroyImageList(*images);
4394           *images=maximum_image;
4395           break;
4396         }
4397       if (LocaleCompare("minimum",argv[0]+1) == 0)
4398         {
4399           Image
4400             *minimum_image;
4401
4402           /*
4403             Minimum image sequence (deprecated).
4404           */
4405           (void) SyncImagesSettings(image_info,*images);
4406           minimum_image=EvaluateImages(*images,MinEvaluateOperator,exception);
4407           if (minimum_image == (Image *) NULL)
4408             {
4409               status=MagickFalse;
4410               break;
4411             }
4412           *images=DestroyImageList(*images);
4413           *images=minimum_image;
4414           break;
4415         }
4416       if (LocaleCompare("morph",argv[0]+1) == 0)
4417         {
4418           Image
4419             *morph_image;
4420
4421           (void) SyncImagesSettings(image_info,*images);
4422           morph_image=MorphImages(*images,StringToUnsignedLong(argv[1]),
4423             exception);
4424           if (morph_image == (Image *) NULL)
4425             {
4426               status=MagickFalse;
4427               break;
4428             }
4429           *images=DestroyImageList(*images);
4430           *images=morph_image;
4431           break;
4432         }
4433       if (LocaleCompare("mosaic",argv[0]+1) == 0)
4434         {
4435           Image
4436             *mosaic_image;
4437
4438           (void) SyncImagesSettings(image_info,*images);
4439           mosaic_image=MergeImageLayers(*images,MosaicLayer,exception);
4440           if (mosaic_image == (Image *) NULL)
4441             {
4442               status=MagickFalse;
4443               break;
4444             }
4445           *images=DestroyImageList(*images);
4446           *images=mosaic_image;
4447           break;
4448         }
4449       break;
4450     }
4451     case 'p':
4452     {
4453       if (LocaleCompare("print",argv[0]+1) == 0)
4454         {
4455           char
4456             *string;
4457
4458           (void) SyncImagesSettings(image_info,*images);
4459           string=InterpretImageProperties(image_info,*images,argv[1],
4460             exception);
4461           if (string == (char *) NULL)
4462             break;
4463           (void) FormatLocaleFile(stdout,"%s",string);
4464           string=DestroyString(string);
4465         }
4466       if (LocaleCompare("process",argv[0]+1) == 0)
4467         {
4468           char
4469             **arguments;
4470
4471           int
4472             j,
4473             number_arguments;
4474
4475           (void) SyncImagesSettings(image_info,*images);
4476           arguments=StringToArgv(argv[1],&number_arguments);
4477           if (arguments == (char **) NULL)
4478             break;
4479           if ((argc > 1) && (strchr(arguments[1],'=') != (char *) NULL))
4480             {
4481               char
4482                 breaker,
4483                 quote,
4484                 *token;
4485
4486               const char
4487                 *arguments;
4488
4489               int
4490                 next,
4491                 status;
4492
4493               size_t
4494                 length;
4495
4496               TokenInfo
4497                 *token_info;
4498
4499               /*
4500                 Support old style syntax, filter="-option arg".
4501               */
4502               length=strlen(argv[1]);
4503               token=(char *) NULL;
4504               if (~length >= (MaxTextExtent-1))
4505                 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4506                   sizeof(*token));
4507               if (token == (char *) NULL)
4508                 break;
4509               next=0;
4510               arguments=argv[1];
4511               token_info=AcquireTokenInfo();
4512               status=Tokenizer(token_info,0,token,length,arguments,"","=",
4513                 "\"",'\0',&breaker,&next,&quote);
4514               token_info=DestroyTokenInfo(token_info);
4515               if (status == 0)
4516                 {
4517                   const char
4518                     *argv;
4519
4520                   argv=(&(arguments[next]));
4521                   (void) InvokeDynamicImageFilter(token,&(*images),1,&argv,
4522                     exception);
4523                 }
4524               token=DestroyString(token);
4525               break;
4526             }
4527           (void) SubstituteString(&arguments[1],"-","");
4528           (void) InvokeDynamicImageFilter(arguments[1],&(*images),
4529             number_arguments-2,(const char **) arguments+2,exception);
4530           for (j=0; j < number_arguments; j++)
4531             arguments[j]=DestroyString(arguments[j]);
4532           arguments=(char **) RelinquishMagickMemory(arguments);
4533           break;
4534         }
4535       break;
4536     }
4537     case 'r':
4538     {
4539       if (LocaleCompare("reverse",argv[0]+1) == 0)
4540         {
4541           ReverseImageList(images);
4542           break;
4543         }
4544       break;
4545     }
4546     case 's':
4547     {
4548       if (LocaleCompare("smush",argv[0]+1) == 0)
4549         {
4550           Image
4551             *smush_image;
4552
4553           ssize_t
4554             offset;
4555
4556           (void) SyncImagesSettings(image_info,*images);
4557           offset=(ssize_t) StringToLong(argv[1]);
4558           smush_image=SmushImages(*images,*argv[0] == '-' ? MagickTrue :
4559             MagickFalse,offset,exception);
4560           if (smush_image == (Image *) NULL)
4561             {
4562               status=MagickFalse;
4563               break;
4564             }
4565           *images=DestroyImageList(*images);
4566           *images=smush_image;
4567           break;
4568         }
4569       if (LocaleCompare("swap",argv[0]+1) == 0)
4570         {
4571           Image
4572             *p,
4573             *q,
4574             *swap;
4575
4576           ssize_t
4577             swap_index;
4578
4579           index=(-1);
4580           swap_index=(-2);
4581           if (*argv[0] != '+')
4582             {
4583               GeometryInfo
4584                 geometry_info;
4585
4586               MagickStatusType
4587                 flags;
4588
4589               swap_index=(-1);
4590               flags=ParseGeometry(argv[1],&geometry_info);
4591               index=(ssize_t) geometry_info.rho;
4592               if ((flags & SigmaValue) != 0)
4593                 swap_index=(ssize_t) geometry_info.sigma;
4594             }
4595           p=GetImageFromList(*images,index);
4596           q=GetImageFromList(*images,swap_index);
4597           if ((p == (Image *) NULL) || (q == (Image *) NULL))
4598             {
4599               (void) ThrowMagickException(exception,GetMagickModule(),
4600                 OptionError,"NoSuchImage","`%s'",(*images)->filename);
4601               status=MagickFalse;
4602               break;
4603             }
4604           if (p == q)
4605             break;
4606           swap=CloneImage(p,0,0,MagickTrue,exception);
4607           ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4608           ReplaceImageInList(&q,swap);
4609           *images=GetFirstImageInList(q);
4610           break;
4611         }
4612       break;
4613     }
4614     case 'w':
4615     {
4616       if (LocaleCompare("write",argv[0]+1) == 0)
4617         {
4618           char
4619             key[MaxTextExtent];
4620
4621           Image
4622             *write_images;
4623
4624           ImageInfo
4625             *write_info;
4626
4627           (void) SyncImagesSettings(image_info,*images);
4628           (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",argv[1]);
4629           (void) DeleteImageRegistry(key);
4630           write_images=(*images);
4631           if (*argv[0] == '+')
4632             write_images=CloneImageList(*images,exception);
4633           write_info=CloneImageInfo(image_info);
4634           status&=WriteImages(write_info,write_images,argv[1],exception);
4635           write_info=DestroyImageInfo(write_info);
4636           if (*argv[0] == '+')
4637             write_images=DestroyImageList(write_images);
4638           break;
4639         }
4640       break;
4641     }
4642     default:
4643       break;
4644   }
4645   quantize_info=DestroyQuantizeInfo(quantize_info);
4646
4647   status=(MagickStatusType) (exception->severity == UndefinedException ? 1 : 0);
4648   return(status != 0 ? MagickTrue : MagickFalse);
4649 }
4650 #endif