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