]> granicus.if.org Git - imagemagick/blobdiff - wand/compare.c
(no commit message)
[imagemagick] / wand / compare.c
index 52f79dce60e99d36e693f5dc1ad2b262801d1083..3034d0a1db7ab0f87875ecea5f8f1aa180bd42f4 100644 (file)
@@ -17,7 +17,7 @@
 %                               December 2003                                 %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2011 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  %
@@ -44,6 +44,7 @@
 #include "wand/studio.h"
 #include "wand/MagickWand.h"
 #include "wand/mogrify-private.h"
+#include "magick/string-private.h"
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -109,7 +110,7 @@ static MagickBooleanType CompareUsage(void)
       "-density geometry    horizontal and vertical density of the image",
       "-depth value         image depth",
       "-dissimilarity-threshold value",
-      "                     maximum RMSE for (sub)image match",
+      "                     maximum distortion for (sub)image match",
       "-encipher filename   convert plain pixels to cipher pixels",
       "-extract geometry    extract area from image",
       "-format \"string\"     output formatted image characteristics",
@@ -136,6 +137,7 @@ static MagickBooleanType CompareUsage(void)
       "-set attribute value set an image attribute",
       "-quality value       JPEG/MIFF/PNG compression level",
       "-size geometry       width and height of image",
+      "-subimage-search     search for subimage",
       "-transparent-color color",
       "                     transparent color",
       "-type type           image type",
@@ -146,9 +148,9 @@ static MagickBooleanType CompareUsage(void)
       (char *) NULL
     };
 
-  (void) printf("Version: %s\n",GetMagickVersion((unsigned long *) NULL));
-  (void) printf("Copyright: %s\n\n",GetMagickCopyright());
-  (void) printf("Features: %s\n",GetMagickFeatures());
+  (void) printf("Version: %s\n",GetMagickVersion((size_t *) NULL));
+  (void) printf("Copyright: %s\n",GetMagickCopyright());
+  (void) printf("Features: %s\n\n",GetMagickFeatures());
   (void) printf("Usage: %s [options ...] image reconstruct difference\n",
     GetClientName());
   (void) printf("\nImage Settings:\n");
@@ -172,7 +174,7 @@ static MagickBooleanType CompareUsage(void)
 WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
   int argc,char **argv,char **metadata,ExceptionInfo *exception)
 {
-#define DefaultDissimilarityThreshold  0.2
+#define DefaultDissimilarityThreshold  0.31830988618379067154
 #define DestroyCompare() \
 { \
   if (similarity_image != (Image *) NULL) \
@@ -180,7 +182,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
   if (difference_image != (Image *) NULL) \
     difference_image=DestroyImageList(difference_image); \
   DestroyImageStack(); \
-  for (i=0; i < (long) argc; i++) \
+  for (i=0; i < (ssize_t) argc; i++) \
     argv[i]=DestroyString(argv[i]); \
   argv=(char **) RelinquishMagickMemory(argv); \
 }
@@ -224,13 +226,10 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
   ImageStack
     image_stack[MaxImageStackDepth+1];
 
-  long
-    j,
-    k;
-
   MagickBooleanType
     fire,
-    pend;
+    pend,
+    subimage_search;
 
   MagickStatusType
     status;
@@ -241,9 +240,13 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
   RectangleInfo
     offset;
 
-  register long
+  register ssize_t
     i;
 
+  ssize_t
+    j,
+    k;
+
   /*
     Set defaults.
   */
@@ -259,16 +262,14 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
           (LocaleCompare("-version",option+1) == 0))
         {
           (void) fprintf(stdout,"Version: %s\n",
-            GetMagickVersion((unsigned long *) NULL));
-          (void) fprintf(stdout,"Copyright: %s\n\n",GetMagickCopyright());
+            GetMagickVersion((size_t *) NULL));
+          (void) fprintf(stdout,"Copyright: %s\n",GetMagickCopyright());
+          (void) fprintf(stdout,"Features: %s\n\n",GetMagickFeatures());
           return(MagickFalse);
         }
     }
   if (argc < 3)
-    {
-      (void) CompareUsage();
-      return(MagickTrue);
-    }
+    return(CompareUsage());
   channels=AllChannels;
   difference_image=NewImageList();
   similarity_image=NewImageList();
@@ -283,6 +284,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
   pend=MagickFalse;
   reconstruct_image=NewImageList();
   status=MagickTrue;
+  subimage_search=MagickFalse;
   /*
     Compare an image.
   */
@@ -291,7 +293,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
   if (status == MagickFalse)
     ThrowCompareException(ResourceLimitError,"MemoryAllocationFailed",
       GetExceptionMessage(errno));
