]> granicus.if.org Git - imagemagick/blobdiff - MagickWand/operation.c
(no commit message)
[imagemagick] / MagickWand / operation.c
index c77beecf83f257036e7457c8bf289ea7829756a8..a88f83f49f7bd9485e6621755506ceef617f5f6b 100644 (file)
@@ -17,7 +17,7 @@
 %                               September 2011                                %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
 #include "MagickWand/studio.h"
 #include "MagickWand/MagickWand.h"
 #include "MagickWand/magick-wand-private.h"
+#include "MagickWand/mogrify.h"
 #include "MagickWand/wand.h"
 #include "MagickWand/wandcli.h"
 #include "MagickWand/wandcli-private.h"
-#include "MagickWand/operation.h"
+#include "MagickCore/image-private.h"
 #include "MagickCore/monitor-private.h"
+#include "MagickWand/operation.h"
 #include "MagickCore/thread-private.h"
 #include "MagickCore/string-private.h"
+#include "MagickCore/pixel-private.h"
+\f
+/*
+  Constant declaration.
+*/
+static const char
+  MogrifyBackgroundColor[] = "#fff",  /* white */
+  MogrifyBorderColor[] = "#dfdfdf",  /* sRGB gray */
+  MogrifyMatteColor[] = "#bdbdbd";  /* slightly darker gray */
 \f
 /*
   Define declarations.
 */
-#define USE_WAND_METHODS  0
+#define USE_WAND_METHODS  1
 #define MAX_STACK_DEPTH  32
 #define UNDEFINED_COMPRESSION_QUALITY  0UL
 
 /* FUTURE: why is this default so specific? */
 #define DEFAULT_DISSIMILARITY_THRESHOLD "0.31830988618379067154"
 
-/*
-  Constant declaration. (temporary exports)
-*/
-static const char
-  BackgroundColor[] = "#fff",  /* white */
-  BorderColor[] = "#dfdfdf",  /* sRGB gray */
-  MatteColor[] = "#bdbdbd";  /* slightly darker gray */
-
 /* For Debugging Geometry Input */
 #define ReportGeometry(flags,info) \
   (void) FormatLocaleFile(stderr, "Geometry = 0x%04X : %lg x %lg %+lg %+lg\n", \
@@ -148,7 +151,8 @@ static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
   if (image != (Image *) NULL)
     return(image);
   read_info=CloneImageInfo(image_info);
-  (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
+  if (path != (const char *) NULL)
+    (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
   image=ReadImage(read_info,exception);
   read_info=DestroyImageInfo(read_info);
   if (image != (Image *) NULL)
@@ -161,14 +165,13 @@ static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
   an array of floating point values than call SparseColorImage().
   Argument is a complex mix of floating-point pixel coodinates, and color
   specifications (or direct floating point numbers).  The number of floats
-  needed to represent a color varies depending on teh current channel
+  needed to represent a color varies depending on the current channel
   setting.
 
   This really should be in MagickCore, so that other API's can make use of it.
 */
 static Image *SparseColorOption(const Image *image,
-  const SparseColorMethod method,const char *arguments,
-  ExceptionInfo *exception)
+  const SparseColorMethod method,const char *arguments,ExceptionInfo *exception)
 {
   char
     token[MaxTextExtent];
@@ -216,7 +219,7 @@ static Image *SparseColorOption(const Image *image,
       (image->colorspace == CMYKColorspace))
     number_colors++;
   if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-      IfMagickTrue(image->matte))
+      image->alpha_trait == BlendPixelTrait)
     number_colors++;
 
   /*
@@ -295,7 +298,7 @@ static Image *SparseColorOption(const Image *image,
           (image->colorspace == CMYKColorspace))
         sparse_arguments[x++] = QuantumScale*color.black;
       if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-          IfMagickTrue(image->matte))
+          image->alpha_trait == BlendPixelTrait)
         sparse_arguments[x++] = QuantumScale*color.alpha;
     }
     else {
@@ -335,7 +338,7 @@ static Image *SparseColorOption(const Image *image,
         token[0] = ','; /* used this token - get another */
       }
       if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-          IfMagickTrue(image->matte))
+          image->alpha_trait == BlendPixelTrait)
         {
         while ( token[0] == ',' ) GetMagickToken(p,&p,token);
         if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
@@ -398,19 +401,18 @@ static Image *SparseColorOption(const Image *image,
 %        arg2 is currently only used by "-limit"
 %
 */
-WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
-     const char *option,const char *arg1, const char *arg2)
+WandPrivate void CLISettingOptionInfo(MagickCLI *cli_wand,
+     const char *option,const char *arg1n, const char *arg2n)
 {
   ssize_t
     parse;     /* option argument parsing (string to value table lookup) */
 
-  assert(cli_wand != (MagickCLI *) NULL);
-  assert(cli_wand->signature == WandSignature);
-  assert(cli_wand->wand.signature == WandSignature);
-  if (IfMagickTrue(cli_wand->wand.debug))
-    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+  const char    /* percent escaped versions of the args */
+    *arg1,
+    *arg2;
 
 #define _image_info       (cli_wand->wand.image_info)
+#define _image            (cli_wand->wand.images)
 #define _exception        (cli_wand->wand.exception)
 #define _draw_info        (cli_wand->draw_info)
 #define _quantize_info    (cli_wand->quantize_info)
@@ -420,6 +422,44 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
 #define ArgBooleanString  (IfSetOption?"true":"false")
 #define ArgOption(def)    (IfSetOption?arg1:(const char *)(def))
 
+  assert(cli_wand != (MagickCLI *) NULL);
+  assert(cli_wand->signature == WandSignature);
+  assert(cli_wand->wand.signature == WandSignature);
+
+  if (IfMagickTrue(cli_wand->wand.debug))
+    (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+         "- Setting Option: %s \"%s\" \"%s\"", option,arg1n,arg2n);
+
+  arg1 = arg1n,
+  arg2 = arg2n;
+
+#if 1
+#define _process_flags    (cli_wand->process_flags)
+#define _option_type      ((CommandOptionFlags) cli_wand->command->flags)
+  /* Interpret Percent Escapes in Arguments - using first image */
+  if ( (((_process_flags & ProcessInterpretProperities) != 0 )
+        || ((_option_type & AlwaysInterpretArgsFlag) != 0)
+       )  && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
+    /* Interpret Percent escapes in argument 1 */
+    if (arg1n != (char *) NULL) {
+      arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
+      if (arg1 == (char *) NULL) {
+        CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
+        arg1=arg1n;  /* use the given argument as is */
+      }
+    }
+    if (arg2n != (char *) NULL) {
+      arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
+      if (arg2 == (char *) NULL) {
+        CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
+        arg2=arg2n;  /* use the given argument as is */
+      }
+    }
+  }
+#undef _process_flags
+#undef _option_type
+#endif
+
   switch (*(option+1))
   {
     case 'a':
@@ -476,7 +516,7 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
              Better error handling of QueryColorCompliance() needed.
           */
           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
-          (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
+          (void) QueryColorCompliance(ArgOption(MogrifyBackgroundColor),AllCompliance,
              &_image_info->background_color,_exception);
           break;
         }
@@ -529,9 +569,9 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
               break;
             }
           (void) DeleteImageOption(_image_info,option+1);
-          (void) QueryColorCompliance(BorderColor,AllCompliance,
+          (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
             &_image_info->border_color,_exception);
-          (void) QueryColorCompliance(BorderColor,AllCompliance,
+          (void) QueryColorCompliance(MogrifyBorderColor,AllCompliance,
             &_draw_info->border_color,_exception);
           break;
         }
@@ -566,8 +606,7 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
         }
       if (LocaleCompare("channel",option+1) == 0)
         {
-          arg1=ArgOption("default");
-          parse=ParseChannelOption(arg1);
+          parse=ParseChannelOption(ArgOption("Default"));
           if (parse < 0)
             CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
                  option,arg1);
@@ -748,12 +787,12 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
              but also ImageInfo and _quantize_info method!
              FUTURE: merge the duality of the dithering options
           */
-          _image_info->dither = _quantize_info->dither = ArgBoolean;
+          _image_info->dither = ArgBoolean;
           (void) SetImageOption(_image_info,option+1,ArgOption("none"));
           _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
-                    MagickDitherOptions,MagickFalse,ArgOption("none"));
+             MagickDitherOptions,MagickFalse,ArgOption("none"));
           if (_quantize_info->dither_method == NoDitherMethod)
-            _image_info->dither = _quantize_info->dither = MagickFalse;
+            _image_info->dither = MagickFalse;
           break;
         }
       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
@@ -793,6 +832,14 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
           (void) CloneString(&_draw_info->family,ArgOption(NULL));
           break;
         }
+      if (LocaleCompare("features",option+1) == 0)
+        {
+          (void) SetImageOption(_image_info,"identify:features",
+            ArgBooleanString);
+          if (IfSetOption)
+            (void) SetImageArtifact(_image,"verbose","true");
+          break;
+        }
       if (LocaleCompare("fill",option+1) == 0)
         {
           /* Set "fill" OR "fill-pattern" in _draw_info
@@ -863,7 +910,7 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
              SyncImageSettings() used to set per-image attribute.
 
              FUTURE: Can't find anything else using _image_info->fuzz directly!
-                     remove direct sttribute from image_info
+                     convert structure attribute to 'option' string
           */
           arg1=ArgOption("0");
           if (IfMagickFalse(IsGeometry(arg1)))
@@ -916,13 +963,24 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
     }
     case 'i':
     {
+      if (LocaleCompare("intensity",option+1) == 0)
+        {
+          arg1 = ArgOption("undefined");
+          parse = ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,
+            arg1);
+          if (parse < 0)
+            CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityType",
+              option,arg1);
+          (void) SetImageOption(_image_info,option+1,arg1);
+          break;
+        }
       if (LocaleCompare("intent",option+1) == 0)
         {
           /* Only used by coders: MIFF, MPC, BMP, PNG
              and for image profile call to AcquireTransformThreadSet()
              SyncImageSettings() used to set per-image attribute.
           */
-          arg1 = ArgOption("indefined");
+          arg1 = ArgOption("undefined");
           parse = ParseCommandOption(MagickIntentOptions,MagickFalse,arg1);
           if (parse < 0)
             CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",
@@ -1042,7 +1100,7 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
         {
           /* SyncImageSettings() used to set per-image attribute. */
           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
-          (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
+          (void) QueryColorCompliance(ArgOption(MogrifyMatteColor),AllCompliance,
              &_image_info->matte_color,_exception);
           break;
         }
@@ -1057,6 +1115,14 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
           break;
         }
+      if (LocaleCompare("moments",option+1) == 0)
+        {
+          (void) SetImageOption(_image_info,"identify:moments",
+            ArgBooleanString);
+          if (IfSetOption)
+            (void) SetImageArtifact(_image,"verbose","true");
+          break;
+        }
       if (LocaleCompare("monitor",option+1) == 0)
         {
           (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
@@ -1277,8 +1343,8 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
           if (IfMagickFalse(IsGeometry(arg1)))
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           SetRandomSecretKey(
-               IfSetOption ? (size_t) StringToUnsignedLong(arg1)
-                           : (size_t) time((time_t *) NULL) );
+               IfSetOption ? (unsigned long) StringToUnsignedLong(arg1)
+                           : (unsigned long) time((time_t *) NULL) );
           break;
         }
       if (LocaleCompare("size",option+1) == 0)
@@ -1376,6 +1442,7 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
         }
       if (LocaleCompare("texture",option+1) == 0)
         {
+          /* Note: arguments do not have percent escapes expanded */
           /* FUTURE: move _image_info string to option splay-tree
              Other than "montage" what uses "texture" ????
           */
@@ -1384,6 +1451,7 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
         }
       if (LocaleCompare("tile",option+1) == 0)
         {
+          /* Note: arguments do not have percent escapes expanded */
           _draw_info->fill_pattern=IfSetOption
                                  ?GetImageCache(_image_info,arg1,_exception)
                                  :DestroyImage(_draw_info->fill_pattern);
@@ -1536,6 +1604,12 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
   }
 
