]> granicus.if.org Git - imagemagick/blobdiff - MagickWand/operation.c
(no commit message)
[imagemagick] / MagickWand / operation.c
index d5553bcd06148be189a73d7cd09618acfc9fbc86..a88f83f49f7bd9485e6621755506ceef617f5f6b 100644 (file)
@@ -17,7 +17,7 @@
 %                               September 2011                                %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2013 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.
 */
 /* 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", \
@@ -149,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)
@@ -162,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];
@@ -400,18 +402,17 @@ static Image *SparseColorOption(const Image *image,
 %
 */
 WandPrivate void CLISettingOptionInfo(MagickCLI *cli_wand,
-     const char *option,const char *arg1, const char *arg2)
+     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)
@@ -421,15 +422,21 @@ WandPrivate void CLISettingOptionInfo(MagickCLI *cli_wand,
 #define ArgBooleanString  (IfSetOption?"true":"false")
 #define ArgOption(def)    (IfSetOption?arg1:(const char *)(def))
 
-#if 0
-Setting are not directly involved with images, so can not
-interpret Percent Escapes in Arguments, At least not yet */
+  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 */
-  arg1 = arg1n,
-  arg2 = arg2n;
   if ( (((_process_flags & ProcessInterpretProperities) != 0 )
         || ((_option_type & AlwaysInterpretArgsFlag) != 0)
        )  && ((_option_type & NeverInterpretArgsFlag) == 0) ) {
@@ -509,7 +516,7 @@ interpret Percent Escapes in Arguments, At least not yet */
              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;
         }
@@ -562,9 +569,9 @@ interpret Percent Escapes in Arguments, At least not yet */
               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;
         }
@@ -599,8 +606,7 @@ interpret Percent Escapes in Arguments, At least not yet */
         }
       if (LocaleCompare("channel",option+1) == 0)
         {
-          arg1=ArgOption("default");
-          parse=ParseChannelOption(arg1);
+          parse=ParseChannelOption(ArgOption("Default"));
           if (parse < 0)
             CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
                  option,arg1);
@@ -826,6 +832,14 @@ interpret Percent Escapes in Arguments, At least not yet */
           (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
@@ -896,7 +910,7 @@ interpret Percent Escapes in Arguments, At least not yet */
              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)))
@@ -952,9 +966,11 @@ interpret Percent Escapes in Arguments, At least not yet */
       if (LocaleCompare("intensity",option+1) == 0)
         {
           arg1 = ArgOption("undefined");
-          parse = ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,arg1);
+          parse = ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,
+            arg1);
           if (parse < 0)
-            CLIWandExceptArgBreak(OptionError,"UnrecognizedIntentType",option,arg1);
+            CLIWandExceptArgBreak(OptionError,"UnrecognizedIntensityType",
+              option,arg1);
           (void) SetImageOption(_image_info,option+1,arg1);
           break;
         }
@@ -1084,7 +1100,7 @@ interpret Percent Escapes in Arguments, At least not yet */
         {
           /* 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;
         }
@@ -1099,6 +1115,14 @@ interpret Percent Escapes in Arguments, At least not yet */
           (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?
@@ -1580,13 +1604,11 @@ interpret Percent Escapes in Arguments, At least not yet */
       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
   }
 
-#if 0
   /* clean up percent escape interpreted strings */
   if (arg1 != arg1n )
     arg1=DestroyString((char *)arg1);
   if (arg2 != arg2n )
     arg2=DestroyString((char *)arg2);
-#endif
 
 #undef _image_info
 #undef _exception
@@ -1668,21 +1690,21 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
   ssize_t
     parse;
 
-  const char    /* For percent escape interpretImageProperties() */
+  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 normal_op       IsMagickTrue(IfNormalOp)
-#define plus_alt_op     IsMagickFalse(IfNormalOp)
+#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);
@@ -1691,9 +1713,10 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
   if (IfMagickTrue(cli_wand->wand.debug))
     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
 
-  /* Interpret Percent Escapes in Arguments - using first image */
   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) ) {
@@ -1891,6 +1914,26 @@ static MagickBooleanType 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 */
@@ -1900,7 +1943,7 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
           /*
             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,
@@ -1982,9 +2025,7 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
             {
               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)))
@@ -1993,13 +2034,14 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
           /* clean up and set the write mask */
           mask_view=DestroyCacheView(mask_view);
           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;
         }
@@ -2050,14 +2092,14 @@ static MagickBooleanType 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)
@@ -2124,7 +2166,7 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
           StringInfo
             *passkey;
 
-          passkey=FileToStringInfo(arg1,~0,_exception);
+          passkey=FileToStringInfo(arg1,~0UL,_exception);
           if (passkey == (StringInfo *) NULL)
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
 
