MagickWand  6.7.7
operation.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %          OOO   PPPP   EEEE  RRRR    AA   TTTTT  III   OOO   N   N           %
00007 %         O   O  P   P  E     R   R  A  A    T     I   O   O  NN  N           %
00008 %         O   O  PPPP   EEE   RRRR   AAAA    T     I   O   O  N N N           %
00009 %         O   O  P      E     R R    A  A    T     I   O   O  N  NN           %
00010 %          OOO   P      EEEE  R  RR  A  A    T    III   OOO   N   N           %
00011 %                                                                             %
00012 %                                                                             %
00013 %                         CLI Magick Option Methods                           %
00014 %                                                                             %
00015 %                              Dragon Computing                               %
00016 %                              Anthony Thyssen                                %
00017 %                               September 2011                                %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 % Apply the given options (settings, and simple, or sequence operations) to
00037 % the given image(s) according to the current "image_info", "draw_info", and
00038 % "quantize_info" settings, stored in a special CLI Image Wand.
00039 %
00040 % The final goal is to allow the execution in a strict one option at a time
00041 % manner that is needed for 'pipelining and file scripting' of options in
00042 % IMv7.
00043 %
00044 % Anthony Thyssen, September 2011
00045 */
00046 
00047 /*
00048   Include declarations.
00049 */
00050 #include "MagickWand/studio.h"
00051 #include "MagickWand/MagickWand.h"
00052 #include "MagickWand/magick-wand-private.h"
00053 #include "MagickWand/wand.h"
00054 #include "MagickWand/wandcli.h"
00055 #include "MagickWand/wandcli-private.h"
00056 #include "MagickWand/operation.h"
00057 #include "MagickCore/monitor-private.h"
00058 #include "MagickCore/thread-private.h"
00059 #include "MagickCore/string-private.h"
00060 
00061 /*
00062   Define declarations.
00063 */
00064 #define USE_WAND_METHODS  0
00065 #define MAX_STACK_DEPTH  32
00066 #define UNDEFINED_COMPRESSION_QUALITY  0UL
00067 
00068 /* FUTURE: why is this default so specific? */
00069 #define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
00070 
00071 /*
00072   Constant declaration. (temporary exports)
00073 */
00074 static const char
00075   BackgroundColor[] = "#fff",  /* white */
00076   BorderColor[] = "#dfdfdf",  /* sRGB gray */
00077   MatteColor[] = "#bdbdbd";  /* slightly darker gray */
00078 
00079 /* For Debugging Geometry Input */
00080 #define ReportGeometry(flags,info) \
00081   (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
00082        flags, info.rho, info.sigma, info.xi, info.psi )
00083 
00084 /*
00085 ** Function to report on the progress of image operations
00086 */
00087 static MagickBooleanType MonitorProgress(const char *text,
00088   const MagickOffsetType offset,const MagickSizeType extent,
00089   void *wand_unused(cli_wandent_data))
00090 {
00091   char
00092     message[MaxTextExtent],
00093     tag[MaxTextExtent];
00094 
00095   const char
00096     *locale_message;
00097 
00098   register char
00099     *p;
00100 
00101   if (extent < 2)
00102     return(MagickTrue);
00103   (void) CopyMagickMemory(tag,text,MaxTextExtent);
00104   p=strrchr(tag,'/');
00105   if (p != (char *) NULL)
00106     *p='\0';
00107   (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
00108   locale_message=GetLocaleMessage(message);
00109   if (locale_message == message)
00110     locale_message=tag;
00111   if (p == (char *) NULL)
00112     (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
00113       locale_message,(long) offset,(unsigned long) extent,(long)
00114       (100L*offset/(extent-1)));
00115   else
00116     (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
00117       locale_message,p+1,(long) offset,(unsigned long) extent,(long)
00118       (100L*offset/(extent-1)));
00119   if (offset == (MagickOffsetType) (extent-1))
00120     (void) FormatLocaleFile(stderr,"\n");
00121   (void) fflush(stderr);
00122   return(MagickTrue);
00123 }
00124 
00125 /*
00126 ** GetImageCache() will read an image into a image cache if not already
00127 ** present then return the image that is in the cache under that filename.
00128 */
00129 static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
00130   ExceptionInfo *exception)
00131 {
00132   char
00133     key[MaxTextExtent];
00134 
00135   ExceptionInfo
00136     *sans_exception;
00137 
00138   Image
00139     *image;
00140 
00141   ImageInfo
00142     *read_info;
00143 
00144   (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
00145   sans_exception=AcquireExceptionInfo();
00146   image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
00147   sans_exception=DestroyExceptionInfo(sans_exception);
00148   if (image != (Image *) NULL)
00149     return(image);
00150   read_info=CloneImageInfo(image_info);
00151   (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
00152   image=ReadImage(read_info,exception);
00153   read_info=DestroyImageInfo(read_info);
00154   if (image != (Image *) NULL)
00155     (void) SetImageRegistry(ImageRegistryType,key,image,exception);
00156   return(image);
00157 }
00158 
00159 /*
00160   SparseColorOption() parse the complex -sparse-color argument into an
00161   an array of floating point values than call SparseColorImage().
00162   Argument is a complex mix of floating-point pixel coodinates, and color
00163   specifications (or direct floating point numbers).  The number of floats
00164   needed to represent a color varies depending on teh current channel
00165   setting.
00166 
00167   This really should be in MagickCore, so that other API's can make use of it.
00168 */
00169 static Image *SparseColorOption(const Image *image,
00170   const SparseColorMethod method,const char *arguments,
00171   ExceptionInfo *exception)
00172 {
00173   char
00174     token[MaxTextExtent];
00175 
00176   const char
00177     *p;
00178 
00179   double
00180     *sparse_arguments;
00181 
00182   Image
00183     *sparse_image;
00184 
00185   PixelInfo
00186     color;
00187 
00188   MagickBooleanType
00189     error;
00190 
00191   register size_t
00192     x;
00193 
00194   size_t
00195     number_arguments,
00196     number_colors;
00197 
00198   assert(image != (Image *) NULL);
00199   assert(image->signature == MagickSignature);
00200   if (IfMagickTrue(image->debug))
00201     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00202   assert(exception != (ExceptionInfo *) NULL);
00203   assert(exception->signature == MagickSignature);
00204   /*
00205     Limit channels according to image
00206     add up number of values needed per color.
00207   */
00208   number_colors=0;
00209   if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
00210     number_colors++;
00211   if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
00212     number_colors++;
00213   if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
00214     number_colors++;
00215   if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
00216       (image->colorspace == CMYKColorspace))
00217     number_colors++;
00218   if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
00219       IfMagickTrue(image->matte))
00220     number_colors++;
00221 
00222   /*
00223     Read string, to determine number of arguments needed,
00224   */
00225   p=arguments;
00226   x=0;
00227   while( *p != '\0' )
00228   {
00229     GetMagickToken(p,&p,token);
00230     if ( token[0] == ',' ) continue;
00231     if ( isalpha((int) token[0]) || token[0] == '#' )
00232       x += number_colors;  /* color argument found */
00233     else
00234       x++;   /* floating point argument */
00235   }
00236   /* control points and color values */
00237   error = IsMagickTrue( x % (2+number_colors) );
00238   number_arguments=x;
00239   if ( IfMagickTrue(error) ) {
00240     (void) ThrowMagickException(exception,GetMagickModule(),
00241                OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
00242                "Invalid number of Arguments");
00243     return( (Image *)NULL);
00244   }
00245 
00246   /* Allocate and fill in the floating point arguments */
00247   sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
00248     sizeof(*sparse_arguments));
00249   if (sparse_arguments == (double *) NULL) {
00250     (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
00251       "MemoryAllocationFailed","%s","SparseColorOption");
00252     return( (Image *)NULL);
00253   }
00254   (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
00255     sizeof(*sparse_arguments));
00256   p=arguments;
00257   x=0;
00258   while( *p != '\0' && x < number_arguments ) {
00259     /* X coordinate */
00260     token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
00261     if ( token[0] == '\0' ) break;
00262     if ( isalpha((int) token[0]) || token[0] == '#' ) {
00263       (void) ThrowMagickException(exception,GetMagickModule(),
00264             OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
00265             "Color found, instead of X-coord");
00266       error = MagickTrue;
00267       break;
00268     }
00269     sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
00270     /* Y coordinate */
00271     token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
00272     if ( token[0] == '\0' ) break;
00273     if ( isalpha((int) token[0]) || token[0] == '#' ) {
00274       (void) ThrowMagickException(exception,GetMagickModule(),
00275             OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
00276             "Color found, instead of Y-coord");
00277       error = MagickTrue;
00278       break;
00279     }
00280     sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
00281     /* color name or function given in string argument */
00282     token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
00283     if ( token[0] == '\0' ) break;
00284     if ( isalpha((int) token[0]) || token[0] == '#' ) {
00285       /* Color string given */
00286       (void) QueryColorCompliance(token,AllCompliance,&color,
00287                 exception);
00288       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
00289         sparse_arguments[x++] = QuantumScale*color.red;
00290       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
00291         sparse_arguments[x++] = QuantumScale*color.green;
00292       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
00293         sparse_arguments[x++] = QuantumScale*color.blue;
00294       if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
00295           (image->colorspace == CMYKColorspace))
00296         sparse_arguments[x++] = QuantumScale*color.black;
00297       if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
00298           IfMagickTrue(image->matte))
00299         sparse_arguments[x++] = QuantumScale*color.alpha;
00300     }
00301     else {
00302       /* Colors given as a set of floating point values - experimental */
00303       /* NB: token contains the first floating point value to use! */
00304       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
00305         {
00306         while ( token[0] == ',' ) GetMagickToken(p,&p,token);
00307         if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
00308           break;
00309         sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
00310         token[0] = ','; /* used this token - get another */
00311       }
00312       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
00313         {
00314         while ( token[0] == ',' ) GetMagickToken(p,&p,token);
00315         if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
00316           break;
00317         sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
00318         token[0] = ','; /* used this token - get another */
00319       }
00320       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
00321         {
00322         while ( token[0] == ',' ) GetMagickToken(p,&p,token);
00323         if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
00324           break;
00325         sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
00326         token[0] = ','; /* used this token - get another */
00327       }
00328       if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
00329           (image->colorspace == CMYKColorspace))
00330         {
00331         while ( token[0] == ',' ) GetMagickToken(p,&p,token);
00332         if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
00333           break;
00334         sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
00335         token[0] = ','; /* used this token - get another */
00336       }
00337       if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
00338           IfMagickTrue(image->matte))
00339         {
00340         while ( token[0] == ',' ) GetMagickToken(p,&p,token);
00341         if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
00342           break;
00343         sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
00344         token[0] = ','; /* used this token - get another */
00345       }
00346     }
00347   }
00348   if ( number_arguments != x && !error ) {
00349     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
00350       "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
00351     sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
00352     return( (Image *)NULL);
00353   }
00354   if ( error )
00355     return( (Image *)NULL);
00356 
00357   /* Call the Sparse Color Interpolation function with the parsed arguments */
00358   sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
00359     exception);
00360   sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
00361   return( sparse_image );
00362 }
00363 
00364 /*
00365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00366 %                                                                             %
00367 %                                                                             %
00368 %                                                                             %
00369 %   C L I S e t t i n g O p t i o n I n f o                                   %
00370 %                                                                             %
00371 %                                                                             %
00372 %                                                                             %
00373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00374 %
00375 %  CLISettingOptionInfo() applies a single settings option into a CLI wand
00376 %  holding the image_info, draw_info, quantize_info structures that will be
00377 %  used when processing the images.
00378 %
00379 %  These options do no require images to be present in the CLI wand for them
00380 %  to be able to be set, in which case they will generally be applied to image
00381 %  that are read in later
00382 %
00383 %  Options handled by this function are listed in CommandOptions[] of
00384 %  "option.c" that is one of "SettingOptionFlags" option flags.
00385 %
00386 %  The format of the CLISettingOptionInfo method is:
00387 %
00388 %    void CLISettingOptionInfo(MagickCLI *cli_wand,
00389 %               const char *option, const char *arg1, const char *arg2)
00390 %
00391 %  A description of each parameter follows:
00392 %
00393 %    o cli_wand: structure holding settings to be applied
00394 %
00395 %    o option: The option string to be set
00396 %
00397 %    o arg1, arg2: optional argument strings to the operation
00398 %        arg2 is currently only used by "-limit"
00399 %
00400 */
00401 WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
00402      const char *option,const char *arg1, const char *arg2)
00403 {
00404   ssize_t
00405     parse;     /* option argument parsing (string to value table lookup) */
00406 
00407   assert(cli_wand != (MagickCLI *) NULL);
00408   assert(cli_wand->signature == WandSignature);
00409   assert(cli_wand->wand.signature == WandSignature);
00410   if (IfMagickTrue(cli_wand->wand.debug))
00411     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
00412 
00413 #define _image_info       (cli_wand->wand.image_info)
00414 #define _exception        (cli_wand->wand.exception)
00415 #define _draw_info        (cli_wand->draw_info)
00416 #define _quantize_info    (cli_wand->quantize_info)
00417 #define IfSetOption       (*option=='-')
00418 #define ArgBoolean        IsMagickTrue(IfSetOption)
00419 #define ArgBooleanNot     IsMagickFalse(IfSetOption)
00420 #define ArgBooleanString  (IfSetOption?"true":"false")
00421 #define ArgOption(def)    (IfSetOption?arg1:(const char *)(def))
00422 
00423   switch (*(option+1))
00424   {
00425     case 'a':
00426     {
00427       if (LocaleCompare("adjoin",option+1) == 0)
00428         {
00429           _image_info->adjoin = ArgBoolean;
00430           break;
00431         }
00432       if (LocaleCompare("affine",option+1) == 0)
00433         {
00434           CLIWandWarnReplaced("-draw 'affine ...'");
00435           if (IfSetOption)
00436             (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
00437           else
00438             GetAffineMatrix(&_draw_info->affine);
00439           break;
00440         }
00441       if (LocaleCompare("antialias",option+1) == 0)
00442         {
00443           _image_info->antialias =
00444             _draw_info->stroke_antialias =
00445               _draw_info->text_antialias = ArgBoolean;
00446           break;
00447         }
00448       if (LocaleCompare("attenuate",option+1) == 0)
00449         {
00450           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
00451             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00452           (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
00453           break;
00454         }
00455       if (LocaleCompare("authenticate",option+1) == 0)
00456         {
00457           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00458           break;
00459         }
00460       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
00461     }
00462     case 'b':
00463     {
00464       if (LocaleCompare("background",option+1) == 0)
00465         {
00466           /* FUTURE: both _image_info attribute & ImageOption in use!
00467              _image_info only used directly for generating new images.
00468              SyncImageSettings() used to set per-image attribute.
00469 
00470              FUTURE: if _image_info->background_color is not set then
00471              we should fall back to per-image background_color
00472 
00473              At this time -background will 'wipe out' the per-image
00474              background color!
00475 
00476              Better error handling of QueryColorCompliance() needed.
00477           */
00478           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00479           (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
00480              &_image_info->background_color,_exception);
00481           break;
00482         }
00483       if (LocaleCompare("bias",option+1) == 0)
00484         {
00485           /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
00486              as it is actually rarely used except in direct convolve operations
00487              Usage outside a direct convolve operation is actally non-sensible!
00488 
00489              SyncImageSettings() used to set per-image attribute.
00490           */
00491           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
00492             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00493           (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
00494           break;
00495         }
00496       if (LocaleCompare("black-point-compensation",option+1) == 0)
00497         {
00498           /* Used as a image chromaticity setting
00499              SyncImageSettings() used to set per-image attribute.
00500           */
00501           (void) SetImageOption(_image_info,option+1,ArgBooleanString);
00502           break;
00503         }
00504       if (LocaleCompare("blue-primary",option+1) == 0)
00505         {
00506           /* Image chromaticity X,Y  NB: Y=X if Y not defined
00507              Used by many coders including PNG
00508              SyncImageSettings() used to set per-image attribute.
00509           */
00510           arg1=ArgOption("0.0");
00511           if (IfMagickFalse(IsGeometry(arg1)))
00512             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00513           (void) SetImageOption(_image_info,option+1,arg1);
00514           break;
00515         }
00516       if (LocaleCompare("bordercolor",option+1) == 0)
00517         {
00518           /* FUTURE: both _image_info attribute & ImageOption in use!
00519              SyncImageSettings() used to set per-image attribute.
00520              Better error checking of QueryColorCompliance().
00521           */
00522           if (IfSetOption)
00523             {
00524               (void) SetImageOption(_image_info,option+1,arg1);
00525               (void) QueryColorCompliance(arg1,AllCompliance,
00526                   &_image_info->border_color,_exception);
00527               (void) QueryColorCompliance(arg1,AllCompliance,
00528                   &_draw_info->border_color,_exception);
00529               break;
00530             }
00531           (void) DeleteImageOption(_image_info,option+1);
00532           (void) QueryColorCompliance(BorderColor,AllCompliance,
00533             &_image_info->border_color,_exception);
00534           (void) QueryColorCompliance(BorderColor,AllCompliance,
00535             &_draw_info->border_color,_exception);
00536           break;
00537         }
00538       if (LocaleCompare("box",option+1) == 0)
00539         {
00540           CLIWandWarnReplaced("-undercolor");
00541           CLISettingOptionInfo(cli_wand,"-undercolor",arg1, arg2);
00542           break;
00543         }
00544       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
00545     }
00546     case 'c':
00547     {
00548       if (LocaleCompare("cache",option+1) == 0)
00549         {
00550           MagickSizeType
00551             limit;
00552 
00553           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
00554             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00555           limit=MagickResourceInfinity;
00556           if (LocaleCompare("unlimited",arg1) != 0)
00557             limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
00558           (void) SetMagickResourceLimit(MemoryResource,limit);
00559           (void) SetMagickResourceLimit(MapResource,2*limit);
00560           break;
00561         }
00562       if (LocaleCompare("caption",option+1) == 0)
00563         {
00564           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00565           break;
00566         }
00567       if (LocaleCompare("channel",option+1) == 0)
00568         {
00569           arg1=ArgOption("default");
00570           parse=ParseChannelOption(arg1);
00571           if (parse < 0)
00572             CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
00573                  option,arg1);
00574           _image_info->channel=(ChannelType) parse;
00575           (void) SetImageOption(_image_info,option+1,arg1);
00576           break;
00577         }
00578       if (LocaleCompare("colorspace",option+1) == 0)
00579         {
00580           /* Setting used for new images via AquireImage()
00581              But also used as a SimpleImageOperator
00582              Undefined colorspace means don't modify images on
00583              read or as a operation */
00584           parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
00585                         ArgOption("undefined"));
00586           if (parse < 0)
00587             CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
00588                                     option,arg1);
00589           _image_info->colorspace=(ColorspaceType) parse;
00590           break;
00591         }
00592       if (LocaleCompare("comment",option+1) == 0)
00593         {
00594           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00595           break;
00596         }
00597       if (LocaleCompare("compose",option+1) == 0)
00598         {
00599           /* FUTURE: _image_info should be used,
00600              SyncImageSettings() used to set per-image attribute. - REMOVE
00601 
00602              This setting should NOT be used to set image 'compose'
00603              "-layer" operators shoud use _image_info if defined otherwise
00604              they should use a per-image compose setting.
00605           */
00606           parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
00607                           ArgOption("undefined"));
00608           if (parse < 0)
00609             CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
00610                                       option,arg1);
00611           _image_info->compose=(CompositeOperator) parse;
00612           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00613           break;
00614         }
00615       if (LocaleCompare("compress",option+1) == 0)
00616         {
00617           /* FUTURE: What should be used?  _image_info  or ImageOption ???
00618              The former is more efficent, but Crisy prefers the latter!
00619              SyncImageSettings() used to set per-image attribute.
00620 
00621              The coders appears to use _image_info, not Image_Option
00622              however the image attribute (for save) is set from the
00623              ImageOption!
00624 
00625              Note that "undefined" is a different setting to "none".
00626           */
00627           parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
00628                      ArgOption("undefined"));
00629           if (parse < 0)
00630             CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
00631                                       option,arg1);
00632           _image_info->compression=(CompressionType) parse;
00633           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00634           break;
00635         }
00636       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
00637     }
00638     case 'd':
00639     {
00640       if (LocaleCompare("debug",option+1) == 0)
00641         {
00642           /* SyncImageSettings() used to set per-image attribute. */
00643           arg1=ArgOption("none");
00644           parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
00645           if (parse < 0)
00646             CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
00647                                       option,arg1);
00648           (void) SetLogEventMask(arg1);
00649           _image_info->debug=IsEventLogging();   /* extract logging*/
00650           cli_wand->wand.debug=IsEventLogging();
00651           break;
00652         }
00653       if (LocaleCompare("define",option+1) == 0)
00654         {
00655           if (LocaleNCompare(arg1,"registry:",9) == 0)
00656             {
00657               if (IfSetOption)
00658                 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
00659               else
00660                 (void) DeleteImageRegistry(arg1+9);
00661               break;
00662             }
00663           /* DefineImageOption() equals SetImageOption() but with '=' */
00664           if (IfSetOption)
00665             (void) DefineImageOption(_image_info,arg1);
00666           else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
00667             CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
00668           break;
00669         }
00670       if (LocaleCompare("delay",option+1) == 0)
00671         {
00672           /* Only used for new images via AcquireImage()
00673              FUTURE: Option should also be used for "-morph" (color morphing)
00674           */
00675           arg1=ArgOption("0");
00676           if (IfMagickFalse(IsGeometry(arg1)))
00677             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00678           (void) SetImageOption(_image_info,option+1,arg1);
00679           break;
00680         }
00681       if (LocaleCompare("density",option+1) == 0)
00682         {
00683           /* FUTURE: strings used in _image_info attr and _draw_info!
00684              Basically as density can be in a XxY form!
00685 
00686              SyncImageSettings() used to set per-image attribute.
00687           */
00688           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
00689             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00690           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00691           (void) CloneString(&_image_info->density,ArgOption(NULL));
00692           (void) CloneString(&_draw_info->density,_image_info->density);
00693           break;
00694         }
00695       if (LocaleCompare("depth",option+1) == 0)
00696         {
00697           /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
00698              SyncImageSettings() used to set per-image attribute.
00699           */
00700           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
00701             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00702           _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
00703                                        :MAGICKCORE_QUANTUM_DEPTH;
00704           break;
00705         }
00706       if (LocaleCompare("direction",option+1) == 0)
00707         {
00708           /* Image Option is only used to set _draw_info */
00709           arg1=ArgOption("undefined");
00710           parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
00711           if (parse < 0)
00712             CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
00713                                       option,arg1);
00714           _draw_info->direction=(DirectionType) parse;
00715           (void) SetImageOption(_image_info,option+1,arg1);
00716           break;
00717         }
00718       if (LocaleCompare("display",option+1) == 0)
00719         {
00720           (void) CloneString(&_image_info->server_name,ArgOption(NULL));
00721           (void) CloneString(&_draw_info->server_name,_image_info->server_name);
00722           break;
00723         }
00724       if (LocaleCompare("dispose",option+1) == 0)
00725         {
00726           /* only used in setting new images */
00727           arg1=ArgOption("undefined");
00728           parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
00729           if (parse < 0)
00730             CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
00731                                       option,arg1);
00732           (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
00733           break;
00734         }
00735       if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
00736         {
00737           /* FUTURE: this is only used by CompareImages() which is used
00738              only by the "compare" CLI program at this time.  */
00739           arg1=ArgOption(DEFAULT_DISSIMILARITY_THRESHOLD);
00740           if (IfMagickFalse(IsGeometry(arg1)))
00741             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00742           (void) SetImageOption(_image_info,option+1,arg1);
00743           break;
00744         }
00745       if (LocaleCompare("dither",option+1) == 0)
00746         {
00747           /* _image_info attr (on/off), _quantize_info attr (on/off)
00748              but also ImageInfo and _quantize_info method!
00749              FUTURE: merge the duality of the dithering options
00750           */
00751           _image_info->dither = _quantize_info->dither = ArgBoolean;
00752           (void) SetImageOption(_image_info,option+1,ArgOption("none"));
00753           _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
00754                     MagickDitherOptions,MagickFalse,ArgOption("none"));
00755           if (_quantize_info->dither_method == NoDitherMethod)
00756             _image_info->dither = _quantize_info->dither = MagickFalse;
00757           break;
00758         }
00759       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
00760     }
00761     case 'e':
00762     {
00763       if (LocaleCompare("encoding",option+1) == 0)
00764         {
00765           (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
00766           (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
00767           break;
00768         }
00769       if (LocaleCompare("endian",option+1) == 0)
00770         {
00771           /* Both _image_info attr and ImageInfo */
00772           arg1 = ArgOption("undefined");
00773           parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
00774           if (parse < 0)
00775             CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
00776                                       option,arg1);
00777           /* FUTURE: check alloc/free of endian string!  - remove? */
00778           _image_info->endian=(EndianType) (*arg1);
00779           (void) SetImageOption(_image_info,option+1,arg1);
00780           break;
00781         }
00782       if (LocaleCompare("extract",option+1) == 0)
00783         {
00784           (void) CloneString(&_image_info->extract,ArgOption(NULL));
00785           break;
00786         }
00787       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
00788     }
00789     case 'f':
00790     {
00791       if (LocaleCompare("family",option+1) == 0)
00792         {
00793           (void) CloneString(&_draw_info->family,ArgOption(NULL));
00794           break;
00795         }
00796       if (LocaleCompare("fill",option+1) == 0)
00797         {
00798           /* Set "fill" OR "fill-pattern" in _draw_info
00799              The original fill color is preserved if a fill-pattern is given.
00800              That way it does not effect other operations that directly using
00801              the fill color and, can be retored using "+tile".
00802           */
00803           MagickBooleanType
00804             status;
00805 
00806           ExceptionInfo
00807             *sans;
00808 
00809           PixelInfo
00810             color;
00811 
00812           arg1 = ArgOption("none");  /* +fill turns it off! */
00813           (void) SetImageOption(_image_info,option+1,arg1);
00814           if (_draw_info->fill_pattern != (Image *) NULL)
00815             _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
00816 
00817           /* is it a color or a image? -- ignore exceptions */
00818           sans=AcquireExceptionInfo();
00819           status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
00820           sans=DestroyExceptionInfo(sans);
00821 
00822           if (IfMagickFalse(status))
00823             _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
00824           else
00825             _draw_info->fill=color;
00826           break;
00827         }
00828       if (LocaleCompare("filter",option+1) == 0)
00829         {
00830           /* SyncImageSettings() used to set per-image attribute. */
00831           arg1 = ArgOption("undefined");
00832           parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
00833           if (parse < 0)
00834             CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
00835                                       option,arg1);
00836           (void) SetImageOption(_image_info,option+1,arg1);
00837           break;
00838         }
00839       if (LocaleCompare("font",option+1) == 0)
00840         {
00841           (void) CloneString(&_draw_info->font,ArgOption(NULL));
00842           (void) CloneString(&_image_info->font,_draw_info->font);
00843           break;
00844         }
00845       if (LocaleCompare("format",option+1) == 0)
00846         {
00847           /* FUTURE: why the ping test, you could set ping after this! */
00848           /*
00849           register const char
00850             *q;
00851 
00852           for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
00853             if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
00854               _image_info->ping=MagickFalse;
00855           */
00856           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00857           break;
00858         }
00859       if (LocaleCompare("fuzz",option+1) == 0)
00860         {
00861           /* Option used to set image fuzz! unless blank canvas (from color)
00862              Image attribute used for color compare operations
00863              SyncImageSettings() used to set per-image attribute.
00864 
00865              FUTURE: Can't find anything else using _image_info->fuzz directly!
00866                      remove direct sttribute from image_info
00867           */
00868           arg1=ArgOption("0");
00869           if (IfMagickFalse(IsGeometry(arg1)))
00870             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00871           _image_info->fuzz=StringToDoubleInterval(arg1,(double)
00872                 QuantumRange+1.0);
00873           (void) SetImageOption(_image_info,option+1,arg1);
00874           break;
00875         }
00876       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
00877     }
00878     case 'g':
00879     {
00880       if (LocaleCompare("gravity",option+1) == 0)
00881         {
00882           /* SyncImageSettings() used to set per-image attribute. */
00883           arg1 = ArgOption("none");
00884           parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
00885           if (parse < 0)
00886             CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
00887                                       option,arg1);
00888           _draw_info->gravity=(GravityType) parse;
00889           (void) SetImageOption(_image_info,option+1,arg1);
00890           break;
00891         }
00892       if (LocaleCompare("green-primary",option+1) == 0)
00893         {
00894           /* Image chromaticity X,Y  NB: Y=X if Y not defined
00895              SyncImageSettings() used to set per-image attribute.
00896              Used directly by many coders
00897           */
00898           arg1=ArgOption("0.0");
00899           if (IfMagickFalse(IsGeometry(arg1)))
00900             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00901           (void) SetImageOption(_image_info,option+1,arg1);
00902           break;
00903         }
00904       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
00905     }
00906     case 'h':
00907     {
00908       if (LocaleCompare("highlight-color",option+1) == 0)
00909         {
00910           /* FUTURE: this is only used by CompareImages() which is used
00911              only by the "compare" CLI program at this time.  */
00912           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00913           break;
00914         }
00915       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
00916     }
00917     case 'i':
00918     {
00919       if (LocaleCompare("intent",option+1) == 0)
00920         {
00921           /* Only used by coders: MIFF, MPC, BMP, PNG
00922              and for image profile call to AcquireTransformThreadSet()
00923              SyncImageSettings() used to set per-image attribute.
00924           */
00925           arg1 = ArgOption("indefined");
00926           parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
00927           if (parse < 0)
00928             CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
00929                                       option,arg1);
00930           (void) SetImageOption(_image_info,option+1,arg1);
00931           break;
00932         }
00933       if (LocaleCompare("interlace",option+1) == 0)
00934         {
00935           /* _image_info is directly used by coders (so why an image setting?)
00936              SyncImageSettings() used to set per-image attribute.
00937           */
00938           arg1 = ArgOption("undefined");
00939           parse = ParseCommandOption(MagickInterlaceOptions,MagickFalse,arg1);
00940           if (parse < 0)
00941             CLIWandExceptArgBreak(OptionError,"UnrecognizedInterlaceType",
00942                                       option,arg1);
00943           _image_info->interlace=(InterlaceType) parse;
00944           (void) SetImageOption(_image_info,option+1,arg1);
00945           break;
00946         }
00947       if (LocaleCompare("interline-spacing",option+1) == 0)
00948         {
00949           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
00950             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00951           (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
00952           _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
00953                (char **) NULL);
00954           break;
00955         }
00956       if (LocaleCompare("interpolate",option+1) == 0)
00957         {
00958           /* SyncImageSettings() used to set per-image attribute. */
00959           arg1 = ArgOption("undefined");
00960           parse = ParseCommandOption(MagickInterpolateOptions,MagickFalse,arg1);
00961           if (parse < 0)
00962             CLIWandExceptArgBreak(OptionError,"UnrecognizedInterpolateMethod",
00963                                       option,arg1);
00964           (void) SetImageOption(_image_info,option+1,arg1);
00965           break;
00966         }
00967       if (LocaleCompare("interword-spacing",option+1) == 0)
00968         {
00969           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
00970             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00971           (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
00972           _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
00973           break;
00974         }
00975       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
00976     }
00977     case 'k':
00978     {
00979       if (LocaleCompare("kerning",option+1) == 0)
00980         {
00981           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
00982             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
00983           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00984           _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
00985           break;
00986         }
00987       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
00988     }
00989     case 'l':
00990     {
00991       if (LocaleCompare("label",option+1) == 0)
00992         {
00993           /* only used for new images - not in SyncImageOptions() */
00994           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
00995           break;
00996         }
00997       if (LocaleCompare("limit",option+1) == 0)
00998         {
00999           MagickSizeType
01000             limit;
01001 
01002           limit=MagickResourceInfinity;
01003           parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
01004           if ( parse < 0 )
01005             CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
01006                 option,arg1);
01007           if (LocaleCompare("unlimited",arg2) != 0)
01008             limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
01009           (void) SetMagickResourceLimit((ResourceType)parse,limit);
01010           break;
01011         }
01012       if (LocaleCompare("log",option+1) == 0)
01013         {
01014           if (IfSetOption) {
01015             if ((strchr(arg1,'%') == (char *) NULL))
01016               CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01017             (void) SetLogFormat(arg1);
01018           }
01019           break;
01020         }
01021       if (LocaleCompare("lowlight-color",option+1) == 0)
01022         {
01023           /* FUTURE: this is only used by CompareImages() which is used
01024              only by the "compare" CLI program at this time.  */
01025           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01026           break;
01027         }
01028       if (LocaleCompare("loop",option+1) == 0)
01029         {
01030           /* SyncImageSettings() used to set per-image attribute. */
01031           arg1=ArgOption("0");
01032           if (IfMagickFalse(IsGeometry(arg1)))
01033             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01034           (void) SetImageOption(_image_info,option+1,arg1);
01035           break;
01036         }
01037       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01038     }
01039     case 'm':
01040     {
01041       if (LocaleCompare("mattecolor",option+1) == 0)
01042         {
01043           /* SyncImageSettings() used to set per-image attribute. */
01044           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01045           (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
01046              &_image_info->matte_color,_exception);
01047           break;
01048         }
01049       if (LocaleCompare("metric",option+1) == 0)
01050         {
01051           /* FUTURE: this is only used by CompareImages() which is used
01052              only by the "compare" CLI program at this time.  */
01053           parse=ParseCommandOption(MagickMetricOptions,MagickFalse,arg1);
01054           if ( parse < 0 )
01055             CLIWandExceptArgBreak(OptionError,"UnrecognizedMetricType",
01056                 option,arg1);
01057           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01058           break;
01059         }
01060       if (LocaleCompare("monitor",option+1) == 0)
01061         {
01062           (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
01063                 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
01064           break;
01065         }
01066       if (LocaleCompare("monochrome",option+1) == 0)
01067         {
01068           /* Setting (used by some input coders!) -- why?
01069              Warning: This is also Special '-type' SimpleOperator
01070           */
01071           _image_info->monochrome= ArgBoolean;
01072           break;
01073         }
01074       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01075     }
01076     case 'o':
01077     {
01078       if (LocaleCompare("orient",option+1) == 0)
01079         {
01080           /* Is not used when defining for new images.
01081              This makes it more of a 'operation' than a setting
01082              FUTURE: make set meta-data operator instead.
01083              SyncImageSettings() used to set per-image attribute.
01084           */
01085           parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
01086                ArgOption("undefined"));
01087           if (parse < 0)
01088             CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
01089                                       option,arg1);
01090           _image_info->orientation=(OrientationType)parse;
01091           (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
01092           break;
01093         }
01094       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01095     }
01096     case 'p':
01097     {
01098       if (LocaleCompare("page",option+1) == 0)
01099         {
01100           /* Only used for new images and image generators.
01101              SyncImageSettings() used to set per-image attribute. ?????
01102              That last is WRONG!!!!
01103              FUTURE: adjust named 'page' sizes according density
01104           */
01105           char
01106             *canonical_page,
01107             page[MaxTextExtent];
01108 
01109           const char
01110             *image_option;
01111 
01112           MagickStatusType
01113             flags;
01114 
01115           RectangleInfo
01116             geometry;
01117 
01118           if (!IfSetOption)
01119             {
01120               (void) DeleteImageOption(_image_info,option+1);
01121               (void) CloneString(&_image_info->page,(char *) NULL);
01122               break;
01123             }
01124           (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
01125           image_option=GetImageOption(_image_info,"page");
01126           if (image_option != (const char *) NULL)
01127             flags=ParseAbsoluteGeometry(image_option,&geometry);
01128           canonical_page=GetPageGeometry(arg1);
01129           flags=ParseAbsoluteGeometry(canonical_page,&geometry);
01130           canonical_page=DestroyString(canonical_page);
01131           (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
01132             (unsigned long) geometry.width,(unsigned long) geometry.height);
01133           if (((flags & XValue) != 0) || ((flags & YValue) != 0))
01134             (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
01135               (unsigned long) geometry.width,(unsigned long) geometry.height,
01136               (long) geometry.x,(long) geometry.y);
01137           (void) SetImageOption(_image_info,option+1,page);
01138           (void) CloneString(&_image_info->page,page);
01139           break;
01140         }
01141       if (LocaleCompare("ping",option+1) == 0)
01142         {
01143           _image_info->ping = ArgBoolean;
01144           break;
01145         }
01146       if (LocaleCompare("pointsize",option+1) == 0)
01147         {
01148           if (IfSetOption) {
01149             if (IfMagickFalse(IsGeometry(arg1)))
01150               CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01151             _image_info->pointsize =
01152             _draw_info->pointsize =
01153               StringToDouble(arg1,(char **) NULL);
01154           }
01155           else {
01156             _image_info->pointsize=0.0; /* unset pointsize */
01157             _draw_info->pointsize=12.0;
01158           }
01159           break;
01160         }
01161       if (LocaleCompare("precision",option+1) == 0)
01162         {
01163           arg1=ArgOption("-1");
01164           if (IfMagickFalse(IsGeometry(arg1)))
01165             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01166           (void) SetMagickPrecision(StringToInteger(arg1));
01167           break;
01168         }
01169       /* FUTURE: Only the 'preview' coder appears to use this
01170        * DEPRECIATE the coder?  Leaving only the 'preview' operator.
01171       if (LocaleCompare("preview",option+1) == 0)
01172         {
01173           _image_info->preview_type=UndefinedPreview;
01174           if (IfSetOption)
01175             _image_info->preview_type=(PreviewType) ParseCommandOption(
01176                 MagickPreviewOptions,MagickFalse,arg1);
01177           break;
01178         }
01179       */
01180       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01181     }
01182     case 'q':
01183     {
01184       if (LocaleCompare("quality",option+1) == 0)
01185         {
01186           if (IfMagickFalse(IsGeometry(arg1)))
01187             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01188           _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
01189                                             : UNDEFINED_COMPRESSION_QUALITY;
01190           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01191           break;
01192         }
01193       if (LocaleCompare("quantize",option+1) == 0)
01194         {
01195           /* Just a set direct in _quantize_info */
01196           arg1=ArgOption("undefined");
01197           parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
01198           if (parse < 0)
01199             CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
01200                  option,arg1);
01201           _quantize_info->colorspace=(ColorspaceType)parse;
01202           break;
01203         }
01204       if (LocaleCompare("quiet",option+1) == 0)
01205         {
01206           /* FUTURE: if two -quiet is performed you can not do +quiet!
01207              This needs to be checked over thoughly.
01208           */
01209           static WarningHandler
01210             warning_handler = (WarningHandler) NULL;
01211 
01212           WarningHandler
01213             tmp = SetWarningHandler((WarningHandler) NULL);
01214 
01215           if ( tmp != (WarningHandler) NULL)
01216             warning_handler = tmp; /* remember the old handler */
01217           if (!IfSetOption)        /* set the old handler */
01218             warning_handler=SetWarningHandler(warning_handler);
01219           break;
01220         }
01221       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01222     }
01223     case 'r':
01224     {
01225       if (LocaleCompare("red-primary",option+1) == 0)
01226         {
01227           /* Image chromaticity X,Y  NB: Y=X if Y not defined
01228              Used by many coders
01229              SyncImageSettings() used to set per-image attribute.
01230           */
01231           arg1=ArgOption("0.0");
01232           if (IfMagickFalse(IsGeometry(arg1)))
01233             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01234           (void) SetImageOption(_image_info,option+1,arg1);
01235           break;
01236         }
01237       if (LocaleCompare("regard-warnings",option+1) == 0)
01238         /* FUTURE: to be replaced by a 'fatal-level' type setting */
01239         break;
01240       if (LocaleCompare("render",option+1) == 0)
01241         {
01242           /* _draw_info only setting */
01243           _draw_info->render= ArgBooleanNot;
01244           break;
01245         }
01246       if (LocaleCompare("respect-parenthesis",option+1) == 0)
01247         {
01248           /* link image and setting stacks - option is itself saved on stack! */
01249           (void) SetImageOption(_image_info,option+1,ArgBooleanString);
01250           break;
01251         }
01252       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01253     }
01254     case 's':
01255     {
01256       if (LocaleCompare("sampling-factor",option+1) == 0)
01257         {
01258           /* FUTURE: should be converted to jpeg:sampling_factor */
01259           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
01260             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01261           (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
01262           break;
01263         }
01264       if (LocaleCompare("scene",option+1) == 0)
01265         {
01266           /* SyncImageSettings() used to set this as a per-image attribute.
01267              What ??? Why ????
01268           */
01269           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
01270             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01271           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01272           _image_info->scene=StringToUnsignedLong(ArgOption("0"));
01273           break;
01274         }
01275       if (LocaleCompare("seed",option+1) == 0)
01276         {
01277           if (IfMagickFalse(IsGeometry(arg1)))
01278             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01279           SetRandomSecretKey(
01280                IfSetOption ? (size_t) StringToUnsignedLong(arg1)
01281                            : (size_t) time((time_t *) NULL) );
01282           break;
01283         }
01284       if (LocaleCompare("size",option+1) == 0)
01285         {
01286           /* FUTURE: string in _image_info -- convert to Option ???
01287              Look at the special handling for "size" in SetImageOption()
01288            */
01289           (void) CloneString(&_image_info->size,ArgOption(NULL));
01290           break;
01291         }
01292       if (LocaleCompare("stretch",option+1) == 0)
01293         {
01294           arg1=ArgOption("undefined");
01295           parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
01296           if (parse < 0)
01297             CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
01298                  option,arg1);
01299           _draw_info->stretch=(StretchType) parse;
01300           break;
01301         }
01302       if (LocaleCompare("stroke",option+1) == 0)
01303         {
01304           /* set stroke color OR stroke-pattern
01305              UPDATE: ensure stroke color is not destroyed is a pattern
01306              is given. Just in case the color is also used for other purposes.
01307            */
01308           MagickBooleanType
01309             status;
01310 
01311           ExceptionInfo
01312             *sans;
01313 
01314           PixelInfo
01315             color;
01316 
01317           arg1 = ArgOption("none");  /* +fill turns it off! */
01318           (void) SetImageOption(_image_info,option+1,arg1);
01319           if (_draw_info->stroke_pattern != (Image *) NULL)
01320             _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
01321 
01322           /* is it a color or a image? -- ignore exceptions */
01323           sans=AcquireExceptionInfo();
01324           status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
01325           sans=DestroyExceptionInfo(sans);
01326 
01327           if (IfMagickFalse(status))
01328             _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
01329           else
01330             _draw_info->stroke=color;
01331           break;
01332         }
01333       if (LocaleCompare("strokewidth",option+1) == 0)
01334         {
01335           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
01336             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01337           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01338           _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
01339                (char **) NULL);
01340           break;
01341         }
01342       if (LocaleCompare("style",option+1) == 0)
01343         {
01344           arg1=ArgOption("undefined");
01345           parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
01346           if (parse < 0)
01347             CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
01348                  option,arg1);
01349           _draw_info->style=(StyleType) parse;
01350           break;
01351         }
01352 #if 0
01353       if (LocaleCompare("subimage-search",option+1) == 0)
01354         {
01355         /* FUTURE: this is only used by CompareImages() which is used
01356             only by the "compare" CLI program at this time.  */
01357           (void) SetImageOption(_image_info,option+1,ArgBooleanString);
01358           break;
01359         }
01360 #endif
01361       if (LocaleCompare("synchronize",option+1) == 0)
01362         {
01363           /* FUTURE: syncronize to storage - but what does that mean? */
01364           _image_info->synchronize = ArgBoolean;
01365           break;
01366         }
01367       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01368     }
01369     case 't':
01370     {
01371       if (LocaleCompare("taint",option+1) == 0)
01372         {
01373           /* SyncImageSettings() used to set per-image attribute. */
01374           (void) SetImageOption(_image_info,option+1,ArgBooleanString);
01375           break;
01376         }
01377       if (LocaleCompare("texture",option+1) == 0)
01378         {
01379           /* FUTURE: move _image_info string to option splay-tree
01380              Other than "montage" what uses "texture" ????
01381           */
01382           (void) CloneString(&_image_info->texture,ArgOption(NULL));
01383           break;
01384         }
01385       if (LocaleCompare("tile",option+1) == 0)
01386         {
01387           _draw_info->fill_pattern=IfSetOption
01388                                  ?GetImageCache(_image_info,arg1,_exception)
01389                                  :DestroyImage(_draw_info->fill_pattern);
01390           break;
01391         }
01392       if (LocaleCompare("tile-offset",option+1) == 0)
01393         {
01394           /* SyncImageSettings() used to set per-image attribute. ??? */
01395           arg1=ArgOption("0");
01396           if (IfMagickFalse(IsGeometry(arg1)))
01397             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01398           (void) SetImageOption(_image_info,option+1,arg1);
01399           break;
01400         }
01401       if (LocaleCompare("transparent-color",option+1) == 0)
01402         {
01403           /* FUTURE: both _image_info attribute & ImageOption in use!
01404              _image_info only used for generating new images.
01405              SyncImageSettings() used to set per-image attribute.
01406 
01407              Note that +transparent-color, means fall-back to image
01408              attribute so ImageOption is deleted, not set to a default.
01409           */
01410           if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
01411             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01412           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01413           (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
01414               &_image_info->transparent_color,_exception);
01415           break;
01416         }
01417       if (LocaleCompare("treedepth",option+1) == 0)
01418         {
01419           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01420           _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
01421           break;
01422         }
01423       if (LocaleCompare("type",option+1) == 0)
01424         {
01425           /* SyncImageSettings() used to set per-image attribute. */
01426           parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
01427                ArgOption("undefined"));
01428           if (parse < 0)
01429             CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
01430                  option,arg1);
01431           _image_info->type=(ImageType) parse;
01432           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01433           break;
01434         }
01435       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01436     }
01437     case 'u':
01438     {
01439       if (LocaleCompare("undercolor",option+1) == 0)
01440         {
01441           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01442           (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
01443                &_draw_info->undercolor,_exception);
01444           break;
01445         }
01446       if (LocaleCompare("units",option+1) == 0)
01447         {
01448           /* SyncImageSettings() used to set per-image attribute.
01449              Should this effect _draw_info X and Y resolution?
01450              FUTURE: this probably should be part of the density setting
01451           */
01452           parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
01453                ArgOption("undefined"));
01454           if (parse < 0)
01455             CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
01456                  option,arg1);
01457           _image_info->units=(ResolutionType) parse;
01458           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01459           break;
01460         }
01461       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01462     }
01463     case 'v':
01464     {
01465       if (LocaleCompare("verbose",option+1) == 0)
01466         {
01467           /* FUTURE: Remember all options become image artifacts
01468              _image_info->verbose is only used by coders.
01469           */
01470           (void) SetImageOption(_image_info,option+1,ArgBooleanString);
01471           _image_info->verbose= ArgBoolean;
01472           _image_info->ping=MagickFalse; /* verbose can't be a ping */
01473           break;
01474         }
01475       if (LocaleCompare("view",option+1) == 0)
01476         {
01477           /* FUTURE: Convert from _image_info to ImageOption
01478              Only used by coder FPX
01479              And it only tests existance, not its content!
01480           */
01481           (void) CloneString(&_image_info->view,ArgOption(NULL));
01482           break;
01483         }
01484       if (LocaleCompare("virtual-pixel",option+1) == 0)
01485         {
01486           /* SyncImageSettings() used to set per-image attribute.
01487              This is VERY deep in the image caching structure.
01488           */
01489           parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
01490                ArgOption("undefined"));
01491           if (parse < 0)
01492             CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
01493                  option,arg1);
01494           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
01495           break;
01496         }
01497       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01498     }
01499     case 'w':
01500     {
01501       if (LocaleCompare("weight",option+1) == 0)
01502         {
01503           /* Just what does using a font 'weight' do ???
01504              There is no "-list weight" output (reference manual says there is)
01505           */
01506           arg1=ArgOption("all");
01507           _draw_info->weight=StringToUnsignedLong(arg1);
01508           if (LocaleCompare(arg1,"all") == 0)
01509             _draw_info->weight=0;
01510           if (LocaleCompare(arg1,"bold") == 0)
01511             _draw_info->weight=700;
01512           if (LocaleCompare(arg1,"bolder") == 0)
01513             if (_draw_info->weight <= 800)
01514               _draw_info->weight+=100;
01515           if (LocaleCompare(arg1,"lighter") == 0)
01516             if (_draw_info->weight >= 100)
01517               _draw_info->weight-=100;
01518           if (LocaleCompare(arg1,"normal") == 0)
01519             _draw_info->weight=400;
01520           break;
01521         }
01522       if (LocaleCompare("white-point",option+1) == 0)
01523         {
01524           /* Used as a image chromaticity setting
01525              SyncImageSettings() used to set per-image attribute.
01526           */
01527           arg1=ArgOption("0.0");
01528           if (IfMagickFalse(IsGeometry(arg1)))
01529             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01530           (void) SetImageOption(_image_info,option+1,arg1);
01531           break;
01532         }
01533       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01534     }
01535     default:
01536       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01537   }
01538 
01539 #undef _image_info
01540 #undef _exception
01541 #undef _draw_info
01542 #undef _quantize_info
01543 #undef IfSetOption
01544 #undef ArgBoolean
01545 #undef ArgBooleanNot
01546 #undef ArgBooleanString
01547 #undef ArgOption
01548 
01549   return;
01550 }
01551 
01552 /*
01553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01554 %                                                                             %
01555 %                                                                             %
01556 %                                                                             %
01557 +     C L I S i m p l e O p e r a t o r I m a g e s                           %
01558 %                                                                             %
01559 %                                                                             %
01560 %                                                                             %
01561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01562 %
01563 %  WandSimpleOperatorImages() applys one simple image operation given to all
01564 %  the images in the CLI wand,  with the settings that was previously saved in
01565 %  the CLI wand.
01566 %
01567 %  It is assumed that any per-image settings are up-to-date with respect to
01568 %  extra settings that were already saved in the wand.
01569 %
01570 %  The format of the WandSimpleOperatorImage method is:
01571 %
01572 %    void CLISimpleOperatorImages(MagickCLI *cli_wand,
01573 %        const char *option, const char *arg1, const char *arg2)
01574 %
01575 %  A description of each parameter follows:
01576 %
01577 %    o cli_wand: structure holding settings and images to be operated on
01578 %
01579 %    o option:  The option string for the operation
01580 %
01581 %    o arg1, arg2: optional argument strings to the operation
01582 %
01583 */
01584 
01585 /*
01586   Internal subrountine to apply one simple image operation to the current
01587   image pointed to by the CLI wand.
01588 
01589   The image in the list may be modified in three different ways...
01590     * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
01591     * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
01592     * one image replace by a list of images (-separate and -crop only!)
01593 
01594   In each case the result replaces the single original image in the list, as
01595   well as the pointer to the modified image (last image added if replaced by a
01596   list of images) is returned.
01597 
01598   As the image pointed to may be replaced, the first image in the list may
01599   also change.  GetFirstImageInList() should be used by caller if they wish
01600   return the Image pointer to the first image in list.
01601 */
01602 static void CLISimpleOperatorImage(MagickCLI *cli_wand,
01603   const char *option, const char *arg1n, const char *arg2n)
01604 {
01605   Image *
01606     new_image;
01607 
01608   GeometryInfo
01609     geometry_info;
01610 
01611   RectangleInfo
01612     geometry;
01613 
01614   MagickStatusType
01615     flags;
01616 
01617   ssize_t
01618     parse;
01619 
01620   const char    /* For percent escape interpretImageProperties() */
01621     *arg1,
01622     *arg2;
01623 
01624 #define _image_info     (cli_wand->wand.image_info)
01625 #define _image          (cli_wand->wand.images)
01626 #define _exception      (cli_wand->wand.exception)
01627 #define _draw_info      (cli_wand->draw_info)
01628 #define _quantize_info  (cli_wand->quantize_info)
01629 #define _process_flags  (cli_wand->process_flags)
01630 #define _option_type    ((CommandOptionFlags) cli_wand->command->flags)
01631 #define IfNormalOp      (*option=='-')
01632 #define IfPlusOp        (*option!='-')
01633 #define normal_op       IsMagickTrue(IfNormalOp)
01634 #define plus_alt_op     IsMagickFalse(IfNormalOp)
01635 
01636   assert(cli_wand != (MagickCLI *) NULL);
01637   assert(cli_wand->signature == WandSignature);
01638   assert(cli_wand->wand.signature == WandSignature);
01639   assert(_image != (Image *) NULL);             /* an image must be present */
01640   if (IfMagickTrue(cli_wand->wand.debug))
01641     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
01642 
01643   /* Interpret Percent Escapes in Arguments - using first image */
01644   arg1 = arg1n,
01645   arg2 = arg2n;
01646   if ( (((_process_flags & ProcessInterpretProperities) != 0 )
01647         || ((_option_type & AlwaysInterpretArgsFlag) != 0)
01648        )  && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
01649     /* Interpret Percent escapes in argument 1 */
01650     if (arg1n != (char *) NULL) {
01651       arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
01652       if (arg1 == (char *) NULL) {
01653         CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
01654         arg1=arg1n;  /* use the given argument as is */
01655       }
01656     }
01657     if (arg2n != (char *) NULL) {
01658       arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
01659       if (arg2 == (char *) NULL) {
01660         CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
01661         arg2=arg2n;  /* use the given argument as is */
01662       }
01663     }
01664   }
01665 #undef _option_type
01666 
01667 #if 0
01668   (void) FormatLocaleFile(stderr,
01669     "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
01670 #endif
01671 
01672   new_image = (Image *)NULL; /* the replacement image, if not null at end */
01673   SetGeometryInfo(&geometry_info);
01674 
01675   switch (*(option+1))
01676   {
01677     case 'a':
01678     {
01679       if (LocaleCompare("adaptive-blur",option+1) == 0)
01680         {
01681           flags=ParseGeometry(arg1,&geometry_info);
01682           if ((flags & (RhoValue|SigmaValue)) == 0)
01683             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01684           if ((flags & SigmaValue) == 0)
01685             geometry_info.sigma=1.0;
01686           new_image=AdaptiveBlurImage(_image,geometry_info.rho,
01687             geometry_info.sigma,_exception);
01688           break;
01689         }
01690       if (LocaleCompare("adaptive-resize",option+1) == 0)
01691         {
01692           /* FUTURE: Roll into a resize special operator */
01693           if (IfMagickFalse(IsGeometry(arg1)))
01694             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01695           (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
01696           new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
01697             _exception);
01698           break;
01699         }
01700       if (LocaleCompare("adaptive-sharpen",option+1) == 0)
01701         {
01702           flags=ParseGeometry(arg1,&geometry_info);
01703           if ((flags & (RhoValue|SigmaValue)) == 0)
01704             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01705           if ((flags & SigmaValue) == 0)
01706             geometry_info.sigma=1.0;
01707           new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
01708             geometry_info.sigma,_exception);
01709           break;
01710         }
01711       if (LocaleCompare("alpha",option+1) == 0)
01712         {
01713           parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
01714           if (parse < 0)
01715             CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
01716                  option,arg1);
01717           (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
01718                _exception);
01719           break;
01720         }
01721       if (LocaleCompare("annotate",option+1) == 0)
01722         {
01723           char
01724             geometry[MaxTextExtent];
01725 
01726           SetGeometryInfo(&geometry_info);
01727           flags=ParseGeometry(arg1,&geometry_info);
01728           if ((flags & RhoValue) == 0)
01729             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01730           if ((flags & SigmaValue) == 0)
01731             geometry_info.sigma=geometry_info.rho;
01732           (void) CloneString(&_draw_info->text,arg2);
01733           (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
01734             geometry_info.xi,geometry_info.psi);
01735           (void) CloneString(&_draw_info->geometry,geometry);
01736           _draw_info->affine.sx=cos(DegreesToRadians(
01737             fmod(geometry_info.rho,360.0)));
01738           _draw_info->affine.rx=sin(DegreesToRadians(
01739             fmod(geometry_info.rho,360.0)));
01740           _draw_info->affine.ry=(-sin(DegreesToRadians(
01741             fmod(geometry_info.sigma,360.0))));
01742           _draw_info->affine.sy=cos(DegreesToRadians(
01743             fmod(geometry_info.sigma,360.0)));
01744           (void) AnnotateImage(_image,_draw_info,_exception);
01745           GetAffineMatrix(&_draw_info->affine);
01746           break;
01747         }
01748       if (LocaleCompare("auto-gamma",option+1) == 0)
01749         {
01750           (void) AutoGammaImage(_image,_exception);
01751           break;
01752         }
01753       if (LocaleCompare("auto-level",option+1) == 0)
01754         {
01755           (void) AutoLevelImage(_image,_exception);
01756           break;
01757         }
01758       if (LocaleCompare("auto-orient",option+1) == 0)
01759         {
01760           /* This should probably be a MagickCore function */
01761           switch (_image->orientation)
01762           {
01763             case TopRightOrientation:
01764             {
01765               new_image=FlopImage(_image,_exception);
01766               break;
01767             }
01768             case BottomRightOrientation:
01769             {
01770               new_image=RotateImage(_image,180.0,_exception);
01771               break;
01772             }
01773             case BottomLeftOrientation:
01774             {
01775               new_image=FlipImage(_image,_exception);
01776               break;
01777             }
01778             case LeftTopOrientation:
01779             {
01780               new_image=TransposeImage(_image,_exception);
01781               break;
01782             }
01783             case RightTopOrientation:
01784             {
01785               new_image=RotateImage(_image,90.0,_exception);
01786               break;
01787             }
01788             case RightBottomOrientation:
01789             {
01790               new_image=TransverseImage(_image,_exception);
01791               break;
01792             }
01793             case LeftBottomOrientation:
01794             {
01795               new_image=RotateImage(_image,270.0,_exception);
01796               break;
01797             }
01798             default:
01799               break;
01800           }
01801           if (new_image != (Image *) NULL)
01802             new_image->orientation=TopLeftOrientation;
01803           break;
01804         }
01805       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01806     }
01807     case 'b':
01808     {
01809       if (LocaleCompare("black-threshold",option+1) == 0)
01810         {
01811           if (IfMagickFalse(IsGeometry(arg1)))
01812             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01813           (void) BlackThresholdImage(_image,arg1,_exception);
01814           break;
01815         }
01816       if (LocaleCompare("blue-shift",option+1) == 0)
01817         {
01818           geometry_info.rho=1.5;
01819           if (IfNormalOp) {
01820             flags=ParseGeometry(arg1,&geometry_info);
01821             if ((flags & RhoValue) == 0)
01822               CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01823           }
01824           new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
01825           break;
01826         }
01827       if (LocaleCompare("blur",option+1) == 0)
01828         {
01829           flags=ParseGeometry(arg1,&geometry_info);
01830           if ((flags & (RhoValue|SigmaValue)) == 0)
01831             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01832           if ((flags & SigmaValue) == 0)
01833             geometry_info.sigma=1.0;
01834           new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
01835            _exception);
01836           break;
01837         }
01838       if (LocaleCompare("border",option+1) == 0)
01839         {
01840           CompositeOperator
01841             compose;
01842 
01843           const char*
01844             value;
01845 
01846           flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
01847           if ((flags & RhoValue) == 0)
01848             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01849           if ((flags & SigmaValue) == 0)
01850             geometry.height=geometry.width;
01851 
01852           value=GetImageOption(_image_info,"compose");
01853           if (value != (const char *) NULL)
01854             compose=(CompositeOperator) ParseCommandOption(
01855                  MagickComposeOptions,MagickFalse,value);
01856           else
01857             compose=OverCompositeOp;  /* use Over not _image->compose */
01858 
01859           new_image=BorderImage(_image,&geometry,compose,_exception);
01860           break;
01861         }
01862       if (LocaleCompare("brightness-contrast",option+1) == 0)
01863         {
01864           double
01865             brightness,
01866             contrast;
01867 
01868           GeometryInfo
01869             geometry_info;
01870 
01871           MagickStatusType
01872             flags;
01873 
01874           flags=ParseGeometry(arg1,&geometry_info);
01875           if ((flags & RhoValue) == 0)
01876             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01877           brightness=geometry_info.rho;
01878           contrast=0.0;
01879           if ((flags & SigmaValue) != 0)
01880             contrast=geometry_info.sigma;
01881           (void) BrightnessContrastImage(_image,brightness,contrast,
01882             _exception);
01883           break;
01884         }
01885       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
01886     }
01887     case 'c':
01888     {
01889       if (LocaleCompare("cdl",option+1) == 0)
01890         {
01891           char
01892             *color_correction_collection;
01893 
01894           /*
01895             Color correct with a color decision list.
01896           */
01897           color_correction_collection=FileToString(arg1,~0,_exception);
01898           if (color_correction_collection == (char *) NULL)
01899             break;
01900           (void) ColorDecisionListImage(_image,color_correction_collection,
01901             _exception);
01902           break;
01903         }
01904       if (LocaleCompare("charcoal",option+1) == 0)
01905         {
01906           flags=ParseGeometry(arg1,&geometry_info);
01907           if ((flags & (RhoValue|SigmaValue)) == 0)
01908             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01909           if ((flags & SigmaValue) == 0)
01910             geometry_info.sigma=1.0;
01911           if ((flags & XiValue) == 0)
01912             geometry_info.xi=1.0;
01913           new_image=CharcoalImage(_image,geometry_info.rho,
01914             geometry_info.sigma,_exception);
01915           break;
01916         }
01917       if (LocaleCompare("chop",option+1) == 0)
01918         {
01919           if (IfMagickFalse(IsGeometry(arg1)))
01920             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
01921           (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
01922           new_image=ChopImage(_image,&geometry,_exception);
01923           break;
01924         }
01925       if (LocaleCompare("clamp",option+1) == 0)
01926         {
01927           (void) ClampImage(_image,_exception);
01928           break;
01929         }
01930       if (LocaleCompare("clip",option+1) == 0)
01931         {
01932           if (IfNormalOp)
01933             (void) ClipImage(_image,_exception);
01934           else /* "+mask" remove the write mask */
01935             (void) SetImageMask(_image,(Image *) NULL,_exception);
01936           break;
01937         }
01938       if (LocaleCompare("clip-mask",option+1) == 0)
01939         {
01940           CacheView
01941             *mask_view;
01942 
01943           Image
01944             *mask_image;
01945 
01946           register Quantum
01947             *restrict q;
01948 
01949           register ssize_t
01950             x;
01951 
01952           ssize_t
01953             y;
01954 
01955           if (IfPlusOp) {
01956             /* "+clip-mask" Remove the write mask */
01957             (void) SetImageMask(_image,(Image *) NULL,_exception);
01958             break;
01959           }
01960           mask_image=GetImageCache(_image_info,arg1,_exception);
01961           if (mask_image == (Image *) NULL)
01962             break;
01963           if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
01964             break;
01965           /* Create a write mask from cli_wand mask image */
01966           /* FUTURE: use Alpha operations instead and create a Grey Image */
01967           mask_view=AcquireAuthenticCacheView(mask_image,_exception);
01968           for (y=0; y < (ssize_t) mask_image->rows; y++)
01969           {
01970             q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
01971               _exception);
01972             if (q == (Quantum *) NULL)
01973               break;
01974             for (x=0; x < (ssize_t) mask_image->columns; x++)
01975             {
01976               if (IfMagickFalse(mask_image->matte))
01977                 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
01978               SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
01979               SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
01980               SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
01981               q+=GetPixelChannels(mask_image);
01982             }
01983             if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
01984               break;
01985           }
01986           /* clean up and set the write mask */
01987           mask_view=DestroyCacheView(mask_view);
01988           mask_image->matte=MagickTrue;
01989           (void) SetImageMask(_image,mask_image,_exception);
01990           mask_image=DestroyImage(mask_image);
01991           break;
01992         }
01993       if (LocaleCompare("clip-path",option+1) == 0)
01994         {
01995           (void) ClipImagePath(_image,arg1,normal_op,_exception);
01996           break;
01997         }
01998       if (LocaleCompare("colorize",option+1) == 0)
01999         {
02000           if (IfMagickFalse(IsGeometry(arg1)))
02001             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02002           new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
02003           break;
02004         }
02005       if (LocaleCompare("color-matrix",option+1) == 0)
02006         {
02007           KernelInfo
02008             *kernel;
02009 
02010           kernel=AcquireKernelInfo(arg1);
02011           if (kernel == (KernelInfo *) NULL)
02012             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02013           new_image=ColorMatrixImage(_image,kernel,_exception);
02014           kernel=DestroyKernelInfo(kernel);
02015           break;
02016         }
02017       if (LocaleCompare("colors",option+1) == 0)
02018         {
02019           /* Reduce the number of colors in the image.
02020              FUTURE: also provide 'plus version with image 'color counts'
02021           */
02022           _quantize_info->number_colors=StringToUnsignedLong(arg1);
02023           if (_quantize_info->number_colors == 0)
02024             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02025           if ((_image->storage_class == DirectClass) ||
02026               _image->colors > _quantize_info->number_colors)
02027             (void) QuantizeImage(_quantize_info,_image,_exception);
02028           else
02029             (void) CompressImageColormap(_image,_exception);
02030           break;
02031         }
02032       if (LocaleCompare("colorspace",option+1) == 0)
02033         {
02034           /* WARNING: this is both a image_info setting (already done)
02035                       and a operator to change image colorspace.
02036 
02037              FUTURE: default colorspace should be sRGB!
02038              Unless some type of 'linear colorspace' mode is set.
02039 
02040              Note that +colorspace sets "undefined" or no effect on
02041              new images, but forces images already in memory back to RGB!
02042              That seems to be a little strange!
02043           */
02044           (void) TransformImageColorspace(_image,
02045                     IfNormalOp ? _image_info->colorspace : RGBColorspace,
02046                     _exception);
02047           break;
02048         }
02049       if (LocaleCompare("contrast",option+1) == 0)
02050         {
02051           CLIWandWarnReplaced(normal_op?"-level":"+level");
02052           (void) ContrastImage(_image,normal_op,_exception);
02053           break;
02054         }
02055       if (LocaleCompare("contrast-stretch",option+1) == 0)
02056         {
02057           double
02058             black_point,
02059             white_point;
02060 
02061           MagickStatusType
02062             flags;
02063 
02064           flags=ParseGeometry(arg1,&geometry_info);
02065           if ((flags & RhoValue) == 0)
02066             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02067           black_point=geometry_info.rho;
02068           white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
02069             black_point;
02070           if ((flags & PercentValue) != 0) {
02071               black_point*=(double) _image->columns*_image->rows/100.0;
02072               white_point*=(double) _image->columns*_image->rows/100.0;
02073             }
02074           white_point=(MagickRealType) _image->columns*_image->rows-
02075             white_point;
02076           (void) ContrastStretchImage(_image,black_point,white_point,
02077             _exception);
02078           break;
02079         }
02080       if (LocaleCompare("convolve",option+1) == 0)
02081         {
02082           KernelInfo
02083             *kernel_info;
02084 
02085           kernel_info=AcquireKernelInfo(arg1);
02086           if (kernel_info == (KernelInfo *) NULL)
02087             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02088           new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
02089             _exception);
02090           kernel_info=DestroyKernelInfo(kernel_info);
02091           break;
02092         }
02093       if (LocaleCompare("crop",option+1) == 0)
02094         {
02095           /* WARNING: This can generate multiple images! */
02096           if (IfMagickFalse(IsGeometry(arg1)))
02097             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02098           new_image=CropImageToTiles(_image,arg1,_exception);
02099           break;
02100         }
02101       if (LocaleCompare("cycle",option+1) == 0)
02102         {
02103           if (IfMagickFalse(IsGeometry(arg1)))
02104             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02105           (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
02106             _exception);
02107           break;
02108         }
02109       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02110     }
02111     case 'd':
02112     {
02113       if (LocaleCompare("decipher",option+1) == 0)
02114         {
02115           StringInfo
02116             *passkey;
02117 
02118           passkey=FileToStringInfo(arg1,~0,_exception);
02119           if (passkey == (StringInfo *) NULL)
02120             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02121 
02122           (void) PasskeyDecipherImage(_image,passkey,_exception);
02123           passkey=DestroyStringInfo(passkey);
02124           break;
02125         }
02126       if (LocaleCompare("depth",option+1) == 0)
02127         {
02128           /* The _image_info->depth setting has already been set
02129              We just need to apply it to all images in current sequence
02130 
02131              WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
02132              That is it really is an operation, not a setting! Arrgghhh
02133 
02134              FUTURE: this should not be an operator!!!
02135           */
02136           (void) SetImageDepth(_image,_image_info->depth,_exception);
02137           break;
02138         }
02139       if (LocaleCompare("deskew",option+1) == 0)
02140         {
02141           double
02142             threshold;
02143 
02144           if (IfNormalOp) {
02145             if (IfMagickFalse(IsGeometry(arg1)))
02146               CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02147             threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
02148           }
02149           else
02150             threshold=40.0*QuantumRange/100.0;
02151           new_image=DeskewImage(_image,threshold,_exception);
02152           break;
02153         }
02154       if (LocaleCompare("despeckle",option+1) == 0)
02155         {
02156           new_image=DespeckleImage(_image,_exception);
02157           break;
02158         }
02159       if (LocaleCompare("distort",option+1) == 0)
02160         {
02161           double
02162             *args;
02163 
02164           ssize_t
02165             count;
02166 
02167           parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
02168           if ( parse < 0 )
02169              CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
02170                                       option,arg1);
02171           if ((DistortImageMethod) parse == ResizeDistortion)
02172             {
02173                double
02174                  resize_args[2];
02175                /* Special Case - Argument is actually a resize geometry!
02176                ** Convert that to an appropriate distortion argument array.
02177                ** FUTURE: make a separate special resize operator
02178                     Roll into a resize special operator */
02179                if (IfMagickFalse(IsGeometry(arg2)))
02180                  CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
02181                                            option,arg2);
02182                (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
02183                resize_args[0]=(double) geometry.width;
02184                resize_args[1]=(double) geometry.height;
02185                new_image=DistortImage(_image,(DistortImageMethod) parse,
02186                     (size_t)2,resize_args,MagickTrue,_exception);
02187                break;
02188             }
02189           /* convert argument string into an array of doubles */
02190           args = StringToArrayOfDoubles(arg2,&count,_exception);
02191           if (args == (double *)NULL )
02192             CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
02193 
02194           new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
02195                plus_alt_op,_exception);
02196           args=(double *) RelinquishMagickMemory(args);
02197           break;
02198         }
02199       if (LocaleCompare("draw",option+1) == 0)
02200         {
02201           (void) CloneString(&_draw_info->primitive,arg1);
02202           (void) DrawImage(_image,_draw_info,_exception);
02203           (void) CloneString(&_draw_info->primitive,(char *)NULL);
02204           break;
02205         }
02206       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02207     }
02208     case 'e':
02209     {
02210       if (LocaleCompare("edge",option+1) == 0)
02211         {
02212           flags=ParseGeometry(arg1,&geometry_info);
02213           if ((flags & (RhoValue|SigmaValue)) == 0)
02214             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02215           if ((flags & SigmaValue) == 0)
02216             geometry_info.sigma=1.0;
02217           new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
02218                _exception);
02219           break;
02220         }
02221       if (LocaleCompare("emboss",option+1) == 0)
02222         {
02223           flags=ParseGeometry(arg1,&geometry_info);
02224           if ((flags & (RhoValue|SigmaValue)) == 0)
02225             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02226           if ((flags & SigmaValue) == 0)
02227             geometry_info.sigma=1.0;
02228           new_image=EmbossImage(_image,geometry_info.rho,
02229             geometry_info.sigma,_exception);
02230           break;
02231         }
02232       if (LocaleCompare("encipher",option+1) == 0)
02233         {
02234           StringInfo
02235             *passkey;
02236 
02237           passkey=FileToStringInfo(arg1,~0,_exception);
02238           if (passkey != (StringInfo *) NULL)
02239             {
02240               (void) PasskeyEncipherImage(_image,passkey,_exception);
02241               passkey=DestroyStringInfo(passkey);
02242             }
02243           break;
02244         }
02245       if (LocaleCompare("enhance",option+1) == 0)
02246         {
02247           new_image=EnhanceImage(_image,_exception);
02248           break;
02249         }
02250       if (LocaleCompare("equalize",option+1) == 0)
02251         {
02252           (void) EqualizeImage(_image,_exception);
02253           break;
02254         }
02255       if (LocaleCompare("evaluate",option+1) == 0)
02256         {
02257           double
02258             constant;
02259 
02260           parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
02261           if ( parse < 0 )
02262             CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
02263                  option,arg1);
02264           if (IfMagickFalse(IsGeometry(arg2)))
02265             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
02266           constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
02267           (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
02268                _exception);
02269           break;
02270         }
02271       if (LocaleCompare("extent",option+1) == 0)
02272         {
02273           if (IfMagickFalse(IsGeometry(arg1)))
02274             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02275           flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
02276           if (geometry.width == 0)
02277             geometry.width=_image->columns;
02278           if (geometry.height == 0)
02279             geometry.height=_image->rows;
02280           new_image=ExtentImage(_image,&geometry,_exception);
02281           break;
02282         }
02283       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02284     }
02285     case 'f':
02286     {
02287       if (LocaleCompare("features",option+1) == 0)
02288         {
02289           /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
02290           if (IfPlusOp) {
02291               (void) DeleteImageArtifact(_image,"identify:features");
02292               break;
02293             }
02294           (void) SetImageArtifact(_image,"identify:features","true");
02295           (void) SetImageArtifact(_image,"verbose","true");
02296           break;
02297         }
02298       if (LocaleCompare("flip",option+1) == 0)
02299         {
02300           new_image=FlipImage(_image,_exception);
02301           break;
02302         }
02303       if (LocaleCompare("flop",option+1) == 0)
02304         {
02305           new_image=FlopImage(_image,_exception);
02306           break;
02307         }
02308       if (LocaleCompare("floodfill",option+1) == 0)
02309         {
02310           PixelInfo
02311             target;
02312 
02313           if (IfMagickFalse(IsGeometry(arg1)))
02314             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02315           (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
02316           (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
02317           (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
02318                     geometry.y,plus_alt_op,_exception);
02319           break;
02320         }
02321       if (LocaleCompare("frame",option+1) == 0)
02322         {
02323           FrameInfo
02324             frame_info;
02325 
02326           CompositeOperator
02327             compose;
02328 
02329           const char*
02330             value;
02331 
02332           value=GetImageOption(_image_info,"compose");
02333           if (value != (const char *) NULL)
02334             compose=(CompositeOperator) ParseCommandOption(
02335                  MagickComposeOptions,MagickFalse,value);
02336           else
02337             compose=OverCompositeOp;  /* use Over not _image->compose */
02338 
02339           if (IfMagickFalse(IsGeometry(arg1)))
02340             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02341           flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
02342           frame_info.width=geometry.width;
02343           frame_info.height=geometry.height;
02344           if ((flags & HeightValue) == 0)
02345             frame_info.height=geometry.width;
02346           frame_info.outer_bevel=geometry.x;
02347           frame_info.inner_bevel=geometry.y;
02348           frame_info.x=(ssize_t) frame_info.width;
02349           frame_info.y=(ssize_t) frame_info.height;
02350           frame_info.width=_image->columns+2*frame_info.width;
02351           frame_info.height=_image->rows+2*frame_info.height;
02352           new_image=FrameImage(_image,&frame_info,compose,_exception);
02353           break;
02354         }
02355       if (LocaleCompare("function",option+1) == 0)
02356         {
02357           double
02358             *args;
02359 
02360           ssize_t
02361             count;
02362 
02363           parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
02364           if ( parse < 0 )
02365             CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
02366                  option,arg1);
02367           /* convert argument string into an array of doubles */
02368           args = StringToArrayOfDoubles(arg2,&count,_exception);
02369           if (args == (double *)NULL )
02370             CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
02371 
02372           (void) FunctionImage(_image,(MagickFunction)parse,count,args,
02373                _exception);
02374           args=(double *) RelinquishMagickMemory(args);
02375           break;
02376         }
02377       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02378     }
02379     case 'g':
02380     {
02381       if (LocaleCompare("gamma",option+1) == 0)
02382         {
02383           if (IfMagickFalse(IsGeometry(arg1)))
02384             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02385           if (IfNormalOp)
02386             (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
02387                  _exception);
02388           else
02389             _image->gamma=StringToDouble(arg1,(char **) NULL);
02390           break;
02391         }
02392       if (LocaleCompare("gaussian-blur",option+1) == 0)
02393         {
02394           flags=ParseGeometry(arg1,&geometry_info);
02395           if ((flags & (RhoValue|SigmaValue)) == 0)
02396             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02397           if ((flags & SigmaValue) == 0)
02398             geometry_info.sigma=1.0;
02399           new_image=GaussianBlurImage(_image,geometry_info.rho,
02400             geometry_info.sigma,_exception);
02401           break;
02402         }
02403       if (LocaleCompare("gaussian",option+1) == 0)
02404         {
02405           CLIWandWarnReplaced("-gaussian-blur");
02406           CLISimpleOperatorImage(cli_wand,"-gaussian-blur",arg1,NULL);
02407         }
02408       if (LocaleCompare("geometry",option+1) == 0)
02409         {
02410           /*
02411             Record Image offset for composition. (A Setting)
02412             Resize last _image. (ListOperator)  -- DEPRECIATE
02413             FUTURE: Why if no 'offset' does this resize ALL images?
02414             Also why is the setting recorded in the IMAGE non-sense!
02415           */
02416           if (IfPlusOp)
02417             { /* remove the previous composition geometry offset! */
02418               if (_image->geometry != (char *) NULL)
02419                 _image->geometry=DestroyString(_image->geometry);
02420               break;
02421             }
02422           if (IfMagickFalse(IsGeometry(arg1)))
02423             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02424           flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
02425           if (((flags & XValue) != 0) || ((flags & YValue) != 0))
02426             (void) CloneString(&_image->geometry,arg1);
02427           else
02428             new_image=ResizeImage(_image,geometry.width,geometry.height,
02429               _image->filter,_exception);
02430           break;
02431         }
02432       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02433     }
02434     case 'i':
02435     {
02436       if (LocaleCompare("identify",option+1) == 0)
02437         {
02438           const char
02439             *format,
02440             *text;
02441 
02442           format=GetImageOption(_image_info,"format");
02443           if (format == (char *) NULL) {
02444             (void) IdentifyImage(_image,stdout,_image_info->verbose,_exception);
02445             break;
02446           }
02447           text=InterpretImageProperties(_image_info,_image,format,_exception);
02448           if (text == (char *) NULL)
02449             CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
02450                  option);
02451           (void) fputs(text,stdout);
02452           (void) fputc('\n',stdout);
02453           text=DestroyString((char *)text);
02454           break;
02455         }
02456       if (LocaleCompare("implode",option+1) == 0)
02457         {
02458           flags=ParseGeometry(arg1,&geometry_info);
02459           if ((flags & RhoValue) == 0)
02460             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02461           new_image=ImplodeImage(_image,geometry_info.rho,_image->interpolate,
02462                _exception);
02463           break;
02464         }
02465       if (LocaleCompare("interpolative-resize",option+1) == 0)
02466         {
02467           /* FUTURE: New to IMv7
02468                Roll into a resize special operator */
02469           if (IfMagickFalse(IsGeometry(arg1)))
02470             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02471           (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
02472           new_image=InterpolativeResizeImage(_image,geometry.width,
02473                geometry.height,_image->interpolate,_exception);
02474           break;
02475         }
02476       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02477     }
02478     case 'l':
02479     {
02480       if (LocaleCompare("lat",option+1) == 0)
02481         {
02482           flags=ParseGeometry(arg1,&geometry_info);
02483           if ((flags & (RhoValue|SigmaValue)) == 0)
02484             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02485           if ((flags & PercentValue) != 0)
02486             geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
02487           new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
02488                (size_t) geometry_info.sigma,(double) geometry_info.xi,
02489                _exception);
02490           break;
02491         }
02492       if (LocaleCompare("level",option+1) == 0)
02493         {
02494           MagickRealType
02495             black_point,
02496             gamma,
02497             white_point;
02498 
02499           MagickStatusType
02500             flags;
02501 
02502           flags=ParseGeometry(arg1,&geometry_info);
02503           if ((flags & RhoValue) == 0)
02504             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02505           black_point=geometry_info.rho;
02506           white_point=(MagickRealType) QuantumRange;
02507           if ((flags & SigmaValue) != 0)
02508             white_point=geometry_info.sigma;
02509           gamma=1.0;
02510           if ((flags & XiValue) != 0)
02511             gamma=geometry_info.xi;
02512           if ((flags & PercentValue) != 0)
02513             {
02514               black_point*=(MagickRealType) (QuantumRange/100.0);
02515               white_point*=(MagickRealType) (QuantumRange/100.0);
02516             }
02517           if ((flags & SigmaValue) == 0)
02518             white_point=(MagickRealType) QuantumRange-black_point;
02519           if (IfPlusOp || ((flags & AspectValue) != 0))
02520             (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
02521           else
02522             (void) LevelImage(_image,black_point,white_point,gamma,_exception);
02523           break;
02524         }
02525       if (LocaleCompare("level-colors",option+1) == 0)
02526         {
02527           char
02528             token[MaxTextExtent];
02529 
02530           const char
02531             *p;
02532 
02533           PixelInfo
02534             black_point,
02535             white_point;
02536 
02537           p=(const char *) arg1;
02538           GetMagickToken(p,&p,token);  /* get black point color */
02539           if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
02540             (void) QueryColorCompliance(token,AllCompliance,
02541                       &black_point,_exception);
02542           else
02543             (void) QueryColorCompliance("#000000",AllCompliance,
02544                       &black_point,_exception);
02545           if (isalpha((int) token[0]) || (token[0] == '#'))
02546             GetMagickToken(p,&p,token);
02547           if (*token == '\0')
02548             white_point=black_point; /* set everything to that color */
02549           else
02550             {
02551               if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
02552                 GetMagickToken(p,&p,token); /* Get white point color. */
02553               if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
02554                 (void) QueryColorCompliance(token,AllCompliance,
02555                            &white_point,_exception);
02556               else
02557                 (void) QueryColorCompliance("#ffffff",AllCompliance,
02558                            &white_point,_exception);
02559             }
02560           (void) LevelImageColors(_image,&black_point,&white_point,
02561                      plus_alt_op,_exception);
02562           break;
02563         }
02564       if (LocaleCompare("linear-stretch",option+1) == 0)
02565         {
02566           double
02567             black_point,
02568             white_point;
02569 
02570           MagickStatusType
02571             flags;
02572 
02573           flags=ParseGeometry(arg1,&geometry_info);
02574           if ((flags & RhoValue) == 0)
02575             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02576           black_point=geometry_info.rho;
02577           white_point=(MagickRealType) _image->columns*_image->rows;
02578           if ((flags & SigmaValue) != 0)
02579             white_point=geometry_info.sigma;
02580           if ((flags & PercentValue) != 0)
02581             {
02582               black_point*=(double) _image->columns*_image->rows/100.0;
02583               white_point*=(double) _image->columns*_image->rows/100.0;
02584             }
02585           if ((flags & SigmaValue) == 0)
02586             white_point=(MagickRealType) _image->columns*_image->rows-
02587               black_point;
02588           (void) LinearStretchImage(_image,black_point,white_point,_exception);
02589           break;
02590         }
02591       if (LocaleCompare("liquid-rescale",option+1) == 0)
02592         {
02593           /* FUTURE: Roll into a resize special operator */
02594           if (IfMagickFalse(IsGeometry(arg1)))
02595             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02596           flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
02597           if ((flags & XValue) == 0)
02598             geometry.x=1;
02599           if ((flags & YValue) == 0)
02600             geometry.y=0;
02601           new_image=LiquidRescaleImage(_image,geometry.width,
02602             geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
02603           break;
02604         }
02605       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02606     }
02607     case 'm':
02608     {
02609       if (LocaleCompare("map",option+1) == 0)
02610         {
02611           CLIWandWarnReplaced("-remap");
02612           CLISimpleOperatorImage(cli_wand,"-remap",NULL,NULL);
02613           break;
02614         }
02615       if (LocaleCompare("mask",option+1) == 0)
02616         {
02617           Image
02618             *mask;
02619 
02620           if (IfPlusOp)
02621             { /* Remove a mask. */
02622               (void) SetImageMask(_image,(Image *) NULL,_exception);
02623               break;
02624             }
02625           /* Set the image mask. */
02626           mask=GetImageCache(_image_info,arg1,_exception);
02627           if (mask == (Image *) NULL)
02628             break;
02629           (void) SetImageMask(_image,mask,_exception);
02630           mask=DestroyImage(mask);
02631           break;
02632         }
02633       if (LocaleCompare("matte",option+1) == 0)
02634         {
02635           CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
02636           (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
02637                          DeactivateAlphaChannel, _exception);
02638           break;
02639         }
02640       if (LocaleCompare("median",option+1) == 0)
02641         {
02642           CLIWandWarnReplaced("-statistic Median");
02643           CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
02644           break;
02645         }
02646       if (LocaleCompare("mode",option+1) == 0)
02647         {
02648           /* FUTURE: note this is also a special "montage" option */
02649           CLIWandWarnReplaced("-statistic Mode");
02650           CLISimpleOperatorImage(cli_wand,"-statistic","Mode",arg1);
02651           break;
02652         }
02653       if (LocaleCompare("modulate",option+1) == 0)
02654         {
02655           if (IfMagickFalse(IsGeometry(arg1)))
02656             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02657           (void) ModulateImage(_image,arg1,_exception);
02658           break;
02659         }
02660       if (LocaleCompare("monitor",option+1) == 0)
02661         {
02662           (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
02663                 (MagickProgressMonitor) NULL,(void *) NULL);
02664           break;
02665         }
02666       if (LocaleCompare("monochrome",option+1) == 0)
02667         {
02668           (void) SetImageType(_image,BilevelType,_exception);
02669           break;
02670         }
02671       if (LocaleCompare("morphology",option+1) == 0)
02672         {
02673           char
02674             token[MaxTextExtent];
02675 
02676           const char
02677             *p;
02678 
02679           KernelInfo
02680             *kernel;
02681 
02682           ssize_t
02683             iterations;
02684 
02685           p=arg1;
02686           GetMagickToken(p,&p,token);
02687           parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
02688           if ( parse < 0 )
02689             CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
02690                  option,arg1);
02691           iterations=1L;
02692           GetMagickToken(p,&p,token);
02693           if ((*p == ':') || (*p == ','))
02694             GetMagickToken(p,&p,token);
02695           if ((*p != '\0'))
02696             iterations=(ssize_t) StringToLong(p);
02697           kernel=AcquireKernelInfo(arg2);
02698           if (kernel == (KernelInfo *) NULL)
02699             CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
02700                  option,arg2);
02701           new_image=MorphologyImage(_image,(MorphologyMethod)parse,
02702                iterations,kernel,_exception);
02703           kernel=DestroyKernelInfo(kernel);
02704           break;
02705         }
02706       if (LocaleCompare("motion-blur",option+1) == 0)
02707         {
02708           flags=ParseGeometry(arg1,&geometry_info);
02709           if ((flags & (RhoValue|SigmaValue)) == 0)
02710             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02711           if ((flags & SigmaValue) == 0)
02712             geometry_info.sigma=1.0;
02713           new_image=MotionBlurImage(_image,geometry_info.rho,
02714             geometry_info.sigma,geometry_info.xi,_exception);
02715           break;
02716         }
02717       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02718     }
02719     case 'n':
02720     {
02721       if (LocaleCompare("negate",option+1) == 0)
02722         {
02723           (void) NegateImage(_image, plus_alt_op, _exception);
02724           break;
02725         }
02726       if (LocaleCompare("noise",option+1) == 0)
02727         {
02728           double
02729             attenuate;
02730 
02731           const char*
02732             value;
02733 
02734           if (IfNormalOp)
02735             {
02736               CLIWandWarnReplaced("-statistic NonPeak");
02737               CLISimpleOperatorImage(cli_wand,"-statistic","NonPeak",arg1);
02738               break;
02739             }
02740           parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
02741           if ( parse < 0 )
02742             CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
02743                 option,arg1);
02744           attenuate=1.0;
02745           value=GetImageOption(_image_info,"attenuate");
02746           if  (value != (const char *) NULL)
02747             attenuate=StringToDouble(value,(char **) NULL);
02748           new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
02749                _exception);
02750           break;
02751         }
02752       if (LocaleCompare("normalize",option+1) == 0)
02753         {
02754           (void) NormalizeImage(_image,_exception);
02755           break;
02756         }
02757       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02758     }
02759     case 'o':
02760     {
02761       if (LocaleCompare("opaque",option+1) == 0)
02762         {
02763           PixelInfo
02764             target;
02765 
02766           (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
02767           (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
02768                _exception);
02769           break;
02770         }
02771       if (LocaleCompare("ordered-dither",option+1) == 0)
02772         {
02773           (void) OrderedPosterizeImage(_image,arg1,_exception);
02774           break;
02775         }
02776       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02777     }
02778     case 'p':
02779     {
02780       if (LocaleCompare("paint",option+1) == 0)
02781         {
02782           flags=ParseGeometry(arg1,&geometry_info);
02783           if ((flags & (RhoValue|SigmaValue)) == 0)
02784             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02785           new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
02786                _exception);
02787           break;
02788         }
02789       if (LocaleCompare("polaroid",option+1) == 0)
02790         {
02791           const char
02792             *caption;
02793 
02794           double
02795             angle;
02796 
02797           if (IfPlusOp) {
02798             RandomInfo
02799             *random_info;
02800 
02801             random_info=AcquireRandomInfo();
02802             angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
02803             random_info=DestroyRandomInfo(random_info);
02804           }
02805           else {
02806             flags=ParseGeometry(arg1,&geometry_info);
02807             if ((flags & RhoValue) == 0)
02808               CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02809             angle=geometry_info.rho;
02810           }
02811           caption=GetImageProperty(_image,"caption",_exception);
02812           new_image=PolaroidImage(_image,_draw_info,caption,angle,
02813             _image->interpolate,_exception);
02814           break;
02815         }
02816       if (LocaleCompare("posterize",option+1) == 0)
02817         {
02818           flags=ParseGeometry(arg1,&geometry_info);
02819           if ((flags & RhoValue) == 0)
02820             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02821           (void) PosterizeImage(_image,(size_t) geometry_info.rho,
02822                _quantize_info->dither,_exception);
02823           break;
02824         }
02825       if (LocaleCompare("preview",option+1) == 0)
02826         {
02827           /* FUTURE: should be a 'Genesis' option?
02828              Option however is also in WandSettingOptionInfo()
02829              Why???
02830           */
02831           parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
02832           if ( parse < 0 )
02833             CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
02834                 option,arg1);
02835           new_image=PreviewImage(_image,(PreviewType)parse,_exception);
02836           break;
02837         }
02838       if (LocaleCompare("profile",option+1) == 0)
02839         {
02840           const char
02841             *name;
02842 
02843           const StringInfo
02844             *profile;
02845 
02846           Image
02847             *profile_image;
02848 
02849           ImageInfo
02850             *profile_info;
02851 
02852           if (IfPlusOp)
02853             { /* Remove a profile from the _image.  */
02854               (void) ProfileImage(_image,arg1,(const unsigned char *)
02855                 NULL,0,_exception);
02856               break;
02857             }
02858           /* Associate a profile with the _image.  */
02859           profile_info=CloneImageInfo(_image_info);
02860           profile=GetImageProfile(_image,"iptc");
02861           if (profile != (StringInfo *) NULL)
02862             profile_info->profile=(void *) CloneStringInfo(profile);
02863           profile_image=GetImageCache(profile_info,arg1,_exception);
02864           profile_info=DestroyImageInfo(profile_info);
02865           if (profile_image == (Image *) NULL)
02866             {
02867               StringInfo
02868                 *profile;
02869 
02870               profile_info=CloneImageInfo(_image_info);
02871               (void) CopyMagickString(profile_info->filename,arg1,
02872                 MaxTextExtent);
02873               profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
02874               if (profile != (StringInfo *) NULL)
02875                 {
02876                   (void) ProfileImage(_image,profile_info->magick,
02877                     GetStringInfoDatum(profile),(size_t)
02878                     GetStringInfoLength(profile),_exception);
02879                   profile=DestroyStringInfo(profile);
02880                 }
02881               profile_info=DestroyImageInfo(profile_info);
02882               break;
02883             }
02884           ResetImageProfileIterator(profile_image);
02885           name=GetNextImageProfile(profile_image);
02886           while (name != (const char *) NULL)
02887           {
02888             profile=GetImageProfile(profile_image,name);
02889             if (profile != (StringInfo *) NULL)
02890               (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
02891                 (size_t) GetStringInfoLength(profile),_exception);
02892             name=GetNextImageProfile(profile_image);
02893           }
02894           profile_image=DestroyImage(profile_image);
02895           break;
02896         }
02897       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02898     }
02899     case 'r':
02900     {
02901       if (LocaleCompare("radial-blur",option+1) == 0)
02902         {
02903           flags=ParseGeometry(arg1,&geometry_info);
02904           if ((flags & RhoValue) == 0)
02905             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02906           new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
02907           break;
02908         }
02909       if (LocaleCompare("raise",option+1) == 0)
02910         {
02911           if (IfMagickFalse(IsGeometry(arg1)))
02912             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02913           flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
02914           if ((flags & SigmaValue) == 0)
02915             geometry.height=geometry.width;
02916           (void) RaiseImage(_image,&geometry,normal_op,_exception);
02917           break;
02918         }
02919       if (LocaleCompare("random-threshold",option+1) == 0)
02920         {
02921           if (IfMagickFalse(IsGeometry(arg1)))
02922             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02923           (void) RandomThresholdImage(_image,arg1,_exception);
02924           break;
02925         }
02926       if (LocaleCompare("recolor",option+1) == 0)
02927         {
02928           CLIWandWarnReplaced("-color-matrix");
02929           CLISimpleOperatorImage(cli_wand,"-color-matrix",arg1,NULL);
02930         }
02931       if (LocaleCompare("remap",option+1) == 0)
02932         {
02933           Image
02934             *remap_image;
02935 
02936           remap_image=GetImageCache(_image_info,arg1,_exception);
02937           if (remap_image == (Image *) NULL)
02938             break;
02939           (void) RemapImage(_quantize_info,_image,remap_image,_exception);
02940           remap_image=DestroyImage(remap_image);
02941           break;
02942         }
02943       if (LocaleCompare("repage",option+1) == 0)
02944         {
02945           if (IfNormalOp)
02946             {
02947               if (IfMagickFalse(IsGeometry(arg1)))
02948                 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
02949                   arg1);
02950               (void) ResetImagePage(_image,arg1);
02951             }
02952           else
02953             (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
02954           break;
02955         }
02956       if (LocaleCompare("resample",option+1) == 0)
02957         {
02958           /* FUTURE: Roll into a resize special operation */
02959           flags=ParseGeometry(arg1,&geometry_info);
02960           if ((flags & (RhoValue|SigmaValue)) == 0)
02961             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02962           if ((flags & SigmaValue) == 0)
02963             geometry_info.sigma=geometry_info.rho;
02964           new_image=ResampleImage(_image,geometry_info.rho,
02965             geometry_info.sigma,_image->filter,_exception);
02966           break;
02967         }
02968       if (LocaleCompare("resize",option+1) == 0)
02969         {
02970           if (IfMagickFalse(IsGeometry(arg1)))
02971             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02972           (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
02973           new_image=ResizeImage(_image,geometry.width,geometry.height,
02974             _image->filter,_exception);
02975           break;
02976         }
02977       if (LocaleCompare("roll",option+1) == 0)
02978         {
02979           if (IfMagickFalse(IsGeometry(arg1)))
02980             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02981           (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
02982           new_image=RollImage(_image,geometry.x,geometry.y,_exception);
02983           break;
02984         }
02985       if (LocaleCompare("rotate",option+1) == 0)
02986         {
02987           flags=ParseGeometry(arg1,&geometry_info);
02988           if ((flags & RhoValue) == 0)
02989             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
02990           if ((flags & GreaterValue) != 0 && (_image->columns <= _image->rows))
02991             break;
02992           if ((flags & LessValue) != 0 && (_image->columns >= _image->rows))
02993             break;
02994           new_image=RotateImage(_image,geometry_info.rho,_exception);
02995           break;
02996         }
02997       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
02998     }
02999     case 's':
03000     {
03001       if (LocaleCompare("sample",option+1) == 0)
03002         {
03003           /* FUTURE: Roll into a resize special operator */
03004           if (IfMagickFalse(IsGeometry(arg1)))
03005             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03006           (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
03007           new_image=SampleImage(_image,geometry.width,geometry.height,
03008             _exception);
03009           break;
03010         }
03011       if (LocaleCompare("scale",option+1) == 0)
03012         {
03013           /* FUTURE: Roll into a resize special operator */
03014           if (IfMagickFalse(IsGeometry(arg1)))
03015             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03016           (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
03017           new_image=ScaleImage(_image,geometry.width,geometry.height,
03018             _exception);
03019           break;
03020         }
03021       if (LocaleCompare("segment",option+1) == 0)
03022         {
03023           flags=ParseGeometry(arg1,&geometry_info);
03024           if ((flags & (RhoValue|SigmaValue)) == 0)
03025             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03026           if ((flags & SigmaValue) == 0)
03027             geometry_info.sigma=1.0;
03028           (void) SegmentImage(_image,_image->colorspace,
03029             _image_info->verbose,geometry_info.rho,geometry_info.sigma,
03030             _exception);
03031           break;
03032         }
03033       if (LocaleCompare("selective-blur",option+1) == 0)
03034         {
03035           flags=ParseGeometry(arg1,&geometry_info);
03036           if ((flags & (RhoValue|SigmaValue)) == 0)
03037             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03038           if ((flags & SigmaValue) == 0)
03039             geometry_info.sigma=1.0;
03040           if ((flags & PercentValue) != 0)
03041             geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
03042           new_image=SelectiveBlurImage(_image,geometry_info.rho,
03043             geometry_info.sigma,geometry_info.xi,_exception);
03044           break;
03045         }
03046       if (LocaleCompare("separate",option+1) == 0)
03047         {
03048           /* WARNING: This can generate multiple images! */
03049           /* FUTURE - this may be replaced by a "-channel" method */
03050           new_image=SeparateImages(_image,_exception);
03051           break;
03052         }
03053       if (LocaleCompare("sepia-tone",option+1) == 0)
03054         {
03055           if (IfMagickFalse(IsGeometry(arg1)))
03056             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03057           new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
03058                  (double) QuantumRange+1.0),_exception);
03059           break;
03060         }
03061       if (LocaleCompare("set",option+1) == 0)
03062         {
03063           char
03064             *value;
03065 
03066           if (IfPlusOp) {
03067               if (LocaleNCompare(arg1,"registry:",9) == 0)
03068                 (void) DeleteImageRegistry(arg1+9);
03069               else
03070                 if (LocaleNCompare(arg1,"option:",7) == 0)
03071                   {
03072                     (void) DeleteImageOption(_image_info,arg1+7);
03073                     (void) DeleteImageArtifact(_image,arg1+7);
03074                   }
03075                 else
03076                   (void) DeleteImageProperty(_image,arg1);
03077               break;
03078             }
03079           value=InterpretImageProperties(_image_info,_image,arg2,_exception);
03080           if (value == (char *) NULL)
03081             CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
03082                   option);
03083           if (LocaleNCompare(arg1,"registry:",9) == 0)
03084             (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
03085           else
03086             if (LocaleNCompare(arg1,"option:",7) == 0)
03087               {
03088                 (void) SetImageOption(_image_info,arg1+7,value);
03089                 (void) SetImageArtifact(_image,arg1+7,value);
03090               }
03091             else
03092               (void) SetImageProperty(_image,arg1,value,_exception);
03093           value=DestroyString(value);
03094           break;
03095         }
03096       if (LocaleCompare("shade",option+1) == 0)
03097         {
03098           flags=ParseGeometry(arg1,&geometry_info);
03099           if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
03100             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03101           new_image=ShadeImage(_image,normal_op,geometry_info.rho,
03102                geometry_info.sigma,_exception);
03103           break;
03104         }
03105       if (LocaleCompare("shadow",option+1) == 0)
03106         {
03107           flags=ParseGeometry(arg1,&geometry_info);
03108           if ((flags & (RhoValue|SigmaValue)) == 0)
03109             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03110           if ((flags & SigmaValue) == 0)
03111             geometry_info.sigma=1.0;
03112           if ((flags & XiValue) == 0)
03113             geometry_info.xi=4.0;
03114           if ((flags & PsiValue) == 0)
03115             geometry_info.psi=4.0;
03116           new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
03117             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
03118             ceil(geometry_info.psi-0.5),_exception);
03119           break;
03120         }
03121       if (LocaleCompare("sharpen",option+1) == 0)
03122         {
03123           flags=ParseGeometry(arg1,&geometry_info);
03124           if ((flags & (RhoValue|SigmaValue)) == 0)
03125             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03126           if ((flags & SigmaValue) == 0)
03127             geometry_info.sigma=1.0;
03128           if ((flags & XiValue) == 0)
03129             geometry_info.xi=0.0;
03130           new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
03131            _exception);
03132           break;
03133         }
03134       if (LocaleCompare("shave",option+1) == 0)
03135         {
03136           if (IfMagickFalse(IsGeometry(arg1)))
03137             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03138           flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
03139           new_image=ShaveImage(_image,&geometry,_exception);
03140           break;
03141         }
03142       if (LocaleCompare("shear",option+1) == 0)
03143         {
03144           flags=ParseGeometry(arg1,&geometry_info);
03145           if ((flags & RhoValue) == 0)
03146             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03147           if ((flags & SigmaValue) == 0)
03148             geometry_info.sigma=geometry_info.rho;
03149           new_image=ShearImage(_image,geometry_info.rho,
03150             geometry_info.sigma,_exception);
03151           break;
03152         }
03153       if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
03154         {
03155           flags=ParseGeometry(arg1,&geometry_info);
03156           if ((flags & RhoValue) == 0)
03157             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03158           if ((flags & SigmaValue) == 0)
03159             geometry_info.sigma=(double) QuantumRange/2.0;
03160           if ((flags & PercentValue) != 0)
03161             geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
03162               100.0;
03163           (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
03164                geometry_info.sigma,_exception);
03165           break;
03166         }
03167       if (LocaleCompare("sketch",option+1) == 0)
03168         {
03169           flags=ParseGeometry(arg1,&geometry_info);
03170           if ((flags & (RhoValue|SigmaValue)) == 0)
03171             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03172           if ((flags & SigmaValue) == 0)
03173             geometry_info.sigma=1.0;
03174           new_image=SketchImage(_image,geometry_info.rho,
03175             geometry_info.sigma,geometry_info.xi,_exception);
03176           break;
03177         }
03178       if (LocaleCompare("solarize",option+1) == 0)
03179         {
03180           if (IfMagickFalse(IsGeometry(arg1)))
03181             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03182           (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
03183                  QuantumRange+1.0),_exception);
03184           break;
03185         }
03186       if (LocaleCompare("sparse-color",option+1) == 0)
03187         {
03188           parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
03189           if ( parse < 0 )
03190             CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
03191                 option,arg1);
03192           new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
03193                _exception);
03194           break;
03195         }
03196       if (LocaleCompare("splice",option+1) == 0)
03197         {
03198           if (IfMagickFalse(IsGeometry(arg1)))
03199             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03200           flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
03201           new_image=SpliceImage(_image,&geometry,_exception);
03202           break;
03203         }
03204       if (LocaleCompare("spread",option+1) == 0)
03205         {
03206           flags=ParseGeometry(arg1,&geometry_info);
03207           if ((flags & RhoValue) == 0)
03208             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
03209           new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
03210                _exception);
03211           break;
03212         }
03213       if (LocaleCompare("statistic",option+1) == 0)
03214         {
03215           parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
03216           if ( parse < 0 )
03217             CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
03218                  option,arg1);
03219           flags=ParseGeometry(arg2,&geometry_info);
03220           if ((flags & RhoValue) == 0)
03221             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
03222           if ((flags & SigmaValue) == 0)
03223             geometry_info.sigma=geometry_info.rho;
03224           new_image=StatisticImage(_image,(StatisticType)parse,
03225                (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
03226                _exception);
03227           break;
03228         }
03229       if (LocaleCompare("strip",option+1) == 0)
03230         {
03231           (void) StripImage(_image,_exception);
03232           break;
03233         }
03234       if (LocaleCompare("swirl",option+1) == 0)
03235         {
03236           flags=ParseGeometry(arg2,&geometry_info);
03237           if ((flags & RhoValue) == 0)
03238             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
03239           new_image=SwirlImage(_image,geometry_info.rho,
03240             _image->interpolate,_exception);
03241           break;
03242         }
03243       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03244     }
03245     case 't':
03246     {
03247       if (LocaleCompare("threshold",option+1) == 0)
03248         {
03249           double
03250             threshold;
03251 
03252           threshold=(double) QuantumRange/2;
03253           if (normal_op) {
03254             if (IfMagickFalse(IsGeometry(arg1)))
03255               CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03256             threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
03257           }
03258           (void) BilevelImage(_image,threshold,_exception);
03259           break;
03260         }
03261       if (LocaleCompare("thumbnail",option+1) == 0)
03262         {
03263           if (IfMagickFalse(IsGeometry(arg1)))
03264             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03265           (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
03266           new_image=ThumbnailImage(_image,geometry.width,geometry.height,
03267             _exception);
03268           break;
03269         }
03270       if (LocaleCompare("tint",option+1) == 0)
03271         {
03272           if (IfMagickFalse(IsGeometry(arg1)))
03273             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03274           new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
03275           break;
03276         }
03277       if (LocaleCompare("transform",option+1) == 0)
03278         {
03279           CLIWandWarnReplaced("+distort AffineProjection");
03280           new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
03281           break;
03282         }
03283       if (LocaleCompare("transparent",option+1) == 0)
03284         {
03285           PixelInfo
03286             target;
03287 
03288           (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
03289           (void) TransparentPaintImage(_image,&target,(Quantum)
03290             TransparentAlpha,plus_alt_op,_exception);
03291           break;
03292         }
03293       if (LocaleCompare("transpose",option+1) == 0)
03294         {
03295           new_image=TransposeImage(_image,_exception);
03296           break;
03297         }
03298       if (LocaleCompare("transverse",option+1) == 0)
03299         {
03300           new_image=TransverseImage(_image,_exception);
03301           break;
03302         }
03303       if (LocaleCompare("trim",option+1) == 0)
03304         {
03305           new_image=TrimImage(_image,_exception);
03306           break;
03307         }
03308       if (LocaleCompare("type",option+1) == 0)
03309         {
03310           /* Note that "type" setting should have already been defined */
03311           (void) SetImageType(_image,_image_info->type,_exception);
03312           break;
03313         }
03314       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03315     }
03316     case 'u':
03317     {
03318       if (LocaleCompare("unique",option+1) == 0)
03319         {
03320           /* FUTURE: move to SyncImageSettings() and AcqireImage()???
03321              Option is not documented, bt appears to be for "identify".
03322              We may need a identify specific verbose!
03323           */
03324           if (plus_alt_op) {
03325               (void) DeleteImageArtifact(_image,"identify:unique-colors");
03326               break;
03327             }
03328           (void) SetImageArtifact(_image,"identify:unique-colors","true");
03329           (void) SetImageArtifact(_image,"verbose","true");
03330           break;
03331         }
03332       if (LocaleCompare("unique-colors",option+1) == 0)
03333         {
03334           new_image=UniqueImageColors(_image,_exception);
03335           break;
03336         }
03337       if (LocaleCompare("unsharp",option+1) == 0)
03338         {
03339           flags=ParseGeometry(arg1,&geometry_info);
03340           if ((flags & (RhoValue|SigmaValue)) == 0)
03341             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03342           if ((flags & SigmaValue) == 0)
03343             geometry_info.sigma=1.0;
03344           if ((flags & XiValue) == 0)
03345             geometry_info.xi=1.0;
03346           if ((flags & PsiValue) == 0)
03347             geometry_info.psi=0.05;
03348           new_image=UnsharpMaskImage(_image,geometry_info.rho,
03349             geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
03350           break;
03351         }
03352       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03353     }
03354     case 'v':
03355     {
03356       if (LocaleCompare("verbose",option+1) == 0)
03357         {
03358           /* FUTURE: move to SyncImageSettings() and AcquireImage()???
03359              three places!   ImageArtifact   ImageOption  _image_info->verbose
03360              Some how new images also get this artifact!
03361           */
03362           (void) SetImageArtifact(_image,option+1,
03363                            IfNormalOp ? "true" : "false" );
03364           break;
03365         }
03366       if (LocaleCompare("vignette",option+1) == 0)
03367         {
03368           flags=ParseGeometry(arg1,&geometry_info);
03369           if ((flags & (RhoValue|SigmaValue)) == 0)
03370             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03371           if ((flags & SigmaValue) == 0)
03372             geometry_info.sigma=1.0;
03373           if ((flags & XiValue) == 0)
03374             geometry_info.xi=0.1*_image->columns;
03375           if ((flags & PsiValue) == 0)
03376             geometry_info.psi=0.1*_image->rows;
03377           new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
03378             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
03379             ceil(geometry_info.psi-0.5),_exception);
03380           break;
03381         }
03382       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03383     }
03384     case 'w':
03385     {
03386       if (LocaleCompare("wave",option+1) == 0)
03387         {
03388           flags=ParseGeometry(arg1,&geometry_info);
03389           if ((flags & (RhoValue|SigmaValue)) == 0)
03390             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03391           if ((flags & SigmaValue) == 0)
03392             geometry_info.sigma=1.0;
03393           new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
03394                _image->interpolate,_exception);
03395           break;
03396         }
03397       if (LocaleCompare("white-threshold",option+1) == 0)
03398         {
03399           if (IfMagickFalse(IsGeometry(arg1)))
03400             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03401           (void) WhiteThresholdImage(_image,arg1,_exception);
03402           break;
03403         }
03404       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03405     }
03406     default:
03407       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03408   }
03409   /* clean up percent escape interpreted strings */
03410   if (arg1 != arg1n )
03411     arg1=DestroyString((char *)arg1);
03412   if (arg2 != arg2n )
03413     arg2=DestroyString((char *)arg2);
03414 
03415   /* Replace current image with any image that was generated
03416      and set image point to last image (so image->next is correct) */
03417   if (new_image != (Image *) NULL)
03418     ReplaceImageInListReturnLast(&_image,new_image);
03419 
03420   return;
03421 #undef _image_info
03422 #undef _draw_info
03423 #undef _quantize_info
03424 #undef _image
03425 #undef _exception
03426 #undef IfNormalOp
03427 #undef IfPlusOp
03428 #undef normal_op
03429 #undef plus_alt_op
03430 }
03431 
03432 WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
03433   const char *option, const char *arg1, const char *arg2)
03434 {
03435   size_t
03436     n,
03437     i;
03438 
03439   assert(cli_wand != (MagickCLI *) NULL);
03440   assert(cli_wand->signature == WandSignature);
03441   assert(cli_wand->wand.signature == WandSignature);
03442   assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
03443   if (IfMagickTrue(cli_wand->wand.debug))
03444     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
03445 
03446 #if !USE_WAND_METHODS
03447   /* FUTURE add appropriate tracing */
03448   i=0;
03449   n=GetImageListLength(cli_wand->wand.images);
03450   cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
03451   while (1) {
03452     i++;
03453     CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
03454     if ( cli_wand->wand.images->next == (Image *) NULL )
03455       break;
03456     cli_wand->wand.images=cli_wand->wand.images->next;
03457   }
03458   assert( i == n );
03459   cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
03460 #else
03461   MagickResetIterator(&cli_wand->wand);
03462   while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
03463     CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
03464   MagickResetIterator(&cli_wand->wand);
03465 #endif
03466   return;
03467 }
03468 
03469 /*
03470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03471 %                                                                             %
03472 %                                                                             %
03473 %                                                                             %
03474 +     C L I L i s t O p e r a t o r I m a g e s                               %
03475 %                                                                             %
03476 %                                                                             %
03477 %                                                                             %
03478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03479 %
03480 %  CLIListOperatorImages() applies a single operation that is apply to the
03481 %  entire image list as a whole. The result is often a complete replacment
03482 %  of the image list with a completely new list, or just a single image.
03483 %
03484 %  The format of the MogrifyImage method is:
03485 %
03486 %    void CLIListOperatorImages(MagickCLI *cli_wand,
03487 %        const char *option, const char *arg1, const char *arg2)
03488 %
03489 %  A description of each parameter follows:
03490 %
03491 %    o cli_wand: structure holding settings to be applied
03492 %
03493 %    o option:  The option string for the operation
03494 %
03495 %    o arg1, arg2: optional argument strings to the operation
03496 %        arg2 is currently not used
03497 %
03498 */
03499 WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
03500      const char *option,const char *arg1n, const char *arg2n)
03501 {
03502   ssize_t
03503     parse;
03504 
03505   Image
03506     *new_images;
03507 
03508   const char    /* For percent escape interpretImageProperties() */
03509     *arg1,
03510     *arg2;
03511 
03512 #define _image_info     (cli_wand->wand.image_info)
03513 #define _images         (cli_wand->wand.images)
03514 #define _exception      (cli_wand->wand.exception)
03515 #define _draw_info      (cli_wand->draw_info)
03516 #define _quantize_info  (cli_wand->quantize_info)
03517 #define _process_flags  (cli_wand->process_flags)
03518 #define _option_type    ((CommandOptionFlags) cli_wand->command->flags)
03519 #define IfNormalOp      (*option=='-')
03520 #define IfPlusOp        (*option!='-')
03521 #define normal_op       IsMagickTrue(IfNormalOp)
03522 
03523   assert(cli_wand != (MagickCLI *) NULL);
03524   assert(cli_wand->signature == WandSignature);
03525   assert(cli_wand->wand.signature == WandSignature);
03526   assert(_images != (Image *) NULL);             /* _images must be present */
03527   if (IfMagickTrue(cli_wand->wand.debug))
03528     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
03529 
03530   /* Interpret Percent Escapes in Arguments - using first image */
03531   arg1 = arg1n;
03532   arg2 = arg2n;
03533   if ( (((_process_flags & ProcessInterpretProperities) != 0 )
03534         || ((_option_type & AlwaysInterpretArgsFlag) != 0)
03535        )  && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
03536     /* Interpret Percent escapes in argument 1 */
03537     if (arg1n != (char *) NULL) {
03538       arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
03539       if (arg1 == (char *) NULL) {
03540         CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
03541         arg1=arg1n;  /* use the given argument as is */
03542       }
03543     }
03544     if (arg2n != (char *) NULL) {
03545       arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
03546       if (arg2 == (char *) NULL) {
03547         CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
03548         arg2=arg2n;  /* use the given argument as is */
03549       }
03550     }
03551   }
03552 #undef _option_type
03553 
03554 #if 0
03555   (void) FormatLocaleFile(stderr,
03556     "CLIListOperatorImages: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
03557 #endif
03558 
03559 
03560   new_images=NewImageList();
03561 
03562   switch (*(option+1))
03563   {
03564     case 'a':
03565     {
03566       if (LocaleCompare("append",option+1) == 0)
03567         {
03568           new_images=AppendImages(_images,normal_op,_exception);
03569           break;
03570         }
03571       if (LocaleCompare("average",option+1) == 0)
03572         {
03573           CLIWandWarnReplaced("-evaluate-sequence Mean");
03574           CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
03575           break;
03576         }
03577       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03578     }
03579     case 'c':
03580     {
03581       if (LocaleCompare("channel-fx",option+1) == 0)
03582         {
03583           new_images=ChannelFxImage(_images,arg1,_exception);
03584           break;
03585         }
03586       if (LocaleCompare("clut",option+1) == 0)
03587         {
03588           Image
03589             *clut_image;
03590 
03591           /* FUTURE - make this a compose option, and thus can be used
03592              with layers compose or even compose last image over all other
03593              _images.
03594           */
03595           new_images=RemoveFirstImageFromList(&_images);
03596           clut_image=RemoveLastImageFromList(&_images);
03597           /* FUTURE - produce Exception, rather than silent fail */
03598           if (clut_image == (Image *) NULL)
03599             break;
03600           (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
03601           clut_image=DestroyImage(clut_image);
03602           break;
03603         }
03604       if (LocaleCompare("coalesce",option+1) == 0)
03605         {
03606           new_images=CoalesceImages(_images,_exception);
03607           break;
03608         }
03609       if (LocaleCompare("combine",option+1) == 0)
03610         {
03611           /* FUTURE - this may be replaced by a 'channel' method */
03612           new_images=CombineImages(_images,_exception);
03613           break;
03614         }
03615       if (LocaleCompare("composite",option+1) == 0)
03616         {
03617           CompositeOperator
03618             compose;
03619 
03620           const char*
03621             value;
03622 
03623           MagickBooleanType
03624             clip_to_self;
03625 
03626           Image
03627             *mask_image,
03628             *source_image;
03629 
03630           RectangleInfo
03631             geometry;
03632 
03633           /* Compose value from "-compose" option only */
03634           value=GetImageOption(_image_info,"compose");
03635           if (value == (const char *) NULL)
03636             compose=OverCompositeOp;  /* use Over not source_image->compose */
03637           else
03638             compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
03639               MagickFalse,value);
03640 
03641           /* Get "clip-to-self" expert setting (false is normal) */
03642           value=GetImageOption(_image_info,"compose:clip-to-self");
03643           if (value == (const char *) NULL)
03644             clip_to_self=MagickTrue;
03645           else
03646             clip_to_self=IsStringTrue(GetImageOption(_image_info,
03647               "compose:clip-to-self")); /* if this is true */
03648           value=GetImageOption(_image_info,"compose:outside-overlay");
03649           if (value != (const char *) NULL) {   /* or this false */
03650             /* FUTURE: depreciate warning for "compose:outside-overlay"*/
03651             clip_to_self= IsMagickFalse(IsStringNotFalse(value));
03652           }
03653 
03654           new_images=RemoveFirstImageFromList(&_images);
03655           source_image=RemoveFirstImageFromList(&_images);
03656           if (source_image == (Image *) NULL)
03657             break; /* FUTURE - produce Exception, rather than silent fail */
03658 
03659           /* FUTURE - this should not be here! - should be part of -geometry */
03660           (void) TransformImage(&source_image,(char *) NULL,
03661             source_image->geometry,_exception);
03662 
03663           SetGeometry(source_image,&geometry);
03664           (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
03665           GravityAdjustGeometry(new_images->columns,new_images->rows,
03666                new_images->gravity, &geometry);
03667 
03668           mask_image=RemoveFirstImageFromList(&_images);
03669           if (mask_image != (Image *) NULL)
03670             { /* handle a third write mask image */
03671               if ((compose == DisplaceCompositeOp) ||
03672                   (compose == DistortCompositeOp)) {
03673                 /* Merge Y displacement into X displace/distort map. */
03674                 (void) CompositeImage(source_image,mask_image,
03675                   CopyGreenCompositeOp,MagickTrue,0,0,_exception);
03676                 mask_image=DestroyImage(mask_image);
03677               }
03678               else {
03679                 /* Set a blending mask for the composition.  */
03680                 (void) NegateImage(mask_image,MagickFalse,_exception);
03681                 (void) SetImageMask(source_image,mask_image,_exception);
03682                 mask_image=DestroyImage(mask_image);
03683               }
03684             }
03685           (void) CompositeImage(new_images,source_image,compose,clip_to_self,
03686             geometry.x,geometry.y,_exception);
03687           (void) SetImageMask(new_images,(Image *) NULL,_exception);
03688           source_image=DestroyImage(source_image);
03689           break;
03690         }
03691       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03692     }
03693     case 'd':
03694     {
03695       if (LocaleCompare("deconstruct",option+1) == 0)
03696         {
03697           CLIWandWarnReplaced("-layer CompareAny");
03698           CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
03699           break;
03700         }
03701       if (LocaleCompare("delete",option+1) == 0)
03702         {
03703           if (IfNormalOp)
03704             DeleteImages(&_images,arg1,_exception);
03705           else
03706             DeleteImages(&_images,"-1",_exception);
03707           break;
03708         }
03709       if (LocaleCompare("duplicate",option+1) == 0)
03710         {
03711           if (IfNormalOp)
03712             {
03713               const char
03714                 *p;
03715 
03716               size_t
03717                 number_duplicates;
03718 
03719               if (IfMagickFalse(IsGeometry(arg1)))
03720                 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
03721                       arg1);
03722               number_duplicates=(size_t) StringToLong(arg1);
03723               p=strchr(arg1,',');
03724               if (p == (const char *) NULL)
03725                 new_images=DuplicateImages(_images,number_duplicates,"-1",
03726                   _exception);
03727               else
03728                 new_images=DuplicateImages(_images,number_duplicates,p,
03729                   _exception);
03730             }
03731           else
03732             new_images=DuplicateImages(_images,1,"-1",_exception);
03733           AppendImageToList(&_images, new_images);
03734           new_images=(Image *)NULL;
03735           break;
03736         }
03737       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03738     }
03739     case 'e':
03740     {
03741       if (LocaleCompare("evaluate-sequence",option+1) == 0)
03742         {
03743           parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
03744           if ( parse < 0 )
03745             CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
03746                  option,arg1);
03747           new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
03748                _exception);
03749           break;
03750         }
03751       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03752     }
03753     case 'f':
03754     {
03755       if (LocaleCompare("fft",option+1) == 0)
03756         {
03757           new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
03758           break;
03759         }
03760       if (LocaleCompare("flatten",option+1) == 0)
03761         {
03762           /* REDIRECTED to use -layers flatten instead */
03763           CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
03764           break;
03765         }
03766       if (LocaleCompare("fx",option+1) == 0)
03767         {
03768           new_images=FxImage(_images,arg1,_exception);
03769           break;
03770         }
03771       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03772     }
03773     case 'h':
03774     {
03775       if (LocaleCompare("hald-clut",option+1) == 0)
03776         {
03777           /* FUTURE - make this a compose option (and thus layers compose )
03778              or perhaps compose last image over all other _images.
03779           */
03780           Image
03781             *hald_image;
03782 
03783           new_images=RemoveFirstImageFromList(&_images);
03784           hald_image=RemoveLastImageFromList(&_images);
03785           if (hald_image == (Image *) NULL)
03786             break;
03787           (void) HaldClutImage(new_images,hald_image,_exception);
03788           hald_image=DestroyImage(hald_image);
03789           break;
03790         }
03791       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03792     }
03793     case 'i':
03794     {
03795       if (LocaleCompare("ift",option+1) == 0)
03796         {
03797           Image
03798             *magnitude_image,
03799             *phase_image;
03800 
03801            magnitude_image=RemoveFirstImageFromList(&_images);
03802            phase_image=RemoveFirstImageFromList(&_images);
03803           /* FUTURE - produce Exception, rather than silent fail */
03804            if (phase_image == (Image *) NULL)
03805              break;
03806            new_images=InverseFourierTransformImage(magnitude_image,phase_image,
03807                    normal_op,_exception);
03808            magnitude_image=DestroyImage(magnitude_image);
03809            phase_image=DestroyImage(phase_image);
03810           break;
03811         }
03812       if (LocaleCompare("insert",option+1) == 0)
03813         {
03814           Image
03815             *insert_image,
03816             *index_image;
03817 
03818           ssize_t
03819             index;
03820 
03821           if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
03822             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
03823           index=0;
03824           insert_image=RemoveLastImageFromList(&_images);
03825           if (IfNormalOp)
03826             index=(ssize_t) StringToLong(arg1);
03827           index_image=insert_image;
03828           if (index == 0)
03829             PrependImageToList(&_images,insert_image);
03830           else if (index == (ssize_t) GetImageListLength(_images))
03831             AppendImageToList(&_images,insert_image);
03832           else
03833             {
03834                index_image=GetImageFromList(_images,index-1);
03835                if (index_image == (Image *) NULL)
03836                  CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
03837               InsertImageInList(&index_image,insert_image);
03838             }
03839           _images=GetFirstImageInList(index_image);
03840           break;
03841         }
03842       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03843     }
03844     case 'l':
03845     {
03846       if (LocaleCompare("layers",option+1) == 0)
03847         {
03848           parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
03849           if ( parse < 0 )
03850             CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
03851                  option,arg1);
03852           switch ((ImageLayerMethod) parse)
03853           {
03854             case CoalesceLayer:
03855             {
03856               new_images=CoalesceImages(_images,_exception);
03857               break;
03858             }
03859             case CompareAnyLayer:
03860             case CompareClearLayer:
03861             case CompareOverlayLayer:
03862             default:
03863             {
03864               new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
03865                    _exception);
03866               break;
03867             }
03868             case MergeLayer:
03869             case FlattenLayer:
03870             case MosaicLayer:
03871             case TrimBoundsLayer:
03872             {
03873               new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
03874                    _exception);
03875               break;
03876             }
03877             case DisposeLayer:
03878             {
03879               new_images=DisposeImages(_images,_exception);
03880               break;
03881             }
03882             case OptimizeImageLayer:
03883             {
03884               new_images=OptimizeImageLayers(_images,_exception);
03885               break;
03886             }
03887             case OptimizePlusLayer:
03888             {
03889               new_images=OptimizePlusImageLayers(_images,_exception);
03890               break;
03891             }
03892             case OptimizeTransLayer:
03893             {
03894               OptimizeImageTransparency(_images,_exception);
03895               break;
03896             }
03897             case RemoveDupsLayer:
03898             {
03899               RemoveDuplicateLayers(&_images,_exception);
03900               break;
03901             }
03902             case RemoveZeroLayer:
03903             {
03904               RemoveZeroDelayLayers(&_images,_exception);
03905               break;
03906             }
03907             case OptimizeLayer:
03908             { /* General Purpose, GIF Animation Optimizer.  */
03909               new_images=CoalesceImages(_images,_exception);
03910               if (new_images == (Image *) NULL)
03911                 break;
03912               _images=DestroyImageList(_images);
03913               _images=OptimizeImageLayers(new_images,_exception);
03914               if (_images == (Image *) NULL)
03915                 break;
03916               new_images=DestroyImageList(new_images);
03917               OptimizeImageTransparency(_images,_exception);
03918               (void) RemapImages(_quantize_info,_images,(Image *) NULL,
03919                 _exception);
03920               break;
03921             }
03922             case CompositeLayer:
03923             {
03924               Image
03925                 *source;
03926 
03927               RectangleInfo
03928                 geometry;
03929 
03930               CompositeOperator
03931                 compose;
03932 
03933               const char*
03934                 value;
03935 
03936               value=GetImageOption(_image_info,"compose");
03937               compose=OverCompositeOp;  /* Default to Over */
03938               if (value != (const char *) NULL)
03939                 compose=(CompositeOperator) ParseCommandOption(
03940                       MagickComposeOptions,MagickFalse,value);
03941 
03942               /* Split image sequence at the first 'NULL:' image. */
03943               source=_images;
03944               while (source != (Image *) NULL)
03945               {
03946                 source=GetNextImageInList(source);
03947                 if ((source != (Image *) NULL) &&
03948                     (LocaleCompare(source->magick,"NULL") == 0))
03949                   break;
03950               }
03951               if (source != (Image *) NULL)
03952                 {
03953                   if ((GetPreviousImageInList(source) == (Image *) NULL) ||
03954                       (GetNextImageInList(source) == (Image *) NULL))
03955                     source=(Image *) NULL;
03956                   else
03957                     { /* Separate the two lists, junk the null: image.  */
03958                       source=SplitImageList(source->previous);
03959                       DeleteImageFromList(&source);
03960                     }
03961                 }
03962               if (source == (Image *) NULL)
03963                 {
03964                   (void) ThrowMagickException(_exception,GetMagickModule(),
03965                     OptionError,"MissingNullSeparator","layers Composite");
03966                   break;
03967                 }
03968               /* Adjust offset with gravity and virtual canvas.  */
03969               SetGeometry(_images,&geometry);
03970               (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
03971               geometry.width=source->page.width != 0 ?
03972                 source->page.width : source->columns;
03973               geometry.height=source->page.height != 0 ?
03974                source->page.height : source->rows;
03975               GravityAdjustGeometry(_images->page.width != 0 ?
03976                 _images->page.width : _images->columns,
03977                 _images->page.height != 0 ? _images->page.height :
03978                 _images->rows,_images->gravity,&geometry);
03979 
03980               /* Compose the two image sequences together */
03981               CompositeLayers(_images,compose,source,geometry.x,geometry.y,
03982                 _exception);
03983               source=DestroyImageList(source);
03984               break;
03985             }
03986           }
03987           break;
03988         }
03989       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
03990     }
03991     case 'm':
03992     {
03993       if (LocaleCompare("map",option+1) == 0)
03994         {
03995           CLIWandWarnReplaced("+remap");
03996           (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
03997           break;
03998         }
03999       if (LocaleCompare("morph",option+1) == 0)
04000         {
04001           Image
04002             *morph_image;
04003 
04004           if (IfMagickFalse(IsGeometry(arg1)))
04005             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
04006           morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
04007             _exception);
04008           if (morph_image == (Image *) NULL)
04009             break;
04010           _images=DestroyImageList(_images);
04011           _images=morph_image;
04012           break;
04013         }
04014       if (LocaleCompare("mosaic",option+1) == 0)
04015         {
04016           /* REDIRECTED to use -layers mosaic instead */
04017           CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
04018           break;
04019         }
04020       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
04021     }
04022     case 'p':
04023     {
04024       if (LocaleCompare("print",option+1) == 0)
04025         {
04026           (void) FormatLocaleFile(stdout,"%s",arg1);
04027           break;
04028         }
04029       if (LocaleCompare("process",option+1) == 0)
04030         {
04031           /* FUTURE: better parsing using ScriptToken() from string ??? */
04032           char
04033             **arguments;
04034 
04035           int
04036             j,
04037             number_arguments;
04038 
04039           arguments=StringToArgv(arg1,&number_arguments);
04040           if (arguments == (char **) NULL)
04041             break;
04042           if (strchr(arguments[1],'=') != (char *) NULL)
04043             {
04044               char
04045                 breaker,
04046                 quote,
04047                 *token;
04048 
04049               const char
04050                 *arguments;
04051 
04052               int
04053                 next,
04054                 status;
04055 
04056               size_t
04057                 length;
04058 
04059               TokenInfo
04060                 *token_info;
04061 
04062               /*
04063                 Support old style syntax, filter="-option arg1".
04064               */
04065               length=strlen(arg1);
04066               token=(char *) NULL;
04067               if (~length >= (MaxTextExtent-1))
04068                 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
04069                   sizeof(*token));
04070               if (token == (char *) NULL)
04071                 break;
04072               next=0;
04073               arguments=arg1;
04074               token_info=AcquireTokenInfo();
04075               status=Tokenizer(token_info,0,token,length,arguments,"","=",
04076                 "\"",'\0',&breaker,&next,&quote);
04077               token_info=DestroyTokenInfo(token_info);
04078               if (status == 0)
04079                 {
04080                   const char
04081                     *argv;
04082 
04083                   argv=(&(arguments[next]));
04084                   (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
04085                     _exception);
04086                 }
04087               token=DestroyString(token);
04088               break;
04089             }
04090           (void) SubstituteString(&arguments[1],"-","");
04091           (void) InvokeDynamicImageFilter(arguments[1],&_images,
04092             number_arguments-2,(const char **) arguments+2,_exception);
04093           for (j=0; j < number_arguments; j++)
04094             arguments[j]=DestroyString(arguments[j]);
04095           arguments=(char **) RelinquishMagickMemory(arguments);
04096           break;
04097         }
04098       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
04099     }
04100     case 'r':
04101     {
04102       if (LocaleCompare("remap",option+1) == 0)
04103         {
04104           (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
04105           break;
04106         }
04107       if (LocaleCompare("reverse",option+1) == 0)
04108         {
04109           ReverseImageList(&_images);
04110           break;
04111         }
04112       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
04113     }
04114     case 's':
04115     {
04116       if (LocaleCompare("smush",option+1) == 0)
04117         {
04118           /* FUTURE: this option needs more work to make better */
04119           ssize_t
04120             offset;
04121 
04122           if (IfMagickFalse(IsGeometry(arg1)))
04123             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
04124           offset=(ssize_t) StringToLong(arg1);
04125           new_images=SmushImages(_images,normal_op,offset,_exception);
04126           break;
04127         }
04128       if (LocaleCompare("subimage",option+1) == 0)
04129         {
04130           Image
04131             *base_image,
04132             *compare_image;
04133 
04134           const char *
04135             value;
04136 
04137           MetricType
04138             metric;
04139 
04140           double
04141             similarity;
04142 
04143           RectangleInfo
04144             offset;
04145 
04146           base_image=GetImageFromList(_images,0);
04147           compare_image=GetImageFromList(_images,1);
04148 
04149           /* Comparision Metric */
04150           metric=UndefinedMetric;
04151           value=GetImageOption(_image_info,"metric");
04152           if (value != (const char *) NULL)
04153             metric=(MetricType) ParseCommandOption(MagickMetricOptions,
04154               MagickFalse,value);
04155 
04156           new_images=SimilarityImage(base_image,compare_image,metric,
04157                &offset,&similarity,_exception);
04158 
04159           if ( new_images != (Image *)NULL ) {
04160             char
04161               result[MaxTextExtent];
04162 
04163             (void) FormatLocaleString(result,MaxTextExtent,"%lf",similarity);
04164             (void) SetImageProperty(new_images,"subimage:similarity",result,
04165                  _exception);
04166             (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
04167                 (long) offset.x);
04168             (void) SetImageProperty(new_images,"subimage:x",result,
04169                  _exception);
04170             (void) FormatLocaleString(result,MaxTextExtent,"%+ld",
04171                 (long) offset.y);
04172             (void) SetImageProperty(new_images,"subimage:y",result,
04173                  _exception);
04174             (void) FormatLocaleString(result,MaxTextExtent,"%lux%lu%+ld%+ld",
04175                 (unsigned long) offset.width,(unsigned long) offset.height,
04176                 (long) offset.x,(long) offset.y);
04177             (void) SetImageProperty(new_images,"subimage:offset",result,
04178                  _exception);
04179           }
04180           break;
04181         }
04182       if (LocaleCompare("swap",option+1) == 0) {
04183         Image
04184           *p,
04185           *q,
04186           *swap;
04187 
04188         ssize_t
04189           index,
04190           swap_index;
04191 
04192         index=-1;
04193         swap_index=-2;
04194         if (IfNormalOp) {
04195           GeometryInfo
04196             geometry_info;
04197 
04198           MagickStatusType
04199             flags;
04200 
04201           swap_index=(-1);
04202           flags=ParseGeometry(arg1,&geometry_info);
04203           if ((flags & RhoValue) != 0)
04204             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
04205           index=(ssize_t) geometry_info.rho;
04206           if ((flags & SigmaValue) != 0)
04207             swap_index=(ssize_t) geometry_info.sigma;
04208         }
04209         p=GetImageFromList(_images,index);
04210         q=GetImageFromList(_images,swap_index);
04211         if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
04212           if (IfNormalOp)
04213             CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
04214           else
04215             CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
04216         }
04217         if (p == q)
04218           CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
04219         swap=CloneImage(p,0,0,MagickTrue,_exception);
04220         ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
04221         ReplaceImageInList(&q,swap);
04222         _images=GetFirstImageInList(q);
04223         break;
04224       }
04225       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
04226     }
04227     default:
04228       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
04229   }
04230 
04231   /* clean up percent escape interpreted strings */
04232   if (arg1 != arg1n )
04233     arg1=DestroyString((char *)arg1);
04234   if (arg2 != arg2n )
04235     arg2=DestroyString((char *)arg2);
04236 
04237   /* if new image list generated, replace existing image list */
04238   if (new_images == (Image *) NULL)
04239     return;
04240   _images=DestroyImageList(_images);
04241   _images=GetFirstImageInList(new_images);
04242   return;
04243 
04244 #undef _image_info
04245 #undef _images
04246 #undef _exception
04247 #undef _draw_info
04248 #undef _quantize_info
04249 #undef IfNormalOp
04250 #undef IfPlusOp
04251 #undef normal_op
04252 }
04253 
04254 /*
04255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04256 %                                                                             %
04257 %                                                                             %
04258 %                                                                             %
04259 +   C L I N o I m a g e O p e r a t i o n s                                   %
04260 %                                                                             %
04261 %                                                                             %
04262 %                                                                             %
04263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04264 %
04265 %  CLINoImageOperator() Applies operations that may not actually need images
04266 %  in an image list.
04267 %
04268 %  The classic operators of this type is -read, which actually creates images
04269 %  even when no images are present.  Or image stack operators, which can be
04270 %  applied (push or pop) to an empty image list.
04271 %
04272 %  Note: unlike other Operators, these may involve other special 'option'
04273 %  characters other than '-' or '+', namely parenthesis and braces.
04274 %
04275 %  The format of the CLINoImageOption method is:
04276 %
04277 %      void CLINoImageOption(MagickCLI *cli_wand,const char *option,
04278 %           const char *arg1, const char *arg2)
04279 %
04280 %  A description of each parameter follows:
04281 %
04282 %    o cli_wand: the main CLI Wand to use.
04283 %
04284 %    o option: The special option (with any switch char) to process
04285 %
04286 %    o arg1 & arg2: Argument for option, if required
04287 %                   Currently arg2 is not used.
04288 %
04289 */
04290 WandExport void CLINoImageOperator(MagickCLI *cli_wand,
04291   const char *option, const char *arg1, const char *magick_unused(arg2))
04292 {
04293 #define _image_info     (cli_wand->wand.image_info)
04294 #define _images         (cli_wand->wand.images)
04295 #define _exception      (cli_wand->wand.exception)
04296 #define IfNormalOp      (*option=='-')
04297 #define IfPlusOp        (*option!='-')
04298 
04299   assert(cli_wand != (MagickCLI *) NULL);
04300   assert(cli_wand->signature == WandSignature);
04301   assert(cli_wand->wand.signature == WandSignature);
04302   if (IfMagickTrue(cli_wand->wand.debug))
04303     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
04304 
04305   /*
04306     No-op options  (ignore these)
04307   */
04308   if (LocaleCompare("noop",option+1) == 0)   /* no argument */
04309     return;
04310   if (LocaleCompare("sans",option+1) == 0)   /* one argument */
04311     return;
04312   if (LocaleCompare("sans0",option+1) == 0)  /* no argument */
04313     return;
04314   if (LocaleCompare("sans2",option+1) == 0)  /* two arguments */
04315     return;
04316   /*
04317     Image Reading
04318   */
04319   if ( ( LocaleCompare("read",option+1) == 0 ) ||
04320      ( LocaleCompare("--",option) == 0 ) ) {
04321 #if 0
04322     /* Directly read 'arg1' without filename expansion handling (see below).
04323     */
04324 # if !USE_WAND_METHODS
04325     Image    *new_images;
04326 
04327     if (IfMagickTrue(_image_info->ping))
04328       new_images=PingImages(_image_info,arg1,_exception);
04329     else
04330       new_images=ReadImages(_image_info,arg1,_exception);
04331     AppendImageToList(&_images, new_images);
04332 # else
04333     /* read images using MagickWand method - no ping */
04334     /* This is not working! - it locks up in a CPU loop! */
04335     MagickSetLastIterator(&cli_wand->wand);
04336     MagickReadImage(&cli_wand->wand,arg1);
04337     MagickSetFirstIterator(&cli_wand->wand);
04338 # endif
04339 #else
04340     /* Do Filename Expansion for 'arg1' then read all images.
04341      *
04342      * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
04343      * (but attaching to generated argument list) any [...] read modifiers
04344      * that may be present.
04345      *
04346      * For example: correctly expand '*.gif[20x20]' into a list such as
04347      * 'abc.gif[20x20',  'foobar.gif[20x20]',  'xyzzy.gif[20x20]'
04348      *
04349      * NOTE: In IMv6 this was done globally across all images. This
04350      * meant you could include IM options in '@filename' lists, but you
04351      * could not include comments.   Doing it only for image read makes
04352      * it far more secure.
04353      */
04354     int      argc;
04355     char     **argv;
04356     ssize_t  i;
04357 
04358     argc = 1;
04359     argv = (char **) &arg1;
04360 
04361     /* Expand 'glob' expressions in the given filename.
04362        Expansion handles any 'coder:' prefix, or read modifiers attached
04363        to the filename, including them in the resulting expanded list.
04364     */
04365     if (IfMagickFalse(  ExpandFilenames(&argc,&argv)  ))
04366       CLIWandExceptArgReturn(ResourceLimitError,"MemoryAllocationFailed",
04367           option,GetExceptionMessage(errno));
04368 
04369     /* loop over expanded filename list, and read then all in */
04370     for (i=0; i<argc; i++) {
04371       Image *
04372         new_images;
04373 #if 0
04374       fprintf(stderr, "DEBUG: Reading image: \"%s\"\n", argv[i]);
04375 #endif
04376       if (IfMagickTrue(_image_info->ping))
04377         new_images=PingImages(_image_info,argv[i],_exception);
04378       else
04379         new_images=ReadImages(_image_info,argv[i],_exception);
04380       AppendImageToList(&_images, new_images);
04381     }
04382     argv=DestroyStringList(argv);  /* Destroy the Expanded Filename list */
04383 #endif
04384     return;
04385   }
04386   /*
04387     Image Writing
04388     Note: Writing a empty image list is valid in specific cases
04389   */
04390   if (LocaleCompare("write",option+1) == 0) {
04391     char
04392       key[MaxTextExtent];
04393 
04394     Image
04395       *write_images;
04396 
04397     ImageInfo
04398       *write_info;
04399 
04400     /* Need images, unless a "null:" output coder is used */
04401     if ( cli_wand->wand.images == (Image *) NULL ) {
04402       if ( LocaleCompare(arg1,"null:") == 0 )
04403         return;
04404       CLIWandExceptArgReturn(OptionError,"NoImagesForWrite",option,arg1);
04405     }
04406 
04407     (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
04408     (void) DeleteImageRegistry(key);
04409     write_images=_images;
04410     if (IfPlusOp)
04411       write_images=CloneImageList(_images,_exception);
04412     write_info=CloneImageInfo(_image_info);
04413     (void) WriteImages(write_info,write_images,arg1,_exception);
04414     write_info=DestroyImageInfo(write_info);
04415     if (IfPlusOp)
04416       write_images=DestroyImageList(write_images);
04417     return;
04418   }
04419   /*
04420     Parenthesis and Brace operations
04421   */
04422   if (LocaleCompare("(",option) == 0) {
04423     /* stack 'push' images */
04424     Stack
04425       *node;
04426 
04427     size_t
04428       size;
04429 
04430     size=0;
04431     node=cli_wand->image_list_stack;
04432     for ( ; node != (Stack *)NULL; node=node->next)
04433       size++;
04434     if ( size >= MAX_STACK_DEPTH )
04435       CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
04436     node=(Stack *) AcquireMagickMemory(sizeof(*node));
04437     if (node == (Stack *) NULL)
04438       CLIWandExceptionReturn(ResourceLimitFatalError,
04439            "MemoryAllocationFailed",option);
04440     node->data = (void *)cli_wand->wand.images;
04441     cli_wand->wand.images = NewImageList();
04442     node->next = cli_wand->image_list_stack;
04443     cli_wand->image_list_stack = node;
04444 
04445     /* handle respect-parenthesis */
04446     if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
04447                   "respect-parenthesis"))))
04448       option="{"; /* fall-thru so as to push image settings too */
04449     else
04450       return;
04451   }
04452   if (LocaleCompare("{",option) == 0) {
04453     /* stack 'push' of image_info settings */
04454     Stack
04455       *node;
04456 
04457     size_t
04458       size;
04459 
04460     size=0;
04461     node=cli_wand->image_info_stack;
04462     for ( ; node != (Stack *)NULL; node=node->next)
04463       size++;
04464     if ( size >= MAX_STACK_DEPTH )
04465       CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
04466     node=(Stack *) AcquireMagickMemory(sizeof(*node));
04467     if (node == (Stack *) NULL)
04468       CLIWandExceptionReturn(ResourceLimitFatalError,
04469            "MemoryAllocationFailed",option);
04470 
04471     node->data = (void *)cli_wand->wand.image_info;
04472     cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
04473     if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
04474       CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
04475            option);
04476       cli_wand->wand.image_info = (ImageInfo *)node->data;
04477       node = (Stack *)RelinquishMagickMemory(node);
04478       return;
04479     }
04480 
04481     node->next = cli_wand->image_info_stack;
04482     cli_wand->image_info_stack = node;
04483 
04484     return;
04485   }
04486   if (LocaleCompare(")",option) == 0) {
04487     /* pop images from stack */
04488     Stack
04489       *node;
04490 
04491     node = (Stack *)cli_wand->image_list_stack;
04492     if ( node == (Stack *)NULL)
04493       CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
04494     cli_wand->image_list_stack = node->next;
04495 
04496     AppendImageToList((Image **)&node->data,cli_wand->wand.images);
04497     cli_wand->wand.images= (Image *)node->data;
04498     node = (Stack *)RelinquishMagickMemory(node);
04499 
04500     /* handle respect-parenthesis - of the previous 'pushed' settings */
04501     node = cli_wand->image_info_stack;
04502     if ( node != (Stack *)NULL)
04503       {
04504         if (IfMagickTrue(IsStringTrue(GetImageOption(
04505                cli_wand->wand.image_info,"respect-parenthesis"))))
04506           option="}"; /* fall-thru so as to pop image settings too */
04507         else
04508           return;
04509       }
04510     else
04511       return;
04512   }
04513   if (LocaleCompare("}",option) == 0) {
04514     /* pop image_info settings from stack */
04515     Stack
04516       *node;
04517 
04518     node = (Stack *)cli_wand->image_info_stack;
04519     if ( node == (Stack *)NULL)
04520       CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
04521     cli_wand->image_info_stack = node->next;
04522 
04523     (void) DestroyImageInfo(cli_wand->wand.image_info);
04524     cli_wand->wand.image_info = (ImageInfo *)node->data;
04525     node = (Stack *)RelinquishMagickMemory(node);
04526 
04527     GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
04528     cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
04529     cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
04530 
04531     return;
04532   }
04533   if (LocaleCompare("clone",option+1) == 0) {
04534       Image
04535         *new_images;
04536 
04537       if (*option == '+')
04538         arg1="-1";
04539       if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
04540         CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
04541       if ( cli_wand->image_list_stack == (Stack *)NULL)
04542         CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
04543       new_images = (Image *)cli_wand->image_list_stack->data;
04544       if (new_images == (Image *) NULL)
04545         CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
04546       new_images=CloneImages(new_images,arg1,_exception);
04547       if (new_images == (Image *) NULL)
04548         CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
04549       AppendImageToList(&_images,new_images);
04550       return;
04551     }
04552   /*
04553     Informational Operations
04554   */
04555   if (LocaleCompare("version",option+1) == 0) {
04556     (void) FormatLocaleFile(stdout,"Version: %s\n",
04557       GetMagickVersion((size_t *) NULL));
04558     (void) FormatLocaleFile(stdout,"Copyright: %s\n",
04559       GetMagickCopyright());
04560     (void) FormatLocaleFile(stdout,"Features: %s\n\n",
04561       GetMagickFeatures());
04562     return;
04563   }
04564   if (LocaleCompare("list",option+1) == 0) {
04565     /* FUTURE: This should really be built into the MagickCore
04566        It does not actually require a cli-wand or and images!
04567      */
04568     ssize_t
04569       list;
04570 
04571     list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
04572     if ( list < 0 ) {
04573       CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
04574       return;
04575     }
04576     switch (list)
04577     {
04578       case MagickCoderOptions:
04579       {
04580         (void) ListCoderInfo((FILE *) NULL,_exception);
04581         break;
04582       }
04583       case MagickColorOptions:
04584       {
04585         (void) ListColorInfo((FILE *) NULL,_exception);
04586         break;
04587       }
04588       case MagickConfigureOptions:
04589       {
04590         (void) ListConfigureInfo((FILE *) NULL,_exception);
04591         break;
04592       }
04593       case MagickDelegateOptions:
04594       {
04595         (void) ListDelegateInfo((FILE *) NULL,_exception);
04596         break;
04597       }
04598       case MagickFontOptions:
04599       {
04600         (void) ListTypeInfo((FILE *) NULL,_exception);
04601         break;
04602       }
04603       case MagickFormatOptions:
04604         (void) ListMagickInfo((FILE *) NULL,_exception);
04605         break;
04606       case MagickLocaleOptions:
04607         (void) ListLocaleInfo((FILE *) NULL,_exception);
04608         break;
04609       case MagickLogOptions:
04610         (void) ListLogInfo((FILE *) NULL,_exception);
04611         break;
04612       case MagickMagicOptions:
04613         (void) ListMagicInfo((FILE *) NULL,_exception);
04614         break;
04615       case MagickMimeOptions:
04616         (void) ListMimeInfo((FILE *) NULL,_exception);
04617         break;
04618       case MagickModuleOptions:
04619         (void) ListModuleInfo((FILE *) NULL,_exception);
04620         break;
04621       case MagickPolicyOptions:
04622         (void) ListPolicyInfo((FILE *) NULL,_exception);
04623         break;
04624       case MagickResourceOptions:
04625         (void) ListMagickResourceInfo((FILE *) NULL,_exception);
04626         break;
04627       case MagickThresholdOptions:
04628         (void) ListThresholdMaps((FILE *) NULL,_exception);
04629         break;
04630       default:
04631         (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
04632           _exception);
04633         break;
04634     }
04635     return;
04636   }
04637 
04638 #if 0
04639   // Other 'special' options this should handle
04640   //    "region"  "reset"  "arg"
04641   if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
04642 #endif
04643     CLIWandException(OptionError,"UnrecognizedOption",option);
04644 
04645 #undef _image_info
04646 #undef _images
04647 #undef _exception
04648 #undef IfNormalOp
04649 #undef IfPlusOp
04650 }
04651 
04652 /*
04653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04654 %                                                                             %
04655 %                                                                             %
04656 %                                                                             %
04657 +   C L I O p t i o n                                                         %
04658 %                                                                             %
04659 %                                                                             %
04660 %                                                                             %
04661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04662 %
04663 %  CLIOption() Processes the given option using the given CLI Magick Wand.
04664 %  The option arguments can be variable in number, though at this time no more
04665 %  that two is actually used by any option (this may change). Excess options
04666 %  are simply ignored.
04667 %
04668 %  If the cli_wand->command pointer is non-null, then it is assumed that the
04669 %  option has already been search for up from the CommandOptions[] table in
04670 %  "MagickCore/options.c" using  GetCommandOptionInfo().  If not set this
04671 %  routine will do the lookup instead. The pointer is reset afterward.
04672 %
04673 %  This action allows the caller to lookup and pre-handle any 'special'
04674 %  options, (such as implicit reads) before calling this general option
04675 %  handler to deal with 'standard' command line options.
04676 %
04677 %  The format of the CLIOption method is:
04678 %
04679 %       void CLIOption(MagickCLI *cli_wand,const char *option, ...)
04680 %
04681 %  A description of each parameter follows:
04682 %
04683 %     o cli_wand: the main CLI Wand to use.
04684 %
04685 %     o option: The special option (with any switch char) to process
04686 %
04687 %     o args: any required arguments for an option (variable number)
04688 %
04689 %  Example Usage...
04690 %
04691 %    CLIoption(cli_wand,"-read","rose:");
04692 %    CLIoption(cli_wand,"-virtual-pixel","transparent");
04693 %    CLIoption(cli_wand,"-distort","SRT:","30");
04694 %    CLIoption(cli_wand,"-write","rotated_rose.png");
04695 %
04696 */
04697 WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
04698 {
04699   const char
04700     *arg1,
04701     *arg2;
04702 
04703   CommandOptionFlags
04704     option_type;
04705 
04706   assert(cli_wand != (MagickCLI *) NULL);
04707   assert(cli_wand->signature == WandSignature);
04708   assert(cli_wand->wand.signature == WandSignature);
04709   if (IfMagickTrue(cli_wand->wand.debug))
04710     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
04711 
04712   do { /* Break Code Block for error handling */
04713 
04714     /* get information about option */
04715     if ( cli_wand->command == (const OptionInfo *) NULL )
04716       cli_wand->command = GetCommandOptionInfo(option);
04717 #if 0
04718       (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
04719             option, cli_wand->command->mnemonic );
04720 #endif
04721     option_type=(CommandOptionFlags) cli_wand->command->flags;
04722 
04723     if ( option_type == UndefinedOptionFlag )
04724       CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
04725 
04726     assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
04727 
04728     /* depreciated options */
04729     if ( (option_type & DeprecateOptionFlag) != 0 )
04730       CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
04731 
04732     /* options that this module does not handle */
04733     if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
04734       CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
04735 
04736     /* Get argument strings from VarArgs
04737       How can you determine arguments is enough was supplied? */
04738     { size_t
04739         count = cli_wand->command->type;
04740 
04741       va_list
04742         operands;
04743 
04744       va_start(operands,option);
04745 
04746       arg1=arg2=NULL;
04747       if ( count >= 1 )
04748         arg1=(const char *) va_arg(operands, const char *);
04749       if ( count >= 2 )
04750         arg2=(const char *) va_arg(operands, const char *);
04751 
04752       va_end(operands);
04753 
04754 #if 0
04755       (void) FormatLocaleFile(stderr,
04756         "CLIOption: \"%s\"  Count: %ld  Flags: %04x  Args: \"%s\" \"%s\"\n",
04757             option,(long) count,option_type,arg1,arg2);
04758 #endif
04759     }
04760 
04761     /*
04762       Call the appropriate option handler
04763     */
04764 
04765     /* FUTURE: this is temporary - get 'settings' to handle distribution of
04766       settings to images attributes,proprieties,artifacts */
04767     if ( cli_wand->wand.images != (Image *)NULL )
04768       SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
04769           cli_wand->wand.exception);
04770 
04771     if ( (option_type & SettingOptionFlags) != 0 ) {
04772       CLISettingOptionInfo(cli_wand, option, arg1, arg2);
04773       // FUTURE: Sync Specific Settings into Image Properities (not global)
04774     }
04775 
04776     /* Operators that do not need images - read, write, stack, clone */
04777     if ( (option_type & NoImageOperatorFlag) != 0)
04778       CLINoImageOperator(cli_wand, option, arg1, arg2);
04779 
04780     /* FUTURE: The not a setting part below is a temporary hack due to
04781     * some options being both a Setting and a Simple operator.
04782     * Specifically -monitor, -depth, and  -colorspace */
04783     if ( cli_wand->wand.images == (Image *)NULL )
04784       if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
04785           ((option_type & SettingOptionFlags) == 0 ))  /* temp hack */
04786         CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
04787 
04788     /* Operators work on single images, and needs a loop over the images */
04789     if ( (option_type & SimpleOperatorFlag) != 0)
04790       CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
04791 
04792     /* Operators that work on the image list as a whole */
04793     if ( (option_type & ListOperatorFlag) != 0 )
04794       CLIListOperatorImages(cli_wand, option, arg1, arg2);
04795 
04796   } while (0);  /* end Break code block */
04797 
04798   cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
04799 }