+  /* clean up percent escape interpreted strings */
+  if (arg1 != arg1n )
+    arg1=DestroyString((char *)arg1);
+  if (arg2 != arg2n )
+    arg2=DestroyString((char *)arg2);
+
 #undef _image_info
 #undef _exception
 #undef _draw_info
@@ -1560,14 +1634,13 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  WandSimpleOperatorImages() applys one simple image operation given to all
-%  the images in the CLI wand,  with the settings that was previously saved in
-%  the CLI wand.
+%  CLISimpleOperatorImages() applys one simple image operation given to all
+%  the images in the CLI wand, using any per-image or global settings that was
+%  previously saved in the CLI wand.
 %
-%  It is assumed that any per-image settings are up-to-date with respect to
-%  extra settings that were already saved in the wand.
+%  It is assumed that any such settings are up-to-date.
 %
-%  The format of the WandSimpleOperatorImage method is:
+%  The format of the WandSimpleOperatorImages method is:
 %
 %    void CLISimpleOperatorImages(MagickCLI *cli_wand,
 %        const char *option, const char *arg1, const char *arg2)
@@ -1583,8 +1656,8 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
 */
 
 /*
-  Internal subrountine to apply one simple image operation to the current
-  image pointed to by the CLI wand.
+  CLISimpleOperatorImage() is an Internal subrountine to apply one simple
+  image operation to the current image pointed to by the CLI wand.
 
   The image in the list may be modified in three different ways...
     * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
@@ -1599,8 +1672,8 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
   also change.  GetFirstImageInList() should be used by caller if they wish
   return the Image pointer to the first image in list.
 */
-static void CLISimpleOperatorImage(MagickCLI *cli_wand,
-  const char *option, const char *arg1, const char *arg2)
+static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
+  const char *option, const char *arg1n, const char *arg2n)
 {
   Image *
     new_image;
@@ -1617,15 +1690,21 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
   ssize_t
     parse;
 
-#define _image_info     (cli_wand->wand.image_info)
-#define _image          (cli_wand->wand.images)
-#define _exception      (cli_wand->wand.exception)
-#define _draw_info      (cli_wand->draw_info)
-#define _quantize_info  (cli_wand->quantize_info)
-#define IfNormalOp      (*option=='-')
-#define IfPlusOp        (*option!='-')
-#define normal_op       IsMagickTrue(IfNormalOp)
-#define plus_alt_op     IsMagickFalse(IfNormalOp)
+  const char    /* percent escaped versions of the args */
+    *arg1,
+    *arg2;
+
+#define _image_info       (cli_wand->wand.image_info)
+#define _image            (cli_wand->wand.images)
+#define _exception        (cli_wand->wand.exception)
+#define _draw_info        (cli_wand->draw_info)
+#define _quantize_info    (cli_wand->quantize_info)
+#define _process_flags    (cli_wand->process_flags)
+#define _option_type      ((CommandOptionFlags) cli_wand->command->flags)
+#define IfNormalOp        (*option=='-')
+#define IfPlusOp          (*option!='-')
+#define IsNormalOp        IsMagickTrue(IfNormalOp)
+#define IsPlusOp          IsMagickFalse(IfNormalOp)
 
   assert(cli_wand != (MagickCLI *) NULL);
   assert(cli_wand->signature == WandSignature);
@@ -1634,13 +1713,40 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
   if (IfMagickTrue(cli_wand->wand.debug))
     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
 
-  SetGeometryInfo(&geometry_info);
+  arg1 = arg1n,
+  arg2 = arg2n;
+
+  /* Interpret Percent Escapes in Arguments - using first image */
+  if ( (((_process_flags & ProcessInterpretProperities) != 0 )
+        || ((_option_type & AlwaysInterpretArgsFlag) != 0)
+       )  && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
+    /* Interpret Percent escapes in argument 1 */
+    if (arg1n != (char *) NULL) {
+      arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception);
+      if (arg1 == (char *) NULL) {
+        CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
+        arg1=arg1n;  /* use the given argument as is */
+      }
+    }
+    if (arg2n != (char *) NULL) {
+      arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception);
+      if (arg2 == (char *) NULL) {
+        CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
+        arg2=arg2n;  /* use the given argument as is */
+      }
+    }
+  }
+#undef _process_flags
+#undef _option_type
+
+#if 0
+  (void) FormatLocaleFile(stderr,
+    "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
+#endif
 
   new_image = (Image *)NULL; /* the replacement image, if not null at end */
+  SetGeometryInfo(&geometry_info);
 
-  /* FUTURE: We may need somthing a little more optimized than this!
-     Perhaps, do the 'sync' if 'settings tainted' before next operator.
-  */
   switch (*(option+1))
   {
     case 'a':
@@ -1679,32 +1785,26 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("alpha",option+1) == 0)
         {
-          parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
+          parse=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,arg1);
           if (parse < 0)
-            CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
+            CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelOption",
                  option,arg1);
-          (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
+          (void) SetImageAlphaChannel(_image,(AlphaChannelOption)parse,
                _exception);
           break;
         }
       if (LocaleCompare("annotate",option+1) == 0)
         {
           char
-            *text,
             geometry[MaxTextExtent];
 
           SetGeometryInfo(&geometry_info);
           flags=ParseGeometry(arg1,&geometry_info);
-          if ((flags & RhoValue) == 0)
+          if (flags == 0)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           if ((flags & SigmaValue) == 0)
             geometry_info.sigma=geometry_info.rho;
-          text=InterpretImageProperties(_image_info,_image,arg2,
-            _exception);
-          if (text == (char *) NULL)
-            break;
-          (void) CloneString(&_draw_info->text,text);
-          text=DestroyString(text);
+          (void) CloneString(&_draw_info->text,arg2);
           (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
             geometry_info.xi,geometry_info.psi);
           (void) CloneString(&_draw_info->geometry,geometry);
@@ -1732,49 +1832,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("auto-orient",option+1) == 0)
         {
-          /* This should probably be a MagickCore function */
-          switch (_image->orientation)
-          {
-            case TopRightOrientation:
-            {
-              new_image=FlopImage(_image,_exception);
-              break;
-            }
-            case BottomRightOrientation:
-            {
-              new_image=RotateImage(_image,180.0,_exception);
-              break;
-            }
-            case BottomLeftOrientation:
-            {
-              new_image=FlipImage(_image,_exception);
-              break;
-            }
-            case LeftTopOrientation:
-            {
-              new_image=TransposeImage(_image,_exception);
-              break;
-            }
-            case RightTopOrientation:
-            {
-              new_image=RotateImage(_image,90.0,_exception);
-              break;
-            }
-            case RightBottomOrientation:
-            {
-              new_image=TransverseImage(_image,_exception);
-              break;
-            }
-            case LeftBottomOrientation:
-            {
-              new_image=RotateImage(_image,270.0,_exception);
-              break;
-            }
-            default:
-              break;
-          }
-          if (new_image != (Image *) NULL)
-            new_image->orientation=TopLeftOrientation;
+          new_image=AutoOrientImage(_image,_image->orientation,_exception);
           break;
         }
       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
@@ -1819,18 +1877,13 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
             value;
 
           flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
-          if ((flags & RhoValue) == 0)
+          if ((flags & (WidthValue | HeightValue)) == 0)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
-          if ((flags & SigmaValue) == 0)
-            geometry.height=geometry.width;
-
+          compose=OverCompositeOp;
           value=GetImageOption(_image_info,"compose");
           if (value != (const char *) NULL)
-            compose=(CompositeOperator) ParseCommandOption(
-                 MagickComposeOptions,MagickFalse,value);
-          else
-            compose=OverCompositeOp;  /* use Over not _image->compose */
-
+            compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
+              MagickFalse,value);
           new_image=BorderImage(_image,&geometry,compose,_exception);
           break;
         }
@@ -1861,15 +1914,36 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
     }
     case 'c':
     {
+      if (LocaleCompare("canny",option+1) == 0)
+        {
+          flags=ParseGeometry(arg1,&geometry_info);
+          if ((flags & (RhoValue|SigmaValue)) == 0)
+            CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
+          if ((flags & SigmaValue) == 0)
+            geometry_info.sigma=1.0;
+          if ((flags & XiValue) == 0)
+            geometry_info.xi=10;
+          if ((flags & PsiValue) == 0)
+            geometry_info.psi=30;
+          if ((flags & PercentValue) != 0)
+            {
+              geometry_info.xi/=100.0;
+              geometry_info.psi/=100.0;
+            }
+          new_image=CannyEdgeImage(_image,geometry_info.rho,geometry_info.sigma,
+            geometry_info.xi,geometry_info.psi,_exception);
+          break;
+        }
       if (LocaleCompare("cdl",option+1) == 0)
         {
+          /* Note: arguments do not have percent escapes expanded */
           char
             *color_correction_collection;
 
           /*
             Color correct with a color decision list.
           */
-          color_correction_collection=FileToString(arg1,~0,_exception);
+          color_correction_collection=FileToString(arg1,~0UL,_exception);
           if (color_correction_collection == (char *) NULL)
             break;
           (void) ColorDecisionListImage(_image,color_correction_collection,
@@ -1885,8 +1959,8 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
             geometry_info.sigma=1.0;
           if ((flags & XiValue) == 0)
             geometry_info.xi=1.0;
-          new_image=CharcoalImage(_image,geometry_info.rho,
-            geometry_info.sigma,_exception);
+          new_image=CharcoalImage(_image,geometry_info.rho,geometry_info.sigma,
+            _exception);
           break;
         }
       if (LocaleCompare("chop",option+1) == 0)
@@ -1912,6 +1986,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("clip-mask",option+1) == 0)
         {
+          /* Note: arguments do not have percent escapes expanded */
           CacheView
             *mask_view;
 
@@ -1928,7 +2003,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
             y;
 
           if (IfPlusOp) {
-            /* "+clip-mask" Remove the write mask */
+            /* use "+clip-mask" Remove the write mask for -clip-path */
             (void) SetImageMask(_image,(Image *) NULL,_exception);
             break;
           }
@@ -1948,11 +2023,9 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
               break;
             for (x=0; x < (ssize_t) mask_image->columns; x++)
             {
-              if (IfMagickFalse(mask_image->matte))
+              if (mask_image->alpha_trait != BlendPixelTrait)
                 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
-              SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
-              SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
-              SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
+              SetPixelGray(mask_image,GetPixelAlpha(mask_image,q),q);
               q+=GetPixelChannels(mask_image);
             }
             if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
@@ -1960,14 +2033,16 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           }
           /* clean up and set the write mask */
           mask_view=DestroyCacheView(mask_view);
-          mask_image->matte=MagickTrue;
+          mask_image->alpha_trait=BlendPixelTrait;
+          (void) SetImageColorspace(_image,GRAYColorspace,_exception);
           (void) SetImageMask(_image,mask_image,_exception);
           mask_image=DestroyImage(mask_image);
           break;
         }
       if (LocaleCompare("clip-path",option+1) == 0)
         {
-          (void) ClipImagePath(_image,arg1,normal_op,_exception);
+          (void) ClipImagePath(_image,arg1,IsNormalOp,_exception);
+          /* Note: Use "+clip-mask" remove the write mask added */
           break;
         }
       if (LocaleCompare("colorize",option+1) == 0)