-  for (i=1; i < (long) (argc-1); i++)
+  for (i=1; i < (ssize_t) (argc-1); i++)
   {
     option=argv[i];
     if (LocaleCompare(option,"(") == 0)
@@ -321,7 +323,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
         */
         FireImageStack(MagickFalse,MagickFalse,pend);
         filename=argv[i];
-        if ((LocaleCompare(filename,"--") == 0) && (i < (argc-1)))
+        if ((LocaleCompare(filename,"--") == 0) && (i < (ssize_t) (argc-1)))
           filename=argv[++i];
         (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
         images=ReadImages(image_info,exception);
@@ -339,13 +341,13 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
       {
         if (LocaleCompare("alpha",option+1) == 0)
           {
-            long
+            ssize_t
               type;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             type=ParseMagickOption(MagickAlphaOptions,MagickFalse,argv[i]);
             if (type < 0)
@@ -358,7 +360,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             break;
           }
@@ -371,7 +373,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (IsGeometry(argv[i]) == MagickFalse)
               ThrowCompareInvalidArgumentException(option,argv[i]);
@@ -379,13 +381,13 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
           }
         if (LocaleCompare("channel",option+1) == 0)
           {
-            long
+            ssize_t
               channel;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             channel=ParseChannelOption(argv[i]);
             if (channel < 0)
@@ -396,13 +398,13 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
           }
         if (LocaleCompare("colorspace",option+1) == 0)
           {
-            long
+            ssize_t
               colorspace;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             colorspace=ParseMagickOption(MagickColorspaceOptions,MagickFalse,
               argv[i]);
@@ -413,13 +415,13 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
           }
         if (LocaleCompare("compose",option+1) == 0)
           {
-            long
+            ssize_t
               compose;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             compose=ParseMagickOption(MagickComposeOptions,MagickFalse,
               argv[i]);
@@ -430,13 +432,13 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
           }
         if (LocaleCompare("compress",option+1) == 0)
           {
-            long
+            ssize_t
               compress;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             compress=ParseMagickOption(MagickCompressOptions,MagickFalse,
               argv[i]);
@@ -445,6 +447,8 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
                 argv[i]);
             break;
           }
+        if (LocaleCompare("concurrent",option+1) == 0)
+          break;
         ThrowCompareException(OptionError,"UnrecognizedOption",option)
       }
       case 'd':
@@ -457,7 +461,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             event_mask=SetLogEventMask(argv[i]);
             if (event_mask == UndefinedEvents)
@@ -470,14 +474,14 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             break;
           }
         if (LocaleCompare("define",option+1) == 0)
           {
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (*option == '+')
               {
@@ -496,7 +500,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (IsGeometry(argv[i]) == MagickFalse)
               ThrowCompareInvalidArgumentException(option,argv[i]);
@@ -507,7 +511,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (IsGeometry(argv[i]) == MagickFalse)
               ThrowCompareInvalidArgumentException(option,argv[i]);
@@ -518,14 +522,25 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (IsGeometry(argv[i]) == MagickFalse)
               ThrowCompareInvalidArgumentException(option,argv[i]);
             if (*option == '+')
               dissimilarity_threshold=DefaultDissimilarityThreshold;
             else
-              dissimilarity_threshold=atof(argv[i]);
+              dissimilarity_threshold=StringToDouble(argv[i]);
+            break;
+          }
+        if (LocaleCompare("duration",option+1) == 0)
+          {
+            if (*option == '+')
+              break;
+            i++;
+            if (i == (ssize_t) (argc-1))
+              ThrowCompareException(OptionError,"MissingArgument",option);
+            if (IsGeometry(argv[i]) == MagickFalse)
+              ThrowCompareInvalidArgumentException(option,argv[i]);
             break;
           }
         ThrowCompareException(OptionError,"UnrecognizedOption",option)
@@ -537,7 +552,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             break;
           }
@@ -546,7 +561,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (IsGeometry(argv[i]) == MagickFalse)
               ThrowCompareInvalidArgumentException(option,argv[i]);
@@ -561,7 +576,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             format=argv[i];
             break;
@@ -571,7 +586,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (IsGeometry(argv[i]) == MagickFalse)
               ThrowCompareInvalidArgumentException(option,argv[i]);
@@ -589,7 +604,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             break;
           }