@@ -2201,7 +2243,7 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
             CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2);
 
           new_image=DistortImage(_image,(DistortImageMethod) parse,count,args,
-               plus_alt_op,_exception);
+               IsPlusOp,_exception);
           args=(double *) RelinquishMagickMemory(args);
           break;
         }
@@ -2221,10 +2263,7 @@ static MagickBooleanType 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)
@@ -2244,7 +2283,7 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
           StringInfo
             *passkey;
 
-          passkey=FileToStringInfo(arg1,~0,_exception);
+          passkey=FileToStringInfo(arg1,~0UL,_exception);
           if (passkey != (StringInfo *) NULL)
             {
               (void) PasskeyEncipherImage(_image,passkey,_exception);
@@ -2294,17 +2333,6 @@ static MagickBooleanType 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);
@@ -2325,7 +2353,7 @@ static MagickBooleanType 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)
@@ -2448,6 +2476,33 @@ static MagickBooleanType 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':
@@ -2459,16 +2514,17 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
             *text;
 
           format=GetImageOption(_image_info,"format");
-          if (format == (char *) NULL) {
-            (void) IdentifyImage(_image,stdout,_image_info->verbose,_exception);
-            break;
-          }
+          if (format == (char *) NULL)
+            {
+              (void) IdentifyImage(_image,stdout,_image_info->verbose,
+                _exception);
+              break;
+            }
           text=InterpretImageProperties(_image_info,_image,format,_exception);
           if (text == (char *) NULL)
             CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
-                 option);
+              option);
           (void) fputs(text,stdout);
-          (void) fputc('\n',stdout);
           text=DestroyString((char *)text);
           break;
         }
@@ -2579,7 +2635,7 @@ static MagickBooleanType 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)
@@ -2627,6 +2683,11 @@ static MagickBooleanType 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");
@@ -2656,7 +2717,22 @@ static MagickBooleanType 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)
@@ -2742,7 +2818,7 @@ static MagickBooleanType 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)
@@ -2786,7 +2862,7 @@ static MagickBooleanType 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;
         }
@@ -2927,12 +3003,12 @@ static MagickBooleanType 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)
@@ -2940,7 +3016,7 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
           if (IfMagickFalse(IsGeometry(arg1)))
             CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
           flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
-          (void) RaiseImage(_image,&geometry,normal_op,_exception);
+          (void) RaiseImage(_image,&geometry,IsNormalOp,_exception);
           break;
         }
       if (LocaleCompare("random-threshold",option+1) == 0)
@@ -3091,7 +3167,7 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
           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;
         }
@@ -3153,7 +3229,7 @@ static MagickBooleanType 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;
         }
@@ -3243,7 +3319,7 @@ static MagickBooleanType 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);
@@ -3280,7 +3356,7 @@ static MagickBooleanType 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)
@@ -3314,7 +3390,7 @@ static MagickBooleanType 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;
             }
@@ -3339,7 +3415,7 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
           if ((flags & PsiValue) == 0)
             geometry_info.psi=0.05;
           new_image=UnsharpMaskImage(_image,geometry_info.rho,
-            geometry_info.sigma,geometry_info.xi,_exception);
+            geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
           break;
         }
       CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
@@ -3367,6 +3443,11 @@ static MagickBooleanType 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);
@@ -3418,8 +3499,8 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
 #undef _exception
 #undef IfNormalOp
 #undef IfPlusOp
-#undef normal_op
-#undef plus_alt_op
+#undef IsNormalOp
+#undef IsPlusOp
 }
 
 WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
@@ -3435,8 +3516,10 @@ WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
   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 */
@@ -3495,7 +3578,7 @@ WandPrivate MagickBooleanType CLISimpleOperatorImages(MagickCLI *cli_wand,
 WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
   const char *option,const char *arg1n,const char *arg2n)
 {
-  const char    /* For percent escape interpretImageProperties() */
+  const char    /* percent escaped versions of the args */
     *arg1,
     *arg2;
 
@@ -3517,18 +3600,21 @@ WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
 #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);
 
-  /* Interpret Percent Escapes in Arguments - using first image */
   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) ) {
@@ -3551,11 +3637,6 @@ WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
 #undef _process_flags
 #undef _option_type
 
-#if 0
-  (void) FormatLocaleFile(stderr,
-    "CLIListOperatorImages: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2);
-#endif
-
   status=MagickTrue;
   new_images=NewImageList();
 
@@ -3565,7 +3646,7 @@ WandPrivate MagickBooleanType 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)
@@ -3608,14 +3689,58 @@ WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
         }
       if (LocaleCompare("combine",option+1) == 0)
         {
-          /* FUTURE - this may be replaced by a 'channel' method */
-          parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
+          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)
         {
           CompositeOperator
@@ -3756,12 +3881,12 @@ WandPrivate MagickBooleanType 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);
@@ -3770,7 +3895,7 @@ WandPrivate MagickBooleanType 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)
@@ -3820,7 +3945,7 @@ WandPrivate MagickBooleanType 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;
@@ -4012,6 +4137,8 @@ WandPrivate MagickBooleanType 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
@@ -4053,11 +4180,6 @@ WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
           args=(double *) RelinquishMagickMemory(args);
           break;
         }