@@ -2017,14 +2092,14 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
              That seems to be a little strange!
           */
           (void) TransformImageColorspace(_image,
-                    IfNormalOp ? _image_info->colorspace : RGBColorspace,
+                    IfNormalOp ? _image_info->colorspace : sRGBColorspace,
                     _exception);
           break;
         }
       if (LocaleCompare("contrast",option+1) == 0)
         {
-          CLIWandWarnReplaced(normal_op?"-level":"+level");
-          (void) ContrastImage(_image,normal_op,_exception);
+          CLIWandWarnReplaced(IfNormalOp?"-level":"+level");
+          (void) ContrastImage(_image,IsNormalOp,_exception);
           break;
         }
       if (LocaleCompare("contrast-stretch",option+1) == 0)
@@ -2046,7 +2121,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
               black_point*=(double) _image->columns*_image->rows/100.0;
               white_point*=(double) _image->columns*_image->rows/100.0;
             }
-          white_point=(MagickRealType) _image->columns*_image->rows-
+          white_point=(double) _image->columns*_image->rows-
             white_point;
           (void) ContrastStretchImage(_image,black_point,white_point,
             _exception);
@@ -2060,8 +2135,8 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           kernel_info=AcquireKernelInfo(arg1);
           if (kernel_info == (KernelInfo *) NULL)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
-          new_image=MorphologyImage(_image,ConvolveMorphology,1,kernel_info,
-               _exception);
+          new_image=MorphologyImage(_image,CorrelateMorphology,1,kernel_info,
+            _exception);
           kernel_info=DestroyKernelInfo(kernel_info);
           break;
         }
@@ -2087,10 +2162,11 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
     {
       if (LocaleCompare("decipher",option+1) == 0)
         {
+          /* Note: arguments do not have percent escapes expanded */
           StringInfo
             *passkey;
 
-          passkey=FileToStringInfo(arg1,~0,_exception);
+          passkey=FileToStringInfo(arg1,~0UL,_exception);
           if (passkey == (StringInfo *) NULL)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
 
@@ -2133,9 +2209,6 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("distort",option+1) == 0)
         {
-          char
-            *arg;
-
           double
             *args;
 
@@ -2164,18 +2237,13 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
                     (size_t)2,resize_args,MagickTrue,_exception);
                break;
             }
-          /* allow percent escapes in argument string */
-          arg=InterpretImageProperties(_image_info,_image,arg2,_exception);
-          if (arg == (char *) NULL)
-            break;
           /* convert argument string into an array of doubles */
-          args = StringToArrayOfDoubles(arg,&count,_exception);
-          arg=DestroyString(arg);
+          args = StringToArrayOfDoubles(arg2,&count,_exception);
           if (args == (double *)NULL )
             CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
 
           new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
-               plus_alt_op,_exception);
+               IsPlusOp,_exception);
           args=(double *) RelinquishMagickMemory(args);
           break;
         }
@@ -2195,10 +2263,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           flags=ParseGeometry(arg1,&geometry_info);
           if ((flags & (RhoValue|SigmaValue)) == 0)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
-          if ((flags & SigmaValue) == 0)
-            geometry_info.sigma=1.0;
-          new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
-               _exception);
+          new_image=EdgeImage(_image,geometry_info.rho,_exception);
           break;
         }
       if (LocaleCompare("emboss",option+1) == 0)
@@ -2214,10 +2279,11 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("encipher",option+1) == 0)
         {
+          /* Note: arguments do not have percent escapes expanded */
           StringInfo
             *passkey;
 
-          passkey=FileToStringInfo(arg1,~0,_exception);
+          passkey=FileToStringInfo(arg1,~0UL,_exception);
           if (passkey != (StringInfo *) NULL)
             {
               (void) PasskeyEncipherImage(_image,passkey,_exception);
@@ -2267,17 +2333,6 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
     }
     case 'f':
     {
-      if (LocaleCompare("features",option+1) == 0)
-        {
-          /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
-          if (IfPlusOp) {
-              (void) DeleteImageArtifact(_image,"identify:features");
-              break;
-            }
-          (void) SetImageArtifact(_image,"identify:features","true");
-          (void) SetImageArtifact(_image,"verbose","true");
-          break;
-        }
       if (LocaleCompare("flip",option+1) == 0)
         {
           new_image=FlipImage(_image,_exception);
@@ -2298,7 +2353,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
           (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
           (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
-                    geometry.y,plus_alt_op,_exception);
+            geometry.y,IsPlusOp,_exception);
           break;
         }
       if (LocaleCompare("frame",option+1) == 0)
@@ -2313,19 +2368,15 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
             value;
 
           value=GetImageOption(_image_info,"compose");
-          if (value != (const char *) NULL)
-            compose=(CompositeOperator) ParseCommandOption(
-                 MagickComposeOptions,MagickFalse,value);
-          else
             compose=OverCompositeOp;  /* use Over not _image->compose */
-
+          if (value != (const char *) NULL)
+            compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
+              MagickFalse,value);
           if (IfMagickFalse(IsGeometry(arg1)))
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
           frame_info.width=geometry.width;
           frame_info.height=geometry.height;
-          if ((flags & HeightValue) == 0)
-            frame_info.height=geometry.width;
           frame_info.outer_bevel=geometry.x;
           frame_info.inner_bevel=geometry.y;
           frame_info.x=(ssize_t) frame_info.width;
@@ -2337,9 +2388,6 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("function",option+1) == 0)
         {
-          char
-            *arg;
-
           double
             *args;
 
@@ -2350,13 +2398,8 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           if ( parse < 0 )
             CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
                  option,arg1);
-          /* allow percent escapes in argument string */
-          arg=InterpretImageProperties(_image_info,_image,arg2,_exception);
-          if (arg == (char *) NULL)
-            break;
           /* convert argument string into an array of doubles */
-          args = StringToArrayOfDoubles(arg,&count,_exception);
-          arg=DestroyString(arg);
+          args = StringToArrayOfDoubles(arg2,&count,_exception);
           if (args == (double *)NULL )
             CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
 
@@ -2371,13 +2414,26 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
     {
       if (LocaleCompare("gamma",option+1) == 0)
         {
+          double
+            constant;
+
           if (IfMagickFalse(IsGeometry(arg1)))
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
+          constant=StringToDouble(arg1,(char **) NULL);
+#if 0
+          /* Using Gamma, via a cache */
+          if (IfPlusOp)
+            constant=PerceptibleReciprocal(constant);
+          (void) GammaImage(_image,constant,_exception);
+#else
+          /* Using Evaluate POW, direct update of values - more accurite */
           if (IfNormalOp)
-            (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
-                 _exception);
-          else
-            _image->gamma=StringToDouble(arg1,(char **) NULL);
+            constant=PerceptibleReciprocal(constant);
+          (void) EvaluateImage(_image,PowEvaluateOperator,constant,_exception);
+#endif
+          /* Set gamma setting -- Old meaning of "+gamma"
+           * _image->gamma=StringToDouble(arg1,(char **) NULL);
+           */
           break;
         }
       if (LocaleCompare("gaussian-blur",option+1) == 0)
@@ -2420,6 +2476,33 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
               _image->filter,_exception);
           break;
         }
+      if (LocaleCompare("grayscale",option+1) == 0)
+        {
+          parse=ParseCommandOption(MagickPixelIntensityOptions,
+            MagickFalse,arg1);
+          if (parse < 0)
+            CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityMethod",
+              option,arg1);
+          (void) GrayscaleImage(_image,(PixelIntensityMethod) parse,_exception);
+          break;
+        }
+      CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
+    }
+    case 'h':
+    {
+      if (LocaleCompare("hough-lines",option+1) == 0)
+        {
+          flags=ParseGeometry(arg1,&geometry_info);
+          if ((flags & (RhoValue|SigmaValue)) == 0)
+            CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
+          if ((flags & SigmaValue) == 0)
+            geometry_info.sigma=geometry_info.rho;
+          if ((flags & XiValue) == 0)
+            geometry_info.xi=40;
+          new_image=HoughLineImage(_image,(size_t) geometry_info.rho,
+            (size_t) geometry_info.sigma,(size_t) geometry_info.xi,_exception);
+          break;
+        }
       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
     }
     case 'i':
@@ -2439,9 +2522,9 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
             }
           text=InterpretImageProperties(_image_info,_image,format,_exception);
           if (text == (char *) NULL)
-            break;
+            CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
+              option);
           (void) fputs(text,stdout);
-          (void) fputc('\n',stdout);
           text=DestroyString((char *)text);
           break;
         }
@@ -2474,6 +2557,8 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           flags=ParseGeometry(arg1,&geometry_info);
           if ((flags & (RhoValue|SigmaValue)) == 0)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
+          if ((flags & SigmaValue) == 0)
+            geometry_info.sigma=1.0;
           if ((flags & PercentValue) != 0)
             geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
           new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
@@ -2483,7 +2568,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("level",option+1) == 0)
         {
-          MagickRealType
+          double
             black_point,
             gamma,
             white_point;
@@ -2495,7 +2580,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           if ((flags & RhoValue) == 0)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           black_point=geometry_info.rho;
-          white_point=(MagickRealType) QuantumRange;
+          white_point=(double) QuantumRange;
           if ((flags & SigmaValue) != 0)
             white_point=geometry_info.sigma;
           gamma=1.0;
@@ -2503,11 +2588,11 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
             gamma=geometry_info.xi;
           if ((flags & PercentValue) != 0)
             {
-              black_point*=(MagickRealType) (QuantumRange/100.0);
-              white_point*=(MagickRealType) (QuantumRange/100.0);
+              black_point*=(double) (QuantumRange/100.0);
+              white_point*=(double) (QuantumRange/100.0);
             }
           if ((flags & SigmaValue) == 0)
-            white_point=(MagickRealType) QuantumRange-black_point;
+            white_point=(double) QuantumRange-black_point;
           if (IfPlusOp || ((flags & AspectValue) != 0))
             (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
           else
@@ -2550,7 +2635,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
                            &white_point,_exception);
             }
           (void) LevelImageColors(_image,&black_point,&white_point,
-                     plus_alt_op,_exception);
+                     IsPlusOp,_exception);
           break;
         }
       if (LocaleCompare("linear-stretch",option+1) == 0)
@@ -2566,7 +2651,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           if ((flags & RhoValue) == 0)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           black_point=geometry_info.rho;
-          white_point=(MagickRealType) _image->columns*_image->rows;
+          white_point=(double) _image->columns*_image->rows;
           if ((flags & SigmaValue) != 0)
             white_point=geometry_info.sigma;
           if ((flags & PercentValue) != 0)
@@ -2575,7 +2660,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
               white_point*=(double) _image->columns*_image->rows/100.0;
             }
           if ((flags & SigmaValue) == 0)
-            white_point=(MagickRealType) _image->columns*_image->rows-
+            white_point=(double) _image->columns*_image->rows-
               black_point;
           (void) LinearStretchImage(_image,black_point,white_point,_exception);
           break;