@@ -601,13 +616,13 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
           break;
         if (LocaleCompare("interlace",option+1) == 0)
           {
-            long
+            ssize_t
               interlace;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             interlace=ParseMagickOption(MagickInterlaceOptions,MagickFalse,
               argv[i]);
@@ -628,13 +643,13 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             double
               value;
 
-            long
+            ssize_t
               resource;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             resource=ParseMagickOption(MagickResourceOptions,MagickFalse,
               argv[i]);
@@ -642,7 +657,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
               ThrowCompareException(OptionError,"UnrecognizedResourceType",
                 argv[i]);
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             value=strtod(argv[i],&p);
             if ((p == argv[i]) && (LocaleCompare("unlimited",argv[i]) != 0))
@@ -651,28 +666,28 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
           }
         if (LocaleCompare("list",option+1) == 0)
           {
-            long
+            ssize_t
               list;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             list=ParseMagickOption(MagickListOptions,MagickFalse,argv[i]);
             if (list < 0)
               ThrowCompareException(OptionError,"UnrecognizedListType",argv[i]);
-            (void) MogrifyImageInfo(image_info,(int) (i-j+1),(const char **)
+            status=MogrifyImageInfo(image_info,(int) (i-j+1),(const char **)
               argv+j,exception);
             DestroyCompare();
-            return(MagickTrue);
+            return(status != 0 ? MagickFalse : MagickTrue);
           }
         if (LocaleCompare("log",option+1) == 0)
           {
             if (*option == '+')
               break;
             i++;
-            if ((i == (long) argc) || (strchr(argv[i],'%') == (char *) NULL))
+            if ((i == (ssize_t) argc) || (strchr(argv[i],'%') == (char *) NULL))
               ThrowCompareException(OptionError,"MissingArgument",option);
             break;
           }
@@ -681,7 +696,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             break;
           }
@@ -693,13 +708,13 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
           break;
         if (LocaleCompare("metric",option+1) == 0)
           {
-            long
+            ssize_t
               type;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             type=ParseMagickOption(MagickMetricOptions,MagickTrue,argv[i]);
             if (type < 0)
@@ -719,14 +734,14 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             break;
           }
         if (LocaleCompare("profile",option+1) == 0)
           {
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             break;
           }
@@ -739,7 +754,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (IsGeometry(argv[i]) == MagickFalse)
               ThrowCompareInvalidArgumentException(option,argv[i]);
@@ -747,13 +762,13 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
           }
         if (LocaleCompare("quantize",option+1) == 0)
           {
-            long
+            ssize_t
               colorspace;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             colorspace=ParseMagickOption(MagickColorspaceOptions,
               MagickFalse,argv[i]);
@@ -784,7 +799,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (IsGeometry(argv[i]) == MagickFalse)
               ThrowCompareInvalidArgumentException(option,argv[i]);
@@ -795,7 +810,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (IsGeometry(argv[i]) == MagickFalse)
               ThrowCompareInvalidArgumentException(option,argv[i]);
@@ -804,12 +819,12 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
         if (LocaleCompare("set",option+1) == 0)
           {
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             break;
           }
@@ -818,34 +833,48 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             if (IsGeometry(argv[i]) == MagickFalse)
               ThrowCompareInvalidArgumentException(option,argv[i]);
             break;
           }
+        if (LocaleCompare("subimage-search",option+1) == 0)
+          {
+            if (*option == '+')
+              {
+                subimage_search=MagickFalse;
+                break;
+              }
+            subimage_search=MagickTrue;
+            break;
+          }
+        if (LocaleCompare("synchronize",option+1) == 0)
+          break;
         ThrowCompareException(OptionError,"UnrecognizedOption",option)
       }
       case 't':
       {
+        if (LocaleCompare("taint",option+1) == 0)
+          break;
         if (LocaleCompare("transparent-color",option+1) == 0)
           {
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             break;
           }
         if (LocaleCompare("type",option+1) == 0)
           {
-            long
+            ssize_t
               type;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) argc)
+            if (i == (ssize_t) argc)
               ThrowCompareException(OptionError,"MissingArgument",option);
             type=ParseMagickOption(MagickTypeOptions,MagickFalse,argv[i]);
             if (type < 0)
@@ -863,19 +892,20 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             (LocaleCompare("-version",option+1) == 0))
           {
             (void) fprintf(stdout,"Version: %s\n",
-              GetMagickVersion((unsigned long *) NULL));
-            (void) fprintf(stdout,"Copyright: %s\n\n",GetMagickCopyright());
+              GetMagickVersion((size_t *) NULL));
+            (void) fprintf(stdout,"Copyright: %s\n",GetMagickCopyright());
+            (void) fprintf(stdout,"Features: %s\n\n",GetMagickFeatures());
             break;
           }
         if (LocaleCompare("virtual-pixel",option+1) == 0)
           {
-            long
+            ssize_t
               method;
 
             if (*option == '+')
               break;
             i++;
-            if (i == (long) (argc-1))
+            if (i == (ssize_t) (argc-1))
               ThrowCompareException(OptionError,"MissingArgument",option);
             method=ParseMagickOption(MagickVirtualPixelOptions,MagickFalse,
               argv[i]);
@@ -898,7 +928,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
   }
   if (k != 0)
     ThrowCompareException(OptionError,"UnbalancedParenthesis",argv[i]);