-      if (LocaleCompare("print",option+1) == 0)
-        {
-          (void) FormatLocaleFile(stdout,"%s",arg1);
-          break;
-        }
       if (LocaleCompare("process",option+1) == 0)
         {
           /* FUTURE: better parsing using ScriptToken() from string ??? */
@@ -4094,6 +4216,7 @@ WandPrivate MagickBooleanType 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))
@@ -4154,7 +4277,7 @@ WandPrivate MagickBooleanType 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)
@@ -4179,7 +4302,7 @@ WandPrivate MagickBooleanType 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,
@@ -4268,10 +4391,10 @@ WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
 
   /* if new image list generated, replace existing image list */
   if (new_images == (Image *) NULL)
-    return(status);
+    return(status == 0 ? MagickFalse : MagickTrue);
   _images=DestroyImageList(_images);
   _images=GetFirstImageInList(new_images);
-  return(status);
+  return(status == 0 ? MagickFalse : MagickTrue);
 
 #undef _image_info
 #undef _images
@@ -4280,7 +4403,7 @@ WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
 #undef _quantize_info
 #undef IfNormalOp
 #undef IfPlusOp
-#undef normal_op
+#undef IsNormalOp
 }
 \f
 /*
@@ -4320,36 +4443,32 @@ WandPrivate MagickBooleanType CLIListOperatorImages(MagickCLI *cli_wand,
 %
 */
 WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
-  const char *option,const char *arg1,const char *arg2)
+  const char *option,const char *arg1n,const char *arg2n)
 {
-#if 0
-  const char    /* For percent escape interpretImageProperties() */
+  const char    /* percent escaped versions of the args */
     *arg1,
     *arg2;
-#endif
 
 #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);
 
-#if 0
-  Not able to be used as their may not be any images!
-  Also the only option that may have arguments that can be percent escaped is
-  "-clone".
+  if (IfMagickTrue(cli_wand->wand.debug))
+    (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+         "- NoImage Operator: %s \"%s\" \"%s\"", option,arg1n,arg2n);
 
-#define _process_flags  (cli_wand->process_flags)
-#define _option_type    ((CommandOptionFlags) cli_wand->command->flags)
-  /* Interpret Percent Escapes in Arguments - using first image */
   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) ) {
@@ -4371,7 +4490,6 @@ WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
   }
 #undef _process_flags
 #undef _option_type