@@ -2598,6 +2683,11 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
     }
     case 'm':
     {
+      if (LocaleCompare("magnify",option+1) == 0)
+        {
+          new_image=MagnifyImage(_image,_exception);
+          break;
+        }
       if (LocaleCompare("map",option+1) == 0)
         {
           CLIWandWarnReplaced("-remap");
@@ -2606,6 +2696,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("mask",option+1) == 0)
         {
+          /* Note: arguments do not have percent escapes expanded */
           Image
             *mask;
 
@@ -2626,7 +2717,22 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         {
           CLIWandWarnReplaced(IfNormalOp?"-alpha Set":"-alpha Off");
           (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
-                         DeactivateAlphaChannel, _exception);
+            DeactivateAlphaChannel, _exception);
+          break;
+        }
+      if (LocaleCompare("mean-shift",option+1) == 0)
+        {
+          flags=ParseGeometry(arg1,&geometry_info);
+          if ((flags & (RhoValue|SigmaValue)) == 0)
+            CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
+          if ((flags & SigmaValue) == 0)
+            geometry_info.sigma=1.0;
+          if ((flags & XiValue) == 0)
+            geometry_info.xi=0.10*QuantumRange;
+          if ((flags & PercentValue) != 0)
+            geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
+          new_image=MeanShiftImage(_image,(size_t) geometry_info.rho,
+            (size_t) geometry_info.sigma,geometry_info.xi,_exception);
           break;
         }
       if (LocaleCompare("median",option+1) == 0)
@@ -2712,7 +2818,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
     {
       if (LocaleCompare("negate",option+1) == 0)
         {
-          (void) NegateImage(_image, plus_alt_op, _exception);
+          (void) NegateImage(_image, IsPlusOp, _exception);
           break;
         }
       if (LocaleCompare("noise",option+1) == 0)
@@ -2756,7 +2862,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
             target;
 
           (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
-          (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
+          (void) OpaquePaintImage(_image,&target,&_draw_info->fill,IsPlusOp,
                _exception);
           break;
         }
@@ -2778,6 +2884,12 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
                _exception);
           break;
         }
+      if (LocaleCompare("perceptible",option+1) == 0)
+        {
+          (void) PerceptibleImage(_image,StringToDouble(arg1,(char **) NULL),
+            _exception);
+          break;
+        }
       if (LocaleCompare("polaroid",option+1) == 0)
         {
           const char
@@ -2811,7 +2923,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           if ((flags & RhoValue) == 0)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           (void) PosterizeImage(_image,(size_t) geometry_info.rho,
-               _quantize_info->dither,_exception);
+            _quantize_info->dither_method,_exception);
           break;
         }
       if (LocaleCompare("preview",option+1) == 0)
@@ -2829,6 +2941,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("profile",option+1) == 0)
         {
+          /* Note: arguments do not have percent escapes expanded */
           const char
             *name;
 
@@ -2890,12 +3003,12 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
     }
     case 'r':
     {
-      if (LocaleCompare("radial-blur",option+1) == 0)
+      if (LocaleCompare("rotational-blur",option+1) == 0)
         {
           flags=ParseGeometry(arg1,&geometry_info);
           if ((flags & RhoValue) == 0)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
-          new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
+          new_image=RotationalBlurImage(_image,geometry_info.rho,_exception);
           break;
         }
       if (LocaleCompare("raise",option+1) == 0)
@@ -2903,9 +3016,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           if (IfMagickFalse(IsGeometry(arg1)))
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
-          if ((flags & SigmaValue) == 0)
-            geometry.height=geometry.width;
-          (void) RaiseImage(_image,&geometry,normal_op,_exception);
+          (void) RaiseImage(_image,&geometry,IsNormalOp,_exception);
           break;
         }
       if (LocaleCompare("random-threshold",option+1) == 0)
@@ -2922,6 +3033,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("remap",option+1) == 0)
         {
+          /* Note: arguments do not have percent escapes expanded */
           Image
             *remap_image;
 
@@ -3050,46 +3162,12 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
                  (double) QuantumRange+1.0),_exception);
           break;
         }
-      if (LocaleCompare("set",option+1) == 0)
-        {
-          char
-            *value;
-
-          if (IfPlusOp) {
-              if (LocaleNCompare(arg1,"registry:",9) == 0)
-                (void) DeleteImageRegistry(arg1+9);
-              else
-                if (LocaleNCompare(arg1,"option:",7) == 0)
-                  {
-                    (void) DeleteImageOption(_image_info,arg1+7);
-                    (void) DeleteImageArtifact(_image,arg1+7);
-                  }
-                else
-                  (void) DeleteImageProperty(_image,arg1);
-              break;
-            }
-          value=InterpretImageProperties(_image_info,_image,arg2,_exception);
-          if (value == (char *) NULL)
-            break;
-          if (LocaleNCompare(arg1,"registry:",9) == 0)
-            (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
-          else
-            if (LocaleNCompare(arg1,"option:",7) == 0)
-              {
-                (void) SetImageOption(_image_info,arg1+7,value);
-                (void) SetImageArtifact(_image,arg1+7,value);
-              }
-            else
-              (void) SetImageProperty(_image,arg1,value,_exception);
-          value=DestroyString(value);
-          break;
-        }
       if (LocaleCompare("shade",option+1) == 0)
         {
           flags=ParseGeometry(arg1,&geometry_info);
           if (((flags & RhoValue) == 0) || ((flags & SigmaValue) == 0))
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
-          new_image=ShadeImage(_image,normal_op,geometry_info.rho,
+          new_image=ShadeImage(_image,IsNormalOp,geometry_info.rho,
                geometry_info.sigma,_exception);
           break;
         }
@@ -3137,8 +3215,8 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           if ((flags & SigmaValue) == 0)
             geometry_info.sigma=geometry_info.rho;
-          new_image=ShearImage(_image,geometry_info.rho,
-            geometry_info.sigma,_exception);
+          new_image=ShearImage(_image,geometry_info.rho,geometry_info.sigma,
+            _exception);
           break;
         }
       if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
@@ -3151,7 +3229,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
           if ((flags & PercentValue) != 0)
             geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
               100.0;
-          (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
+          (void) SigmoidalContrastImage(_image,IsNormalOp,geometry_info.rho,
                geometry_info.sigma,_exception);
           break;
         }
@@ -3176,19 +3254,12 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("sparse-color",option+1) == 0)
         {
-          char
-            *arguments;
-
           parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
           if ( parse < 0 )
             CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
                 option,arg1);
-          arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
-          if (arguments == (char *) NULL)
-            CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
-          new_image=SparseColorOption(_image,(SparseColorMethod)parse,
-               arguments,_exception);
-          arguments=DestroyString(arguments);
+          new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2,
+               _exception);
           break;
         }
       if (LocaleCompare("splice",option+1) == 0)
@@ -3231,9 +3302,9 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
         }
       if (LocaleCompare("swirl",option+1) == 0)
         {
-          flags=ParseGeometry(arg2,&geometry_info);
+          flags=ParseGeometry(arg1,&geometry_info);
           if ((flags & RhoValue) == 0)
-            CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
+            CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           new_image=SwirlImage(_image,geometry_info.rho,
             _image->interpolate,_exception);
           break;
@@ -3248,7 +3319,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
             threshold;
 
           threshold=(double) QuantumRange/2;
-          if (normal_op) {
+          if (IfNormalOp) {
             if (IfMagickFalse(IsGeometry(arg1)))
               CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
             threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
@@ -3285,7 +3356,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
 
           (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
           (void) TransparentPaintImage(_image,&target,(Quantum)
-            TransparentAlpha,plus_alt_op,_exception);
+            TransparentAlpha,IsPlusOp,_exception);
           break;
         }
       if (LocaleCompare("transpose",option+1) == 0)
@@ -3319,7 +3390,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
              Option is not documented, bt appears to be for "identify".
              We may need a identify specific verbose!
           */
-          if (plus_alt_op) {
+          if (IsPlusOp) {
               (void) DeleteImageArtifact(_image,"identify:unique-colors");
               break;
             }
@@ -3372,6 +3443,11 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
             geometry_info.xi=0.1*_image->columns;
           if ((flags & PsiValue) == 0)
             geometry_info.psi=0.1*_image->rows;
+          if ((flags & PercentValue) != 0)
+            {
+              geometry_info.xi*=(double) _image->columns/100.0;
+              geometry_info.psi*=(double) _image->rows/100.0;
+            }
           new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
             ceil(geometry_info.psi-0.5),_exception);
@@ -3404,14 +3480,18 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
     default:
       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
   }
-  /*
-     Replace current image with any image that was generated
-     and set image point to last image (so image->next is correct)
-  */
+  /* clean up percent escape interpreted strings */
+  if (arg1 != arg1n )
+    arg1=DestroyString((char *)arg1);
+  if (arg2 != arg2n )
+    arg2=DestroyString((char *)arg2);
+
+  /* Replace current image with any image that was generated
+     and set image point to last image (so image->next is correct) */
   if (new_image != (Image *) NULL)
     ReplaceImageInListReturnLast(&_image,new_image);
 
-  return;
+  return(MagickTrue);
 #undef _image_info
 #undef _draw_info
 #undef _quantize_info
@@ -3419,23 +3499,27 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand,
 #undef _exception
 #undef IfNormalOp
 #undef IfPlusOp
-#undef normal_op
-#undef plus_alt_op
+#undef IsNormalOp
+#undef IsPlusOp
 }
 
-WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
-  const char *option, const char *arg1, const char *arg2)
+WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
+  const char *option,const char *arg1,const char *arg2)
 {
+#if !USE_WAND_METHODS
   size_t
     n,
     i;
+#endif
 
   assert(cli_wand != (MagickCLI *) NULL);
   assert(cli_wand->signature == WandSignature);
   assert(cli_wand->wand.signature == WandSignature);
   assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
+
   if (IfMagickTrue(cli_wand->wand.debug))
-    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+    (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+         "- Simple Operator: %s \"%s\" \"%s\"", option,arg1,arg2);
 
 #if !USE_WAND_METHODS
   /* FUTURE add appropriate tracing */
@@ -3457,7 +3541,7 @@ WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
     CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
   MagickResetIterator(&cli_wand->wand);
 #endif
-  return;
+  return(MagickTrue);
 }
 \f
 /*
@@ -3473,12 +3557,13 @@ WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
 %
 %  CLIListOperatorImages() applies a single operation that is apply to the
 %  entire image list as a whole. The result is often a complete replacment
-%  of the image list with a completely new list, or just a single image.
+%  of the image list with a completely new list, or with just a single image
+%  result.
 %
 %  The format of the MogrifyImage method is:
 %
-%    void CLIListOperatorImages(MagickCLI *cli_wand,
-%        const char *option, const char *arg1, const char *arg2)
+%    MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
+%      const char *option,const char *arg1,const char *arg2)
 %
 %  A description of each parameter follows:
 %
@@ -3490,31 +3575,69 @@ WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
 %        arg2 is currently not used
 %
 */
-WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
-     const char *option,const char *arg1, const char *magick_unused(arg2))
+WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
+  const char *option,const char *arg1n,const char *arg2n)
 {
-  ssize_t
-    parse;
+  const char    /* percent escaped versions of the args */
+    *arg1,
+    *arg2;
 
   Image
     *new_images;
 
+  MagickStatusType
+    status;
+
+  ssize_t
+    parse;
+
 #define _image_info     (cli_wand->wand.image_info)
 #define _images         (cli_wand->wand.images)
 #define _exception      (cli_wand->wand.exception)
 #define _draw_info      (cli_wand->draw_info)
 #define _quantize_info  (cli_wand->quantize_info)
+#define _process_flags  (cli_wand->process_flags)
+#define _option_type    ((CommandOptionFlags) cli_wand->command->flags)
 #define IfNormalOp      (*option=='-')
 #define IfPlusOp        (*option!='-')
-#define normal_op       IsMagickTrue(IfNormalOp)
+#define IsNormalOp       IsMagickTrue(IfNormalOp)
 
   assert(cli_wand != (MagickCLI *) NULL);
   assert(cli_wand->signature == WandSignature);
   assert(cli_wand->wand.signature == WandSignature);
   assert(_images != (Image *) NULL);             /* _images must be present */
+
   if (IfMagickTrue(cli_wand->wand.debug))
-    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+    (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+         "- List Operator: %s \"%s\" \"%s\"", option,arg1n,arg2n);
+
+  arg1 = arg1n;
+  arg2 = arg2n;
+
+  /* Interpret Percent Escapes in Arguments - using first image */
+  if ( (((_process_flags & ProcessInterpretProperities) != 0 )
+        || ((_option_type & AlwaysInterpretArgsFlag) != 0)
+       )  && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
+    /* Interpret Percent escapes in argument 1 */
+    if (arg1n != (char *) NULL) {
+      arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
+      if (arg1 == (char *) NULL) {
+        CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
+        arg1=arg1n;  /* use the given argument as is */
+      }
+    }
+    if (arg2n != (char *) NULL) {
+      arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
+      if (arg2 == (char *) NULL) {
+        CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
+        arg2=arg2n;  /* use the given argument as is */
+      }
+    }
+  }
+#undef _process_flags
+#undef _option_type
 
+  status=MagickTrue;
   new_images=NewImageList();
 
   switch (*(option+1))
@@ -3523,7 +3646,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
     {
       if (LocaleCompare("append",option+1) == 0)
         {
-          new_images=AppendImages(_images,normal_op,_exception);
+          new_images=AppendImages(_images,IsNormalOp,_exception);
           break;
         }
       if (LocaleCompare("average",option+1) == 0)
@@ -3566,8 +3689,56 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
         }
       if (LocaleCompare("combine",option+1) == 0)
         {
-          /* FUTURE - this may be replaced by a 'channel' method */
-          new_images=CombineImages(_images,_exception);
+          parse = (ssize_t) sRGBColorspace; /* default (backward compatible) */
+          if ( IfPlusOp )
+            parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
+                 arg1);
+          if (parse < 0)
+            CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",option,
+              arg1);
+          new_images=CombineImages(_images,(ColorspaceType) parse,_exception);
+          break;
+        }
+      if (LocaleCompare("compare",option+1) == 0)
+        {
+          double
+            distortion;
+
+          Image
+            *image,
+            *reconstruct_image;
+
+          MetricType
+            metric;
+
+          /*
+            Mathematically and visually annotate the difference between an
+            image and its reconstruction.
+          */
+          image=RemoveFirstImageFromList(&_images);
+          reconstruct_image=RemoveFirstImageFromList(&_images);
+          /* FUTURE - produce Exception, rather than silent fail */
+          if (reconstruct_image == (Image *) NULL)
+            break;
+          metric=UndefinedErrorMetric;
+          option=GetImageOption(_image_info,"metric");
+          if (option != (const char *) NULL)
+            metric=(MetricType) ParseCommandOption(MagickMetricOptions,
+              MagickFalse,option);
+          new_images=CompareImages(image,reconstruct_image,metric,&distortion,
+            _exception);
+          (void) distortion;
+          reconstruct_image=DestroyImage(reconstruct_image);
+          image=DestroyImage(image);
+          break;
+        }
+      if (LocaleCompare("complex",option+1) == 0)
+        {
+          parse=ParseCommandOption(MagickComplexOptions,MagickFalse,arg1);
+          if (parse < 0)
+            CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
+              option,arg1);
+          new_images=ComplexImages(_images,(ComplexOperator) parse,_exception);
           break;
         }
       if (LocaleCompare("composite",option+1) == 0)
@@ -3617,32 +3788,44 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
           /* FUTURE - this should not be here! - should be part of -geometry */
           (void) TransformImage(&source_image,(char *) NULL,
             source_image->geometry,_exception);
-
           SetGeometry(source_image,&geometry);
           (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
           GravityAdjustGeometry(new_images->columns,new_images->rows,
-               new_images->gravity, &geometry);
-
+            new_images->gravity, &geometry);
           mask_image=RemoveFirstImageFromList(&_images);
           if (mask_image != (Image *) NULL)
-            { /* handle a third write mask image */
+            {
               if ((compose == DisplaceCompositeOp) ||
-                  (compose == DistortCompositeOp)) {
-                /* Merge Y displacement into X displace/distort map. */
-                (void) CompositeImage(source_image,mask_image,
+                  (compose == DistortCompositeOp))
+                status&=CompositeImage(source_image,mask_image,
                   CopyGreenCompositeOp,MagickTrue,0,0,_exception);
-                mask_image=DestroyImage(mask_image);
-              }
-              else {
-                /* Set a blending mask for the composition.  */
-                (void) NegateImage(mask_image,MagickFalse,_exception);
-                (void) SetImageMask(new_images,mask_image,_exception);
-                mask_image=DestroyImage(mask_image);
-              }
+              else
+                {
+                  Image
+                    *image;
+
+                  RectangleInfo
+                    source_geometry;
+
+                  source_geometry.width=mask_image->columns;
+                  source_geometry.height=mask_image->rows;
+                  source_geometry.x=(-geometry.x);
+                  source_geometry.y=(-geometry.y);
+                  geometry.x=0;
+                  geometry.y=0;
+                  image=ExtentImage(source_image,&source_geometry,_exception);
+                  if (image != (Image *) NULL)
+                    {
+                      source_image=DestroyImage(source_image);
+                      source_image=image;
+                    }
+                  status&=CompositeImage(source_image,mask_image,
+                    IntensityCompositeOp,MagickTrue,0,0,_exception);
+                }
+              mask_image=DestroyImage(mask_image);
             }
-          (void) CompositeImage(new_images,source_image,compose,clip_to_self,
+          status&=CompositeImage(new_images,source_image,compose,clip_to_self,
             geometry.x,geometry.y,_exception);
-          (void) SetImageMask(new_images,(Image *) NULL,_exception);
           source_image=DestroyImage(source_image);
           break;
         }
@@ -3698,12 +3881,12 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
     {
       if (LocaleCompare("evaluate-sequence",option+1) == 0)
         {
-          parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
-          if ( parse < 0 )
+          parse=ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
+          if (parse < 0)
             CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
-                 option,arg1);
+              option,arg1);
           new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
-               _exception);
+            _exception);
           break;
         }
       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
@@ -3712,7 +3895,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
     {
       if (LocaleCompare("fft",option+1) == 0)
         {
-          new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
+          new_images=ForwardFourierTransformImage(_images,IsNormalOp,_exception);
           break;
         }
       if (LocaleCompare("flatten",option+1) == 0)
@@ -3762,7 +3945,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
            if (phase_image == (Image *) NULL)
              break;
            new_images=InverseFourierTransformImage(magnitude_image,phase_image,
-                   normal_op,_exception);
+                   IsNormalOp,_exception);
            magnitude_image=DestroyImage(magnitude_image);
            phase_image=DestroyImage(phase_image);
           break;
@@ -3807,7 +3990,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
           if ( parse < 0 )
             CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
                  option,arg1);