-  if (i-- != (long) (argc-1))
+  if (i-- != (ssize_t) (argc-1))
     ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]);
   if ((image == (Image *) NULL) || (GetImageListLength(image) < 2))
     ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]);
@@ -907,16 +937,22 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
     ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]);
   image=GetImageFromList(image,0);
   reconstruct_image=GetImageFromList(image,1);
-  similarity_image=SimilarityImage(image,reconstruct_image,&offset,
-    &similarity_metric,exception);
-  if (similarity_metric > dissimilarity_threshold)
-    ThrowCompareException(ImageError,"ImagesTooDissimilar",image->filename);
+  if (subimage_search != MagickFalse)
+    {
+      similarity_image=SimilarityImage(image,reconstruct_image,&offset,
+        &similarity_metric,exception);
+      if (similarity_metric > dissimilarity_threshold)
+        ThrowCompareException(ImageError,"ImagesTooDissimilar",image->filename);
+    }
   if ((reconstruct_image->columns == image->columns) &&
       (reconstruct_image->rows == image->rows))
     difference_image=CompareImageChannels(image,reconstruct_image,channels,
       metric,&distortion,exception);
   else
-    if (similarity_image != (Image *) NULL)
+    if (similarity_image == (Image *) NULL)
+      ThrowCompareException(OptionError,"ImageWidthsOrHeightsDiffer",
+        image->filename)
+    else
       {
         Image
           *composite_image;
@@ -941,9 +977,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
               }
             composite_image=DestroyImage(composite_image);
           }
-        if (difference_image == (Image *) NULL)
-          similarity_image=DestroyImage(similarity_image);
-        else
+        if (difference_image != (Image *) NULL)
           {
             AppendImageToList(&difference_image,similarity_image);
             similarity_image=(Image *) NULL;
@@ -967,23 +1001,24 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
             case RootMeanSquaredErrorMetric:
             case PeakAbsoluteErrorMetric:
             {
-              (void) fprintf(stderr,"%g (%g)",QuantumRange*distortion,(double)
-                distortion);
+              (void) fprintf(stderr,"%g (%g)",QuantumRange*distortion,
+                (double) distortion);
               if ((reconstruct_image->columns != image->columns) ||
                   (reconstruct_image->rows != image->rows))
-                (void) fprintf(stderr," @ %ld,%ld",difference_image->page.x,
-                  difference_image->page.y);
+                (void) fprintf(stderr," @ %.20g,%.20g",(double)
+                  difference_image->page.x,(double) difference_image->page.y);
               (void) fprintf(stderr,"\n");
               break;
             }
             case AbsoluteErrorMetric:
+            case NormalizedCrossCorrelationErrorMetric:
             case PeakSignalToNoiseRatioMetric:
             {
               (void) fprintf(stderr,"%g",distortion);
               if ((reconstruct_image->columns != image->columns) ||
                   (reconstruct_image->rows != image->rows))
-                (void) fprintf(stderr," @ %ld,%ld",difference_image->page.x,
-                  difference_image->page.y);
+                (void) fprintf(stderr," @ %.20g,%.20g",(double)
+                  difference_image->page.x,(double) difference_image->page.y);
               (void) fprintf(stderr,"\n");
               break;
             }
@@ -994,8 +1029,8 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
                 image->error.normalized_maximum_error);
               if ((reconstruct_image->columns != image->columns) ||
                   (reconstruct_image->rows != image->rows))
-                (void) fprintf(stderr," @ %ld,%ld",difference_image->page.x,
-                  difference_image->page.y);
+                (void) fprintf(stderr," @ %.20g,%.20g",(double)
+                  difference_image->page.x,(double) difference_image->page.y);
               (void) fprintf(stderr,"\n");
               break;
             }
@@ -1013,10 +1048,10 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
           (void) fprintf(stderr,"Image: %s\n",image->filename);
           if ((reconstruct_image->columns != image->columns) ||
               (reconstruct_image->rows != image->rows))
-            (void) fprintf(stderr,"Offset: %ld,%ld\n",difference_image->page.x,
-              difference_image->page.y);
+            (void) fprintf(stderr,"Offset: %.20g,%.20g\n",(double)
+              difference_image->page.x,(double) difference_image->page.y);
           (void) fprintf(stderr,"  Channel distortion: %s\n",
-            MagickOptionToMnemonic(MagickMetricOptions,(long) metric));
+            MagickOptionToMnemonic(MagickMetricOptions,(ssize_t) metric));
           switch (metric)
           {
             case MeanAbsoluteErrorMetric:
@@ -1082,6 +1117,7 @@ WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
               break;
             }
             case AbsoluteErrorMetric:
+            case NormalizedCrossCorrelationErrorMetric:
             case PeakSignalToNoiseRatioMetric:
             {
               switch (image->colorspace)