-#endif
 
   do {  /* break to exit code */
     /*
@@ -4453,7 +4571,7 @@ WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
         *write_info;
 
       /* Need images, unless a "null:" output coder is used */
-      if ( cli_wand->wand.images == (Image *) NULL ) {
+      if ( _images == (Image *) NULL ) {
         if ( LocaleCompare(arg1,"null:") == 0 )
           break;
         CLIWandExceptArgBreak(OptionError,"NoImagesForWrite",option,arg1);
@@ -4493,9 +4611,9 @@ WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
         CLIWandExceptionBreak(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;
+      cli_wand->wand.images = NewImageList();
 
       /* handle respect-parenthesis */
       if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
@@ -4503,7 +4621,7 @@ WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
         option="{"; /* fall-thru so as to push image settings too */
       else
         break;
-      /* fall thru to next if */
+      /* fall thru to operation */
     }
     if (LocaleCompare("{",option) == 0) {
       /* stack 'push' of image_info settings */
@@ -4525,6 +4643,9 @@ WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
             "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",
@@ -4534,9 +4655,6 @@ WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
         break;
       }
 
-      node->next = cli_wand->image_info_stack;
-      cli_wand->image_info_stack = node;
-
       break;
     }
     if (LocaleCompare(")",option) == 0) {
@@ -4587,86 +4705,94 @@ WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
 
       break;
     }
+      if (LocaleCompare("print",option+1) == 0)
+        {
+          (void) FormatLocaleFile(stdout,"%s",arg1);
+          break;
+        }
     if (LocaleCompare("set",option+1) == 0)
       {
-        /* Note: arguments are not percent escapes expanded yet */
-        /* Some settings are applied to each image in memory in turn.
-           While others only need to be applied once globally.
+        /* Settings are applied to each image in memory in turn (if any).
+           While a option: only need to be applied once globally.
+
+           NOTE: rguments have not been automatically percent expaneded
         */
-        char
-          *value;
+
+        /* escape the 'key' once only, using first image. */
+        arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception);
+        if (arg1 == (char *) NULL)
+          CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
+                option);
 
         if (LocaleNCompare(arg1,"registry:",9) == 0)
           {
             if (IfPlusOp)
               {
                 (void) DeleteImageRegistry(arg1+9);
+                arg1=DestroyString((char *)arg1);
                 break;
               }
-            value=InterpretImageProperties(_image_info,_images,arg2,_exception);
-            if (value == (char *) NULL)
+            arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception);
+            if (arg2 == (char *) NULL) {
+              arg1=DestroyString((char *)arg1);
               CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
                     option);
-            (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
-            value=DestroyString(value);
+            }
+            (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) */
-            MagickResetIterator(&cli_wand->wand);
-            while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
-              (void) DeleteImageArtifact(_images,arg1+7);
-            MagickResetIterator(&cli_wand->wand);
+            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 */
-            if (IfPlusOp) {
-              (void) DeleteImageOption(_image_info,arg1+7);
-              break;
-            }
-            value=InterpretImageProperties(_image_info,_images,arg2,_exception);
-            if (value == (char *) NULL)
-              CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
-                option);
-            (void) SetImageOption(_image_info,arg1+7,value);
-            value=DestroyString(value);
+            /* 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;
           }
-        if ( cli_wand->wand.images == (Image *) NULL )
-          CLIWandExceptArgBreak(OptionError,"NoImagesFound",option,arg1);
+        /* Set Artifacts/Properties/Attributes all images (required) */
+        if ( _images == (Image *) NULL )
+          CLIWandExceptArgBreak(OptionWarning,"NoImageForProperty",option,arg1);
+
         MagickResetIterator(&cli_wand->wand);
         while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
           {
-            Image
-              *next;
-
-            if (IfPlusOp) {
-              if (LocaleNCompare(arg1,"artifact:",9) == 0)
-                (void) DeleteImageArtifact(_images,arg1+9);
-              else if (LocaleNCompare(arg1,"property:",9) == 0)
-                (void) DeleteImageProperty(_images,arg1+9);
-              else
-                (void) DeleteImageProperty(_images,arg1);
-              break;
-            }
-            next=_images;
-            for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
-            {
-              value=InterpretImageProperties(_image_info,next,arg2,_exception);
-              if (value == (char *) NULL)
-                CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure",
-                  option);
-              if (LocaleNCompare(arg1,"artifact:",9) == 0)
-                (void) SetImageArtifact(next,arg1+9,value);
-              else
-                if (LocaleNCompare(arg1,"property:",9) == 0)
-                  (void) SetImageProperty(next,arg1+9,value,_exception);
-                else
-                  (void) SetImageProperty(next,arg1,value,_exception);
-              value=DestroyString(value);
-            }
-            break;
+            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;
      }
     if (LocaleCompare("clone",option+1) == 0) {
@@ -4775,15 +4901,15 @@ WandPrivate void CLINoImageOperator(MagickCLI *cli_wand,
 
     CLIWandException(OptionError,"UnrecognizedOption",option);
 
+DisableMSCWarning(4127)
   } while (0);  /* break to exit code. */
+RestoreMSCWarning
 
-#if 0
   /* clean up percent escape interpreted strings */
   if (arg1 != arg1n )
     arg1=DestroyString((char *)arg1);
   if (arg2 != arg2n )
     arg2=DestroyString((char *)arg2);
-#endif
 
 #undef _image_info
 #undef _images
@@ -4839,7 +4965,7 @@ WandPrivate 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;
 
@@ -4849,8 +4975,6 @@ 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);
 
   do { /* Break Code Block for error handling */
 
@@ -4877,7 +5001,9 @@ WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
       CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option);
 
     /* Get argument strings from VarArgs
-      How can you determine arguments is enough was supplied? */
+      How can you determine if enough arguments was supplied?
+      What happens if not enough arguments were supplied?
+    */
     { size_t
         count = cli_wand->command->type;
 
@@ -4893,7 +5019,6 @@ WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
         arg2=(const char *) va_arg(operands, const char *);
 
       va_end(operands);
-
 #if 0
       (void) FormatLocaleFile(stderr,
         "CLIOption: \"%s\"  Count: %ld  Flags: %04x  Args: \"%s\" \"%s\"\n",
@@ -4928,15 +5053,18 @@ WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...)
           ((option_type & SettingOptionFlags) == 0 ))  /* temp hack */
         CLIWandExceptionBreak(OptionError,"NoImagesFound",option);
 
-    /* Operators work on single images, and needs a loop over the images */
-    if ( (option_type & SimpleOperatorFlag) != 0)
+    /* 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);
 
     /* Operators that work on the image list as a whole */
     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 */
 }