-          switch ((ImageLayerMethod) parse)
+          switch ((LayerMethod) parse)
           {
             case CoalesceLayer:
             {
@@ -3819,7 +4002,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
             case CompareOverlayLayer:
             default:
             {
-              new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
+              new_images=CompareImagesLayers(_images,(LayerMethod) parse,
                    _exception);
               break;
             }
@@ -3828,7 +4011,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
             case MosaicLayer:
             case TrimBoundsLayer:
             {
-              new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
+              new_images=MergeImageLayers(_images,(LayerMethod) parse,
                    _exception);
               break;
             }
@@ -3954,6 +4137,8 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
           (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
           break;
         }
+      if (LocaleCompare("metric",option+1) == 0)
+        break;
       if (LocaleCompare("morph",option+1) == 0)
         {
           Image
@@ -3979,16 +4164,20 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
     }
     case 'p':
     {
-      if (LocaleCompare("print",option+1) == 0)
+      if (LocaleCompare("poly",option+1) == 0)
         {
-          char
-            *string;
+          double
+            *args;
 
-          string=InterpretImageProperties(_image_info,_images,arg1,_exception);
-          if (string == (char *) NULL)
-            break;
-          (void) FormatLocaleFile(stdout,"%s",string);
-          string=DestroyString(string);
+          ssize_t
+            count;
+
+          /* convert argument string into an array of doubles */
+          args = StringToArrayOfDoubles(arg2,&count,_exception);
+          if (args == (double *)NULL )
+            CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
+          new_images=PolynomialImage(_images,count >> 1,args,_exception);
+          args=(double *) RelinquishMagickMemory(args);
           break;
         }
       if (LocaleCompare("process",option+1) == 0)
@@ -4027,6 +4216,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
               /*
                 Support old style syntax, filter="-option arg1".
               */
+              assert(arg1 != (const char *) NULL);
               length=strlen(arg1);
               token=(char *) NULL;
               if (~length >= (MaxTextExtent-1))
@@ -4087,7 +4277,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
           if (IfMagickFalse(IsGeometry(arg1)))
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           offset=(ssize_t) StringToLong(arg1);
-          new_images=SmushImages(_images,normal_op,offset,_exception);
+          new_images=SmushImages(_images,IsNormalOp,offset,_exception);
           break;
         }
       if (LocaleCompare("subimage",option+1) == 0)
@@ -4112,13 +4302,13 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
           compare_image=GetImageFromList(_images,1);
 
           /* Comparision Metric */
-          metric=UndefinedMetric;
+          metric=UndefinedErrorMetric;
           value=GetImageOption(_image_info,"metric");
           if (value != (const char *) NULL)
             metric=(MetricType) ParseCommandOption(MagickMetricOptions,
               MagickFalse,value);
 
-          new_images=SimilarityImage(base_image,compare_image,metric,
+          new_images=SimilarityImage(base_image,compare_image,metric,0.0,
                &offset,&similarity,_exception);
 
           if ( new_images != (Image *)NULL ) {
@@ -4154,8 +4344,8 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
           index,
           swap_index;
 
-        index=-1;
-        swap_index=-2;
+        index=(-1);
+        swap_index=(-2);
         if (IfNormalOp) {
           GeometryInfo
             geometry_info;
@@ -4165,7 +4355,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
 
           swap_index=(-1);
           flags=ParseGeometry(arg1,&geometry_info);
-          if ((flags & RhoValue) != 0)
+          if ((flags & RhoValue) == 0)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           index=(ssize_t) geometry_info.rho;
           if ((flags & SigmaValue) != 0)
@@ -4192,13 +4382,19 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
     default:
       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
   }
-  if (new_images == (Image *) NULL)
-    return;
 
-  if (_images != (Image *) NULL)
-    _images=DestroyImageList(_images);
+  /* clean up percent escape interpreted strings */
+  if (arg1 != arg1n )
+    arg1=DestroyString((char *)arg1);
+  if (arg2 != arg2n )
+    arg2=DestroyString((char *)arg2);
+
+  /* if new image list generated, replace existing image list */
+  if (new_images == (Image *) NULL)
+    return(status == 0 ? MagickFalse : MagickTrue);
+  _images=DestroyImageList(_images);
   _images=GetFirstImageInList(new_images);
-  return;
+  return(status == 0 ? MagickFalse : MagickTrue);
 
 #undef _image_info
 #undef _images
@@ -4207,7 +4403,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
 #undef _quantize_info
 #undef IfNormalOp
 #undef IfPlusOp
-#undef normal_op
+#undef IsNormalOp
 }
 \f
 /*
@@ -4215,21 +4411,21 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   C L I S p e c i a l O p e r a t i o n s                                   %
++   C L I N o I m a g e O p e r a t i o n s                                   %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %  CLINoImageOperator() Applies operations that may not actually need images
-%  in an image list wen it is applied.
+%  in an image list.
 %
-%  The classic operators of this type is -read, which actually creates images
-%  even when no images are present.  Or image stack operators, which can be
-%  applied to empty image lists.
+%  The classic operators of this type is "-read", which actually creates
+%  images even when no images are present.  Or image stack operators, which
+%  can be applied (push or pop) to an empty image list.
 %
-%  Note: unlike other Operators, these may involve other special 'option'
-%  character prefixes, other than simply '-' or '+'.
+%  Note that these operators may involve other special 'option' prefix
+%  characters other  than '-' or '+', namely parenthesis and braces.
 %
 %  The format of the CLINoImageOption method is:
 %
@@ -4238,7 +4434,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
 %
 %  A description of each parameter follows:
 %
-%    o cli_wand: the main CLI Wand to use.
+%    o cli_wand: the main CLI Wand to use. (sometimes not required)
 %
 %    o option: The special option (with any switch char) to process
 %
@@ -4246,335 +4442,475 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
 %                   Currently arg2 is not used.
 %
 */
-WandExport void CLINoImageOperator(MagickCLI *cli_wand,
-  const char *option, const char *arg1, const char *magick_unused(arg2))
+WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
+  const char *option,const char *arg1n,const char *arg2n)
 {
+  const char    /* percent escaped versions of the args */
+    *arg1,
+    *arg2;
+
 #define _image_info     (cli_wand->wand.image_info)
 #define _images         (cli_wand->wand.images)
 #define _exception      (cli_wand->wand.exception)
+#define _process_flags  (cli_wand->process_flags)
+#define _option_type    ((CommandOptionFlags) cli_wand->command->flags)
 #define IfNormalOp      (*option=='-')
 #define IfPlusOp        (*option!='-')
 
   assert(cli_wand != (MagickCLI *) NULL);
   assert(cli_wand->signature == WandSignature);
   assert(cli_wand->wand.signature == WandSignature);
+
   if (IfMagickTrue(cli_wand->wand.debug))
-    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+    (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+         "- NoImage Operator: %s \"%s\" \"%s\"", option,arg1n,arg2n);
+
+  arg1 = arg1n;
+  arg2 = arg2n;
+
+  /* Interpret Percent Escapes in Arguments - using first image */
+  if ( (((_process_flags & ProcessInterpretProperities) != 0 )
+        || ((_option_type & AlwaysInterpretArgsFlag) != 0)
+       )  && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
+    /* Interpret Percent escapes in argument 1 */
+    if (arg1n != (char *) NULL) {
+      arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
+      if (arg1 == (char *) NULL) {
+        CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
+        arg1=arg1n;  /* use the given argument as is */
+      }
+    }
+    if (arg2n != (char *) NULL) {
+      arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
+      if (arg2 == (char *) NULL) {
+        CLIWandException(OptionWarning,"InterpretPropertyFailure",option);
+        arg2=arg2n;  /* use the given argument as is */
+      }
+    }
+  }
+#undef _process_flags
+#undef _option_type
+
+  do {  /* break to exit code */
+    /*
+      No-op options  (ignore these)
+    */
+    if (LocaleCompare("noop",option+1) == 0)   /* zero argument */
+      break;
+    if (LocaleCompare("sans",option+1) == 0)   /* one argument */
+      break;
+    if (LocaleCompare("sans0",option+1) == 0)  /* zero argument */
+      break;
+    if (LocaleCompare("sans1",option+1) == 0)  /* one argument */
+      break;
+    if (LocaleCompare("sans2",option+1) == 0)  /* two arguments */
+      break;
+    /*
+      Image Reading
+    */
+    if ( ( LocaleCompare("read",option+1) == 0 ) ||
+      ( LocaleCompare("--",option) == 0 ) ) {
+      /* Do Glob filename Expansion for 'arg1' then read all images.
+      *
+      * Expansion handles '@', '~', '*', and '?' meta-characters while ignoring
+      * (but attaching to the filenames in the generated argument list) any
+      * [...] read modifiers that may be present.
+      *
+      * For example: It will expand '*.gif[20x20]' into a list such as
+      * 'abc.gif[20x20]',  'foobar.gif[20x20]',  'xyzzy.gif[20x20]'
+      *
+      * NOTE: In IMv6 this was done globally across all images. This
+      * meant you could include IM options in '@filename' lists, but you
+      * could not include comments.   Doing it only for image read makes
+      * it far more secure.
+      *
+      * Note: arguments do not have percent escapes expanded for security
+      * reasons.
+      */
+      int      argc;
+      char     **argv;
+      ssize_t  i;
 
-  /*
-    No-op options  (ignore these)
-  */
-  if (LocaleCompare("noop",option+1) == 0)   /* no argument */
-    return;
-  if (LocaleCompare("sans",option+1) == 0)   /* one argument */
-    return;
-  if (LocaleCompare("sans0",option+1) == 0)  /* no argument */
-    return;
-  if (LocaleCompare("sans2",option+1) == 0)  /* two arguments */
-    return;
-  /*
-    Image Reading
-  */
-  if ( ( LocaleCompare("read",option+1) == 0 ) ||
-     ( LocaleCompare("--",option) == 0 ) ) {
-    int
-      argc;
-    char
-      **argv;
-
-    ssize_t
-      i;
-
-    /* Expand the filename argument (meta-characters or "@filelist" ) */
-    argc = 1;
-    argv = (char **) &arg1;
-    MagickBooleanType
-      status=ExpandFilenames(&argc,&argv);
-
-    if (IfMagickFalse(status))
-      CLIWandExceptArgReturn(ResourceLimitError,"MemoryAllocationFailed",
-          option,GetExceptionMessage(errno));
-
-    /* loop over expanded list reading images */
-    for (i=0; i<argc; i++) {
-#if !USE_WAND_METHODS
-      Image *
-        new_images;
-      if (IfMagickTrue(_image_info->ping))
-        new_images=PingImages(_image_info,argv[i],_exception);
-      else
-        new_images=ReadImages(_image_info,argv[i],_exception);
-      AppendImageToList(&_images, new_images);
-#else
-      /* read images using MagickWand method - no ping */
-      /* This is not working! - it locks up in a CPU loop! */
-      MagickSetLastIterator(&cli_wand->wand);
-      MagickReadImage(&cli_wand->wand,arg1);
-      MagickSetFirstIterator(&cli_wand->wand);
-#endif
+      argc = 1;
+      argv = (char **) &arg1;
+
+      /* Expand 'glob' expressions in the given filename.
+        Expansion handles any 'coder:' prefix, or read modifiers attached
+        to the filename, including them in the resulting expanded list.
+      */
+      if (IfMagickFalse(  ExpandFilenames(&argc,&argv)  ))
+        CLIWandExceptArgBreak(ResourceLimitError,"MemoryAllocationFailed",
+            option,GetExceptionMessage(errno));
+
+      /* loop over expanded filename list, and read then all in */
+      for (i=0; i<argc; i++) {
+        Image *
+          new_images;
+        if (IfMagickTrue(_image_info->ping))
+          new_images=PingImages(_image_info,argv[i],_exception);
+        else
+          new_images=ReadImages(_image_info,argv[i],_exception);
+        AppendImageToList(&_images, new_images);
+      }
+      argv=DestroyStringList(argv);  /* Destroy the Expanded Filename list */
+      break;
     }
-    /* FUTURE: how do I free the expanded filename arguments??? */
+    /*
+      Image Writing
+      Note: Writing a empty image list is valid in specific cases
+    */
+    if (LocaleCompare("write",option+1) == 0) {
+      /* Note: arguments do not have percent escapes expanded */
+      char
+        key[MaxTextExtent];
 
-    return;
-  }
-  /*
-    Image Writing  (no-images present is valid in specific cases)
-  */
-  if (LocaleCompare("write",option+1) == 0) {
-    char
-      key[MaxTextExtent];
+      Image
+        *write_images;
 
-    Image
-      *write_images;
+      ImageInfo
+        *write_info;
 
-    ImageInfo
-      *write_info;
+      /* Need images, unless a "null:" output coder is used */
+      if ( _images == (Image *) NULL ) {
+        if ( LocaleCompare(arg1,"null:") == 0 )
+          break;
+        CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
+      }
 
-    /* Need images, unless a "null:" output coder is used */
-    if ( cli_wand->wand.images == (Image *) NULL ) {
-      if ( LocaleCompare(arg1,"null:") == 0 )
-        return;
-      CLIWandExceptArgReturn(OptionError,"NoImagesForWrite",option,arg1);
+      (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
+      (void) DeleteImageRegistry(key);
+      write_images=_images;
+      if (IfPlusOp)
+        write_images=CloneImageList(_images,_exception);
+      write_info=CloneImageInfo(_image_info);
+      (void) WriteImages(write_info,write_images,arg1,_exception);
+      write_info=DestroyImageInfo(write_info);
+      if (IfPlusOp)
+        write_images=DestroyImageList(write_images);
+      break;
+    }
+    /*
+      Parenthesis and Brace operations
+    */
+    if (LocaleCompare("(",option) == 0) {
+      /* stack 'push' images */
+      Stack
+        *node;
+
+      size_t
+        size;
+
+      size=0;
+      node=cli_wand->image_list_stack;
+      for ( ; node != (Stack *)NULL; node=node->next)
+        size++;
+      if ( size >= MAX_STACK_DEPTH )
+        CLIWandExceptionBreak(OptionError,"ParenthesisNestedTooDeeply",option);
+      node=(Stack *) AcquireMagickMemory(sizeof(*node));
+      if (node == (Stack *) NULL)
+        CLIWandExceptionBreak(ResourceLimitFatalError,
+            "MemoryAllocationFailed",option);
+      node->data = (void *)cli_wand->wand.images;
+      node->next = cli_wand->image_list_stack;
+      cli_wand->image_list_stack = node;
+      cli_wand->wand.images = NewImageList();
+
+      /* handle respect-parenthesis */
+      if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
+                    "respect-parenthesis"))))
+        option="{"; /* fall-thru so as to push image settings too */
+      else
+        break;
+      /* fall thru to operation */
     }
+    if (LocaleCompare("{",option) == 0) {
+      /* stack 'push' of image_info settings */
+      Stack
+        *node;
+
+      size_t
+        size;
+
+      size=0;
+      node=cli_wand->image_info_stack;
+      for ( ; node != (Stack *)NULL; node=node->next)
+        size++;
+      if ( size >= MAX_STACK_DEPTH )
+        CLIWandExceptionBreak(OptionError,"CurlyBracesNestedTooDeeply",option);
+      node=(Stack *) AcquireMagickMemory(sizeof(*node));
+      if (node == (Stack *) NULL)
+        CLIWandExceptionBreak(ResourceLimitFatalError,
+            "MemoryAllocationFailed",option);
+
+      node->data = (void *)cli_wand->wand.image_info;
+      node->next = cli_wand->image_info_stack;
+
+      cli_wand->image_info_stack = node;
+      cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
+      if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
+        CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
+            option);
+        cli_wand->wand.image_info = (ImageInfo *)node->data;
+        node = (Stack *)RelinquishMagickMemory(node);
+        break;
+      }
 
-    (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
-    (void) DeleteImageRegistry(key);
-    write_images=_images;
-    if (IfPlusOp)
-      write_images=CloneImageList(_images,_exception);
-    write_info=CloneImageInfo(_image_info);
-    (void) WriteImages(write_info,write_images,arg1,_exception);
-    write_info=DestroyImageInfo(write_info);
-    if (IfPlusOp)
-      write_images=DestroyImageList(write_images);
-    return;
-  }
-  /*
-    Parenthesis and Brace operations
-  */
-  if (LocaleCompare("(",option) == 0) {
-    /* stack 'push' images */
-    Stack
-      *node;
-
-    size_t
-      size;
-
-    size=0;
-    node=cli_wand->image_list_stack;
-    for ( ; node != (Stack *)NULL; node=node->next)
-      size++;
-    if ( size >= MAX_STACK_DEPTH )
-      CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
-    node=(Stack *) AcquireMagickMemory(sizeof(*node));
-    if (node == (Stack *) NULL)
-      CLIWandExceptionReturn(ResourceLimitFatalError,
-           "MemoryAllocationFailed",option);
-    node->data = (void *)cli_wand->wand.images;
-    cli_wand->wand.images = NewImageList();
-    node->next = cli_wand->image_list_stack;
-    cli_wand->image_list_stack = node;
-
-    /* handle respect-parenthesis */
-    if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
-                  "respect-parenthesis"))))
-      option="{"; /* fall-thru so as to push image settings too */
-    else
-      return;
-  }
-  if (LocaleCompare("{",option) == 0) {
-    /* stack 'push' of image_info settings */
-    Stack
-      *node;
-
-    size_t
-      size;
-
-    size=0;
-    node=cli_wand->image_info_stack;
-    for ( ; node != (Stack *)NULL; node=node->next)
-      size++;
-    if ( size >= MAX_STACK_DEPTH )
-      CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
-    node=(Stack *) AcquireMagickMemory(sizeof(*node));
-    if (node == (Stack *) NULL)
-      CLIWandExceptionReturn(ResourceLimitFatalError,
-           "MemoryAllocationFailed",option);
-
-    node->data = (void *)cli_wand->wand.image_info;
-    cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
-    if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
-      CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
-           option);
-      cli_wand->wand.image_info = (ImageInfo *)node->data;
+      break;
+    }
+    if (LocaleCompare(")",option) == 0) {
+      /* pop images from stack */
+      Stack
+        *node;
+
+      node = (Stack *)cli_wand->image_list_stack;
+      if ( node == (Stack *)NULL)
+        CLIWandExceptionBreak(OptionError,"UnbalancedParenthesis",option);
+      cli_wand->image_list_stack = node->next;
+
+      AppendImageToList((Image **)&node->data,cli_wand->wand.images);
+      cli_wand->wand.images= (Image *)node->data;
       node = (Stack *)RelinquishMagickMemory(node);
-      return;
+
+      /* handle respect-parenthesis - of the previous 'pushed' settings */
+      node = cli_wand->image_info_stack;
+      if ( node != (Stack *)NULL)
+        {
+          if (IfMagickTrue(IsStringTrue(GetImageOption(
+                cli_wand->wand.image_info,"respect-parenthesis"))))
+            option="}"; /* fall-thru so as to pop image settings too */
+          else
+            break;
+        }
+      else
+        break;
+      /* fall thru to next if */
     }
+    if (LocaleCompare("}",option) == 0) {
+      /* pop image_info settings from stack */
+      Stack
+        *node;
 
-    node->next = cli_wand->image_info_stack;
-    cli_wand->image_info_stack = node;
+      node = (Stack *)cli_wand->image_info_stack;
+      if ( node == (Stack *)NULL)
+        CLIWandExceptionBreak(OptionError,"UnbalancedCurlyBraces",option);
+      cli_wand->image_info_stack = node->next;
 
-    return;
-  }
-  if (LocaleCompare(")",option) == 0) {
-    /* pop images from stack */
-    Stack
-      *node;
-
-    node = (Stack *)cli_wand->image_list_stack;
-    if ( node == (Stack *)NULL)
-      CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
-    cli_wand->image_list_stack = node->next;
-
-    AppendImageToList((Image **)&node->data,cli_wand->wand.images);
-    cli_wand->wand.images= (Image *)node->data;
-    node = (Stack *)RelinquishMagickMemory(node);
-
-    /* handle respect-parenthesis - of the previous 'pushed' settings */
-    node = cli_wand->image_info_stack;
-    if ( node != (Stack *)NULL)
+      (void) DestroyImageInfo(cli_wand->wand.image_info);
+      cli_wand->wand.image_info = (ImageInfo *)node->data;
+      node = (Stack *)RelinquishMagickMemory(node);
+
+      GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
+      cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
+      cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
+
+      break;
+    }
+      if (LocaleCompare("print",option+1) == 0)
+        {
+          (void) FormatLocaleFile(stdout,"%s",arg1);
+          break;
+        }
+    if (LocaleCompare("set",option+1) == 0)
       {
-        if (IfMagickTrue(IsStringTrue(GetImageOption(
-               cli_wand->wand.image_info,"respect-parenthesis"))))
-          option="}"; /* fall-thru so as to pop image settings too */
-        else
-          return;
-      }
-    else
-      return;
-  }
-  if (LocaleCompare("}",option) == 0) {
-    /* pop image_info settings from stack */
-    Stack
-      *node;
+        /* Settings are applied to each image in memory in turn (if any).
+           While a option: only need to be applied once globally.
 
-    node = (Stack *)cli_wand->image_info_stack;
-    if ( node == (Stack *)NULL)
-      CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
-    cli_wand->image_info_stack = node->next;
+           NOTE: rguments have not been automatically percent expaneded
+        */
 
-    (void) DestroyImageInfo(cli_wand->wand.image_info);
-    cli_wand->wand.image_info = (ImageInfo *)node->data;
-    node = (Stack *)RelinquishMagickMemory(node);
+        /* escape the 'key' once only, using first image. */
+        arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
+        if (arg1 == (char *) NULL)
+          CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
+                option);
 
-    GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
-    cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
-    cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
+        if (LocaleNCompare(arg1,"registry:",9) == 0)
+          {
+            if (IfPlusOp)
+              {
+                (void) DeleteImageRegistry(arg1+9);
+                arg1=DestroyString((char *)arg1);
+                break;
+              }
+            arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
+            if (arg2 == (char *) NULL) {
+              arg1=DestroyString((char *)arg1);
+              CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
+                    option);
+            }
+            (void) SetImageRegistry(StringRegistryType,arg1+9,arg2,_exception);
+            arg1=DestroyString((char *)arg1);
+            arg2=DestroyString((char *)arg2);
+            break;
+          }
+        if (LocaleNCompare(arg1,"option:",7) == 0)
+          {
+            /* delete equivelent artifact from all images (if any) */
+            if (_images != (Image *)NULL)
+              {
+                MagickResetIterator(&cli_wand->wand);
+                while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
+                  (void) DeleteImageArtifact(_images,arg1+7);
+                MagickResetIterator(&cli_wand->wand);
+              }
+            /* now set/delete the global option as needed */
+            /* FUTURE: make escapes in a global 'option:' delayed */
+            arg2=(char *)NULL;
+            if (IfNormalOp)
+              {
+                arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
+                if (arg2 == (char *) NULL)
+                  CLIWandExceptionBreak(OptionWarning,
+                       "InterpretPropertyFailure",option);
+              }
+            (void) SetImageOption(_image_info,arg1+7,arg2);
+            arg1=DestroyString((char *)arg1);
+            arg2=DestroyString((char *)arg2);
+            break;
+          }
+        /* Set Artifacts/Properties/Attributes all images (required) */
+        if ( _images == (Image *) NULL )
+          CLIWandExceptArgBreak(OptionWarning,"NoImageForProperty",option,arg1);
 
-    return;
-  }
-  if (LocaleCompare("clone",option+1) == 0) {
-      Image
-        *new_images;
-
-      if (*option == '+')
-        arg1="-1";
-      if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
-        CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
-      if ( cli_wand->image_list_stack == (Stack *)NULL)
-        CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
-      new_images = (Image *)cli_wand->image_list_stack->data;
-      if (new_images == (Image *) NULL)
-        CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
-      new_images=CloneImages(new_images,arg1,_exception);
-      if (new_images == (Image *) NULL)
-        CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
-      AppendImageToList(&_images,new_images);
-      return;
-    }
-  /*
-    Informational Operations
-  */
-  if (LocaleCompare("version",option+1) == 0) {
-    (void) FormatLocaleFile(stdout,"Version: %s\n",
-      GetMagickVersion((size_t *) NULL));
-    (void) FormatLocaleFile(stdout,"Copyright: %s\n",
-      GetMagickCopyright());
-    (void) FormatLocaleFile(stdout,"Features: %s\n\n",
-      GetMagickFeatures());
-    return;
-  }
-  if (LocaleCompare("list",option+1) == 0) {
-    /* FUTURE: This should really be built into the MagickCore
-       It does not actually require a cli-wand or and images!
-     */
-    ssize_t
-      list;
-
-    list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
-    if ( list < 0 ) {
-      CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
-      return;
-    }
-    switch (list)
-    {
-      case MagickCoderOptions:
-      {
-        (void) ListCoderInfo((FILE *) NULL,_exception);
+        MagickResetIterator(&cli_wand->wand);
+        while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
+          {
+            arg2=(char *)NULL;
+            if (IfNormalOp)
+              {
+                arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
+                if (arg2 == (char *) NULL)
+                  CLIWandExceptionBreak(OptionWarning,
+                       "InterpretPropertyFailure",option);
+              }
+            if (LocaleNCompare(arg1,"artifact:",9) == 0)
+              (void) SetImageArtifact(_images,arg1+9,arg2);
+            else if (LocaleNCompare(arg1,"property:",9) == 0)
+              (void) SetImageProperty(_images,arg1+9,arg2,_exception);
+            else
+              (void) SetImageProperty(_images,arg1,arg2,_exception);
+            arg2=DestroyString((char *)arg2);
+          }
+        MagickResetIterator(&cli_wand->wand);
+        arg1=DestroyString((char *)arg1);
         break;
-      }
-      case MagickColorOptions:
-      {
-        (void) ListColorInfo((FILE *) NULL,_exception);
+     }
+    if (LocaleCompare("clone",option+1) == 0) {
+        Image
+          *new_images;
+
+        if (*option == '+')
+          arg1="-1";
+        if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
+          CLIWandExceptionBreak(OptionError,"InvalidArgument",option);
+        if ( cli_wand->image_list_stack == (Stack *)NULL)
+          CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
+        new_images = (Image *)cli_wand->image_list_stack->data;
+        if (new_images == (Image *) NULL)
+          CLIWandExceptionBreak(OptionError,"UnableToCloneImage",option);
+        new_images=CloneImages(new_images,arg1,_exception);
+        if (new_images == (Image *) NULL)
+          CLIWandExceptionBreak(OptionError,"NoSuchImage",option);
+        AppendImageToList(&_images,new_images);
         break;
       }
-      case MagickConfigureOptions:
+    /*
+       Informational Operations.
+
+       Note that these do not require either a cli-wand or images!
+       Though currently a cli-wand much be provided regardless.
+    */
+    if (LocaleCompare("version",option+1) == 0)
       {
-        (void) ListConfigureInfo((FILE *) NULL,_exception);
+        ListMagickVersion(stdout);
         break;
       }
-      case MagickDelegateOptions:
-      {
-        (void) ListDelegateInfo((FILE *) NULL,_exception);
+    if (LocaleCompare("list",option+1) == 0) {
+      /*
+         FUTURE: This 'switch' should really be part of MagickCore
+      */
+      ssize_t
+        list;
+
+      list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
+      if ( list < 0 ) {
+        CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
         break;
       }
-      case MagickFontOptions:
+      switch (list)
       {
-        (void) ListTypeInfo((FILE *) NULL,_exception);
-        break;
+        case MagickCoderOptions:
+        {
+          (void) ListCoderInfo((FILE *) NULL,_exception);
+          break;
+        }
+        case MagickColorOptions:
+        {
+          (void) ListColorInfo((FILE *) NULL,_exception);
+          break;
+        }
+        case MagickConfigureOptions:
+        {
+          (void) ListConfigureInfo((FILE *) NULL,_exception);
+          break;
+        }
+        case MagickDelegateOptions:
+        {
+          (void) ListDelegateInfo((FILE *) NULL,_exception);
+          break;
+        }
+        case MagickFontOptions:
+        {
+          (void) ListTypeInfo((FILE *) NULL,_exception);
+          break;
+        }
+        case MagickFormatOptions:
+          (void) ListMagickInfo((FILE *) NULL,_exception);
+          break;
+        case MagickLocaleOptions:
+          (void) ListLocaleInfo((FILE *) NULL,_exception);
+          break;
+        case MagickLogOptions:
+          (void) ListLogInfo((FILE *) NULL,_exception);
+          break;
+        case MagickMagicOptions:
+          (void) ListMagicInfo((FILE *) NULL,_exception);
+          break;
+        case MagickMimeOptions:
+          (void) ListMimeInfo((FILE *) NULL,_exception);
+          break;
+        case MagickModuleOptions:
+          (void) ListModuleInfo((FILE *) NULL,_exception);
+          break;
+        case MagickPolicyOptions:
+          (void) ListPolicyInfo((FILE *) NULL,_exception);
+          break;
+        case MagickResourceOptions:
+          (void) ListMagickResourceInfo((FILE *) NULL,_exception);
+          break;
+        case MagickThresholdOptions:
+          (void) ListThresholdMaps((FILE *) NULL,_exception);
+          break;
+        default:
+          (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
+            _exception);
+          break;
       }
-      case MagickFormatOptions:
-        (void) ListMagickInfo((FILE *) NULL,_exception);
-        break;
-      case MagickLocaleOptions:
-        (void) ListLocaleInfo((FILE *) NULL,_exception);
-        break;
-      case MagickLogOptions:
-        (void) ListLogInfo((FILE *) NULL,_exception);
-        break;
-      case MagickMagicOptions:
-        (void) ListMagicInfo((FILE *) NULL,_exception);
-        break;
-      case MagickMimeOptions:
-        (void) ListMimeInfo((FILE *) NULL,_exception);
-        break;
-      case MagickModuleOptions:
-        (void) ListModuleInfo((FILE *) NULL,_exception);
-        break;
-      case MagickPolicyOptions:
-        (void) ListPolicyInfo((FILE *) NULL,_exception);
-        break;
-      case MagickResourceOptions:
-        (void) ListMagickResourceInfo((FILE *) NULL,_exception);
-        break;
-      case MagickThresholdOptions:
-        (void) ListThresholdMaps((FILE *) NULL,_exception);
-        break;
-      default:
-        (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
-          _exception);
-        break;
+      break;
     }
-    return;
-  }
 
-#if 0
-  // Other 'special' options this should handle
-  //    "region"  "reset"  "arg"
-  if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
-#endif
     CLIWandException(OptionError,"UnrecognizedOption",option);
 
+DisableMSCWarning(4127)
+  } while (0);  /* break to exit code. */
+RestoreMSCWarning
+
+  /* clean up percent escape interpreted strings */
+  if (arg1 != arg1n )
+    arg1=DestroyString((char *)arg1);
+  if (arg2 != arg2n )
+    arg2=DestroyString((char *)arg2);
+
 #undef _image_info
 #undef _images
 #undef _exception
@@ -4587,19 +4923,25 @@ WandExport void CLINoImageOperator(MagickCLI *cli_wand,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   C L I O p t i o n O p e r a t i o n s                                     %
++   C L I O p t i o n                                                         %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %  CLIOption() Processes the given option using the given CLI Magick Wand.
+%  The option arguments can be variable in number, though at this time no more
+%  that two is actually used by any option (this may change). Excess options
+%  are simply ignored.
 %
 %  If the cli_wand->command pointer is non-null, then it is assumed that the
 %  option has already been search for up from the CommandOptions[] table in
-%  "MagickCore/options.c" using  GetCommandOptionInfo(), so that any command
-%  specific options (such as "magick" scripting options, or "display" settings)
-%  can be handled separatally.
+%  "MagickCore/options.c" using  GetCommandOptionInfo().  If not set this
+%  routine will do the lookup instead. The pointer is reset afterward.
+%
+%  This action allows the caller to lookup and pre-handle any 'special'
+%  options, (such as implicit reads) before calling this general option
+%  handler to deal with 'standard' command line options.
 %
 %  The format of the CLIOption method is:
 %
@@ -4611,7 +4953,7 @@ WandExport void CLINoImageOperator(MagickCLI *cli_wand,
 %
 %     o option: The special option (with any switch char) to process
 %
-%     o args: any required arguments for an option
+%     o args: any required arguments for an option (variable number)
 %
 %  Example Usage...
 %
@@ -4623,7 +4965,7 @@ WandExport void CLINoImageOperator(MagickCLI *cli_wand,
 */
 WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
 {
-  const char
+  const char    /* extracted option args from args */
     *arg1,
     *arg2;
 
@@ -4633,91 +4975,96 @@ WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
   assert(cli_wand != (MagickCLI *) NULL);
   assert(cli_wand->signature == WandSignature);
   assert(cli_wand->wand.signature == WandSignature);
-  if (IfMagickTrue(cli_wand->wand.debug))
-    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
 
-  if ( cli_wand->command == (const OptionInfo *) NULL )
-    cli_wand->command = GetCommandOptionInfo(option);
+  do { /* Break Code Block for error handling */
+
+    /* get information about option */
+    if ( cli_wand->command == (const OptionInfo *) NULL )
+      cli_wand->command = GetCommandOptionInfo(option);
 #if 0
-    (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
-          option, cli_wand->command->mnemonic );
+      (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n",
+            option, cli_wand->command->mnemonic );
 #endif
+    option_type=(CommandOptionFlags) cli_wand->command->flags;
 
-  option_type=(CommandOptionFlags) cli_wand->command->flags;
+    if ( option_type == UndefinedOptionFlag )
+      CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
 
-  if ( option_type == UndefinedOptionFlag )
-    CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option);
+    assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
 
-  assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 );
+    /* depreciated options */
+    if ( (option_type & DeprecateOptionFlag) != 0 )
+      CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option);
 
-  if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
-    CLIWandExceptionReturn(OptionFatalError,"InvalidUseOfOption",option);
+    /* options that this module does not handle */
+    if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 )
+      CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
 
-  if ( (option_type & DeprecateOptionFlag) != 0 )
-    CLIWandExceptionReturn(OptionError,"DeprecatedOptionNoCode",option);
+    /* Get argument strings from VarArgs
+      How can you determine if enough arguments was supplied?
+      What happens if not enough arguments were supplied?
+    */
+    { size_t
+        count = cli_wand->command->type;
 
-  if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
-    return;
+      va_list
+        operands;
 
+      va_start(operands,option);
 
-  { size_t
-      count = cli_wand->command->type;
+      arg1=arg2=NULL;
+      if ( count >= 1 )
+        arg1=(const char *) va_arg(operands, const char *);
+      if ( count >= 2 )
+        arg2=(const char *) va_arg(operands, const char *);
 
-    va_list
-      operands;
-
-    va_start(operands,option);
-
-    arg1=arg2=NULL;
-    if ( count >= 1 )
-      arg1=(const char *) va_arg(operands, const char *);
-    if ( count >= 2 )
-      arg2=(const char *) va_arg(operands, const char *);
-
-    va_end(operands);
-
-#if 1
-    (void) FormatLocaleFile(stderr,
-      "CLIOption: \"%s\"  Count: %d  Flags: %04x  Args: \"%s\" \"%s\"\n",
-          option,count,option_type,arg1,arg2);
+      va_end(operands);
+#if 0
+      (void) FormatLocaleFile(stderr,
+        "CLIOption: \"%s\"  Count: %ld  Flags: %04x  Args: \"%s\" \"%s\"\n",
+            option,(long) count,option_type,arg1,arg2);
 #endif
-  }
+    }
 
-  cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
+    /*
+      Call the appropriate option handler
+    */
 
+    /* FUTURE: this is temporary - get 'settings' to handle distribution of
+      settings to images attributes,proprieties,artifacts */
+    if ( cli_wand->wand.images != (Image *)NULL )
+      SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
+          cli_wand->wand.exception);
 
-  /*
-     Call the appropriate option handler
-  */
+    if ( (option_type & SettingOptionFlags) != 0 ) {
+      CLISettingOptionInfo(cli_wand, option, arg1, arg2);
+      // FUTURE: Sync Specific Settings into Image Properities (not global)
+    }
 
-  /* FUTURE: this is temporary - get 'settings' to handle
-     distribution of settings to images attributes,proprieties,artifacts */
-  if ( cli_wand->wand.images != (Image *)NULL )
-    SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
-        cli_wand->wand.exception);
+    /* Operators that do not need images - read, write, stack, clone */
+    if ( (option_type & NoImageOperatorFlag) != 0)
+      CLINoImageOperator(cli_wand, option, arg1, arg2);
 
-  if ( (option_type & SettingOptionFlags) != 0 ) {
-    CLISettingOptionInfo(cli_wand, option, arg1, arg2);
-    // FUTURE: Sync Specific Settings into Image Properities (not global)
-  }
+    /* FUTURE: The not a setting part below is a temporary hack due to
+    * some options being both a Setting and a Simple operator.
+    * Specifically -monitor, -depth, and  -colorspace */
+    if ( cli_wand->wand.images == (Image *)NULL )
+      if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
+          ((option_type & SettingOptionFlags) == 0 ))  /* temp hack */
+        CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
 
-  if ( (option_type & NoImageOperatorFlag) != 0)
-    CLINoImageOperator(cli_wand, option, arg1, arg2);
-
-  /* FUTURE: The not a setting part below is a temporary hack due to
-   * some options being both a Setting and a Simple operator.
-   * Specifically -monitor, -depth, and  -colorspace */
-  if ( cli_wand->wand.images == (Image *)NULL ) {
-    if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) &&
-         ((option_type & SettingOptionFlags) == 0 ))  /* temp hack */
-      CLIWandException(OptionError,"NoImagesFound",option);
-    return; /* on its own this is not an error */
-  }
+    /* Operators which loop of individual images, simply */
+    if ( (option_type & SimpleOperatorFlag) != 0 &&
+         cli_wand->wand.images != (Image *)NULL) /* temp hack */
+      CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
 
-  if ( (option_type & SimpleOperatorFlag) != 0)
-    CLISimpleOperatorImages(cli_wand, option, arg1, arg2);
+    /* Operators that work on the image list as a whole */
+    if ( (option_type & ListOperatorFlag) != 0 )
+      CLIListOperatorImages(cli_wand, option, arg1, arg2);
 
-  if ( (option_type & ListOperatorFlag) != 0 )
-    CLIListOperatorImages(cli_wand, option, arg1, arg2);
+DisableMSCWarning(4127)
+  } while (0);  /* end Break code block */
+RestoreMSCWarning
 
+  cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */
 }