44#include "MagickWand/studio.h" 
   45#include "MagickWand/MagickWand.h" 
   46#include "MagickWand/mogrify-private.h" 
   47#include "MagickCore/compare-private.h" 
   48#include "MagickCore/image-private.h" 
   49#include "MagickCore/string-private.h" 
   85static MagickBooleanType CompareUsage(
void)
 
   89      "  -separate            separate an image channel into a grayscale image",
 
   91      "  -channel mask        set the image channel mask\n" 
   92      "  -debug events        display copious debugging information\n" 
   93      "  -help                print program options\n" 
   94      "  -list type           print a list of supported option arguments\n" 
   95      "  -log format          format of debugging information",
 
   97      "  -auto-orient         automagically orient (rotate) image\n" 
   98      "  -brightness-contrast geometry\n" 
   99      "                       improve brightness / contrast of the image\n" 
  100      "  -distort method args\n" 
  101      "                       distort images according to given method and args\n" 
  102      "  -level value         adjust the level of image contrast\n" 
  103      "  -resize geometry     resize the image\n" 
  104      "  -rotate degrees      apply Paeth rotation to the image\n" 
  105      "  -sigmoidal-contrast geometry\n" 
  106      "                       increase the contrast without saturating highlights or\n" 
  107      "  -trim                trim image edges\n" 
  108      "  -write filename      write images to this file",
 
  109    sequence_operators[] =
 
  110      "  -crop geometry       cut out a rectangular region of the image",
 
  112      "  -adjoin              join images into a single multi-image file\n" 
  113      "  -alpha option        on, activate, off, deactivate, set, opaque, copy\n" 
  114      "                       transparent, extract, background, or shape\n" 
  115      "  -authenticate password\n" 
  116      "                       decipher image with this password\n" 
  117      "  -background color    background color\n" 
  118      "  -colorspace type     alternate image colorspace\n" 
  119      "  -compose operator    set image composite operator\n" 
  120      "  -compress type       type of pixel compression when writing the image\n" 
  121      "  -decipher filename   convert cipher pixels to plain pixels\n" 
  122      "  -define format:option\n" 
  123      "                       define one or more image format options\n" 
  124      "  -density geometry    horizontal and vertical density of the image\n" 
  125      "  -depth value         image depth\n" 
  126      "  -dissimilarity-threshold value\n" 
  127      "                       maximum distortion for (sub)image match\n" 
  128      "  -encipher filename   convert plain pixels to cipher pixels\n" 
  129      "  -extract geometry    extract area from image\n" 
  130      "  -format \"string\"     output formatted image characteristics\n" 
  131      "  -fuzz distance       colors within this distance are considered equal\n" 
  132      "  -gravity type        horizontal and vertical text placement\n" 
  133      "  -highlight-color color\n" 
  134      "                       emphasize pixel differences with this color\n" 
  135      "  -identify            identify the format and characteristics of the image\n" 
  136      "  -interlace type      type of image interlacing scheme\n" 
  137      "  -limit type value    pixel cache resource limit\n" 
  138      "  -lowlight-color color\n" 
  139      "                       de-emphasize pixel differences with this color\n" 
  140      "  -metric type         measure differences between images with this metric\n" 
  141      "  -monitor             monitor progress\n" 
  142      "  -negate              replace every pixel with its complementary color \n" 
  143      "  -passphrase filename get the passphrase from this file\n" 
  144      "  -precision value     maximum number of significant digits to print\n" 
  145      "  -profile filename    add, delete, or apply an image profile\n" 
  146      "  -quality value       JPEG/MIFF/PNG compression level\n" 
  147      "  -quiet               suppress all warning messages\n" 
  148      "  -quantize colorspace reduce colors in this colorspace\n" 
  149      "  -read-mask filename  associate a read mask with the image\n" 
  150      "  -regard-warnings     pay attention to warning messages\n" 
  151      "  -respect-parentheses settings remain in effect until parenthesis boundary\n" 
  152      "  -sampling-factor geometry\n" 
  153      "                       horizontal and vertical sampling factor\n" 
  154      "  -seed value          seed a new sequence of pseudo-random numbers\n" 
  155      "  -set attribute value set an image attribute\n" 
  156      "  -quality value       JPEG/MIFF/PNG compression level\n" 
  157      "  -repage geometry     size and location of an image canvas\n" 
  158      "  -similarity-threshold value\n" 
  159      "                       minimum distortion for (sub)image match\n" 
  160      "  -size geometry       width and height of image\n" 
  161      "  -subimage-search     search for subimage\n" 
  162      "  -synchronize         synchronize image to storage device\n" 
  163      "  -taint               declare the image as modified\n" 
  164      "  -transparent-color color\n" 
  165      "                       transparent color\n" 
  166      "  -type type           image type\n" 
  167      "  -verbose             print detailed information about the image\n" 
  168      "  -version             print version information\n" 
  169      "  -virtual-pixel method\n" 
  170      "                       virtual pixel access method\n" 
  171      "  -write-mask filename  associate a write mask with the image",
 
  173      "  -delete indexes      delete the image from the image sequence";
 
  175  ListMagickVersion(stdout);
 
  176  (void) printf(
"Usage: %s [options ...] image reconstruct difference\n",
 
  178  (void) printf(
"\nImage Settings:\n");
 
  179  (void) puts(settings);
 
  180  (void) printf(
"\nImage Operators:\n");
 
  181  (void) puts(operators);
 
  182  (void) printf(
"\nImage Channel Operators:\n");
 
  183  (void) puts(channel_operators);
 
  184  (void) printf(
"\nImage Sequence Operators:\n");
 
  185  (void) puts(sequence_operators);
 
  186  (void) printf(
"\nImage Stack Operators:\n");
 
  187  (void) puts(stack_operators);
 
  188  (void) printf(
"\nMiscellaneous Options:\n");
 
  189  (void) puts(miscellaneous);
 
  191    "\nBy default, the image format of 'file' is determined by its magic\n");
 
  193    "number.  To specify a particular image format, precede the filename\n");
 
  195    "with an image format name and a colon (i.e. ps:image) or specify the\n");
 
  197    "image type as the filename suffix (i.e. image.ps).  Specify 'file' as\n");
 
  198  (void) printf(
"'-' for standard input or output.\n");
 
  202WandExport MagickBooleanType CompareImagesCommand(ImageInfo *image_info,
 
  203  int argc,
char **argv,
char **metadata,ExceptionInfo *exception)
 
  205#define CompareEpsilon  (1.0e-06) 
  206#define CompareConstantColorException \ 
  207  "search metric is unreliable for constant-color images" 
  208#define CompareEqualSizedException \ 
  209  "subimage search metric is unreliable for equal-sized images" 
  210#define DefaultDissimilarityThreshold  (1.0/MagickPI) 
  211#define DestroyCompare() \ 
  213  if (similarity_image != (Image *) NULL) \ 
  214    similarity_image=DestroyImageList(similarity_image); \ 
  215  if (difference_image != (Image *) NULL) \ 
  216    difference_image=DestroyImageList(difference_image); \ 
  217  DestroyImageStack(); \ 
  218  for (i=0; i < (ssize_t) argc; i++) \ 
  219    argv[i]=DestroyString(argv[i]); \ 
  220  argv=(char **) RelinquishMagickMemory(argv); \ 
  222#define ThrowCompareException(asperity,tag,option) \ 
  224  if (exception->severity < (asperity)) \ 
  225    (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag, \ 
  228  return(MagickFalse); \ 
  230#define ThrowCompareInvalidArgumentException(option,argument) \ 
  232  (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \ 
  233    "InvalidArgument","'%s': %s",option,argument); \ 
  235  return(MagickFalse); \ 
  246    dissimilarity_threshold = DefaultDissimilarityThreshold,
 
  248    scale = (double) QuantumRange,
 
  249    similarity_metric = 0.0,
 
  250    similarity_threshold = DefaultSimilarityThreshold;
 
  254    *image = (Image *) NULL,
 
  259    image_stack[MaxImageStackDepth+1];
 
  265    similar = MagickTrue,
 
  272    metric = UndefinedErrorMetric;
 
  287  assert(image_info != (ImageInfo *) NULL);
 
  288  assert(image_info->signature == MagickCoreSignature);
 
  289  assert(exception != (ExceptionInfo *) NULL);
 
  290  if (IsEventLogging() != MagickFalse)
 
  291    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
 
  295      if ((LocaleCompare(
"version",option+1) == 0) ||
 
  296          (LocaleCompare(
"-version",option+1) == 0))
 
  298          ListMagickVersion(stdout);
 
  304      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
 
  305        "MissingArgument",
"%s",
"");
 
  306      (void) CompareUsage();
 
  309  difference_image=NewImageList();
 
  310  similarity_image=NewImageList();
 
  311  format=(
char *) NULL;
 
  315  option=(
char *) NULL;
 
  317  reconstruct_image=NewImageList();
 
  318  respect_parentheses=MagickFalse;
 
  320  subimage_search=MagickFalse;
 
  324  ReadCommandlLine(argc,&argv);
 
  325  status=ExpandFilenames(&argc,&argv);
 
  326  if (status == MagickFalse)
 
  327    ThrowCompareException(ResourceLimitError,
"MemoryAllocationFailed",
 
  328      GetExceptionMessage(errno));
 
  329  for (i=1; i < (ssize_t) (argc-1); i++)
 
  332    if (LocaleCompare(option,
"(") == 0)
 
  334        FireImageStack(MagickTrue,MagickTrue,pend);
 
  335        if (k == MaxImageStackDepth)
 
  336          ThrowCompareException(OptionError,
"ParenthesisNestedTooDeeply",
 
  341    if (LocaleCompare(option,
")") == 0)
 
  343        FireImageStack(MagickTrue,MagickTrue,MagickTrue);
 
  345          ThrowCompareException(OptionError,
"UnableToParseExpression",option);
 
  349    if (IsCommandOption(option) == MagickFalse)
 
  357        FireImageStack(MagickFalse,MagickFalse,pend);
 
  359        if ((LocaleCompare(filename,
"--") == 0) && (i < (ssize_t) (argc-1)))
 
  361        images=ReadImages(image_info,filename,exception);
 
  362        status&=(MagickStatusType) ((images != (Image *) NULL) &&
 
  363          (exception->severity < ErrorException));
 
  364        if (images == (Image *) NULL)
 
  366        AppendImageStack(images);
 
  369    pend=image != (Image *) NULL ? MagickTrue : MagickFalse;
 
  374        if (LocaleCompare(
"adjoin",option+1) == 0)
 
  376        if (LocaleCompare(
"alpha",option+1) == 0)
 
  384            if (i == (ssize_t) argc)
 
  385              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  386            type=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,
 
  389              ThrowCompareException(OptionError,
 
  390                "UnrecognizedAlphaChannelOption",argv[i]);
 
  393        if (LocaleCompare(
"auto-orient",option+1) == 0)
 
  395        if (LocaleCompare(
"authenticate",option+1) == 0)
 
  400            if (i == (ssize_t) argc)
 
  401              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  404        ThrowCompareException(OptionError,
"UnrecognizedOption",option);
 
  408        if (LocaleCompare(
"background",option+1) == 0)
 
  413            if (i == (ssize_t) argc)
 
  414              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  417        if (LocaleCompare(
"brightness-contrast",option+1) == 0)
 
  420            if (i == (ssize_t) argc)
 
  421              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  422            if (IsGeometry(argv[i]) == MagickFalse)
 
  423              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  426        ThrowCompareException(OptionError,
"UnrecognizedOption",option);
 
  430        if (LocaleCompare(
"cache",option+1) == 0)
 
  435            if (i == (ssize_t) argc)
 
  436              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  437            if (IsGeometry(argv[i]) == MagickFalse)
 
  438              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  441        if (LocaleCompare(
"channel",option+1) == 0)
 
  449            if (i == (ssize_t) argc)
 
  450              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  451            channel=ParseChannelOption(argv[i]);
 
  453              ThrowCompareException(OptionError,
"UnrecognizedChannelType",
 
  457        if (LocaleCompare(
"colorspace",option+1) == 0)
 
  465            if (i == (ssize_t) argc)
 
  466              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  467            colorspace=ParseCommandOption(MagickColorspaceOptions,MagickFalse,
 
  470              ThrowCompareException(OptionError,
"UnrecognizedColorspace",
 
  474        if (LocaleCompare(
"compose",option+1) == 0)
 
  482            if (i == (ssize_t) argc)
 
  483              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  484            compose=ParseCommandOption(MagickComposeOptions,MagickFalse,
 
  487              ThrowCompareException(OptionError,
"UnrecognizedComposeOperator",
 
  491        if (LocaleCompare(
"compress",option+1) == 0)
 
  499            if (i == (ssize_t) argc)
 
  500              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  501            compress=ParseCommandOption(MagickCompressOptions,MagickFalse,
 
  504              ThrowCompareException(OptionError,
"UnrecognizedImageCompression",
 
  508        if (LocaleCompare(
"concurrent",option+1) == 0)
 
  510        if (LocaleCompare(
"crop",option+1) == 0)
 
  515            if (i == (ssize_t) argc)
 
  516              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  517            if (IsGeometry(argv[i]) == MagickFalse)
 
  518              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  521        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  525        if (LocaleCompare(
"debug",option+1) == 0)
 
  533            if (i == (ssize_t) argc)
 
  534              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  535            event_mask=SetLogEventMask(argv[i]);
 
  536            if (event_mask == UndefinedEvents)
 
  537              ThrowCompareException(OptionError,
"UnrecognizedEventType",
 
  541        if (LocaleCompare(
"decipher",option+1) == 0)
 
  546            if (i == (ssize_t) argc)
 
  547              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  550        if (LocaleCompare(
"define",option+1) == 0)
 
  553            if (i == (ssize_t) argc)
 
  554              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  560                define=GetImageOption(image_info,argv[i]);
 
  561                if (define == (
const char *) NULL)
 
  562                  ThrowCompareException(OptionError,
"NoSuchOption",argv[i]);
 
  567        if (LocaleCompare(
"delete",option+1) == 0)
 
  572            if (i == (ssize_t) argc)
 
  573              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  574            if (IsSceneGeometry(argv[i],MagickFalse) == MagickFalse)
 
  575              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  578        if (LocaleCompare(
"density",option+1) == 0)
 
  583            if (i == (ssize_t) argc)
 
  584              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  585            if (IsGeometry(argv[i]) == MagickFalse)
 
  586              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  589        if (LocaleCompare(
"depth",option+1) == 0)
 
  594            if (i == (ssize_t) argc)
 
  595              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  596            if (IsGeometry(argv[i]) == MagickFalse)
 
  597              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  600        if (LocaleCompare(
"dissimilarity-threshold",option+1) == 0)
 
  605            if (i == (ssize_t) argc)
 
  606              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  607            if (IsGeometry(argv[i]) == MagickFalse)
 
  608              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  610              dissimilarity_threshold=DefaultDissimilarityThreshold;
 
  612              dissimilarity_threshold=StringToDouble(argv[i],(
char **) NULL);
 
  615        if (LocaleCompare(
"distort",option+1) == 0)
 
  621            if (i == (ssize_t) argc)
 
  622              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  623            op=ParseCommandOption(MagickDistortOptions,MagickFalse,argv[i]);
 
  625              ThrowCompareException(OptionError,
"UnrecognizedDistortMethod",
 
  628            if (i == (ssize_t) argc)
 
  629              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  632        if (LocaleCompare(
"duration",option+1) == 0)
 
  637            if (i == (ssize_t) argc)
 
  638              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  639            if (IsGeometry(argv[i]) == MagickFalse)
 
  640              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  643        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  647        if (LocaleCompare(
"encipher",option+1) == 0)
 
  652            if (i == (ssize_t) argc)
 
  653              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  656        if (LocaleCompare(
"extract",option+1) == 0)
 
  661            if (i == (ssize_t) argc)
 
  662              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  663            if (IsGeometry(argv[i]) == MagickFalse)
 
  664              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  667        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  671        if (LocaleCompare(
"format",option+1) == 0)
 
  676            if (i == (ssize_t) argc)
 
  677              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  681        if (LocaleCompare(
"fuzz",option+1) == 0)
 
  686            if (i == (ssize_t) argc)
 
  687              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  688            if (IsGeometry(argv[i]) == MagickFalse)
 
  689              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  692        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  696        if (LocaleCompare(
"gravity",option+1) == 0)
 
  704            if (i == (ssize_t) argc)
 
  705              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  706            gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
 
  709              ThrowCompareException(OptionError,
"UnrecognizedGravityType",
 
  713        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  717        if ((LocaleCompare(
"help",option+1) == 0) ||
 
  718            (LocaleCompare(
"-help",option+1) == 0))
 
  721            return(CompareUsage());
 
  723        if (LocaleCompare(
"highlight-color",option+1) == 0)
 
  728            if (i == (ssize_t) argc)
 
  729              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  732        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  736        if (LocaleCompare(
"identify",option+1) == 0)
 
  738        if (LocaleCompare(
"interlace",option+1) == 0)
 
  746            if (i == (ssize_t) argc)
 
  747              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  748            interlace=ParseCommandOption(MagickInterlaceOptions,MagickFalse,
 
  751              ThrowCompareException(OptionError,
"UnrecognizedInterlaceType",
 
  755        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  759        if (LocaleCompare(
"level",option+1) == 0)
 
  762            if (i == (ssize_t) argc)
 
  763              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  764            if (IsGeometry(argv[i]) == MagickFalse)
 
  765              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  768        if (LocaleCompare(
"limit",option+1) == 0)
 
  782            if (i == (ssize_t) argc)
 
  783              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  784            resource=ParseCommandOption(MagickResourceOptions,MagickFalse,
 
  787              ThrowCompareException(OptionError,
"UnrecognizedResourceType",
 
  790            if (i == (ssize_t) argc)
 
  791              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  792            value=StringToDouble(argv[i],&p);
 
  794            if ((p == argv[i]) && (LocaleCompare(
"unlimited",argv[i]) != 0))
 
  795              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  798        if (LocaleCompare(
"list",option+1) == 0)
 
  806            if (i == (ssize_t) argc)
 
  807              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  808            list=ParseCommandOption(MagickListOptions,MagickFalse,argv[i]);
 
  810              ThrowCompareException(OptionError,
"UnrecognizedListType",argv[i]);
 
  811            status=MogrifyImageInfo(image_info,(
int) (i-j+1),(
const char **)
 
  814            return(status == 0 ? MagickFalse : MagickTrue);
 
  816        if (LocaleCompare(
"log",option+1) == 0)
 
  821            if ((i == (ssize_t) argc) || (strchr(argv[i],
'%') == (
char *) NULL))
 
  822              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  825        if (LocaleCompare(
"lowlight-color",option+1) == 0)
 
  830            if (i == (ssize_t) argc)
 
  831              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  834        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  838        if (LocaleCompare(
"matte",option+1) == 0)
 
  840        if (LocaleCompare(
"metric",option+1) == 0)
 
  848            if (i == (ssize_t) argc)
 
  849              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  850            type=ParseCommandOption(MagickMetricOptions,MagickTrue,argv[i]);
 
  852              ThrowCompareException(OptionError,
"UnrecognizedMetricType",
 
  854            metric=(MetricType) type;
 
  857        if (LocaleCompare(
"monitor",option+1) == 0)
 
  859        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  863        if (LocaleCompare(
"negate",option+1) == 0)
 
  865        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  869        if (LocaleCompare(
"passphrase",option+1) == 0)
 
  874            if (i == (ssize_t) argc)
 
  875              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  878        if (LocaleCompare(
"precision",option+1) == 0)
 
  883            if (i == (ssize_t) argc)
 
  884              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  885            if (IsGeometry(argv[i]) == MagickFalse)
 
  886              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  889        if (LocaleCompare(
"profile",option+1) == 0)
 
  892            if (i == (ssize_t) argc)
 
  893              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  896        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  900        if (LocaleCompare(
"quality",option+1) == 0)
 
  905            if (i == (ssize_t) argc)
 
  906              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  907            if (IsGeometry(argv[i]) == MagickFalse)
 
  908              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  911        if (LocaleCompare(
"quantize",option+1) == 0)
 
  919            if (i == (ssize_t) argc)
 
  920              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  921            colorspace=ParseCommandOption(MagickColorspaceOptions,
 
  922              MagickFalse,argv[i]);
 
  924              ThrowCompareException(OptionError,
"UnrecognizedColorspace",
 
  928        if (LocaleCompare(
"quiet",option+1) == 0)
 
  930        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  934        if (LocaleCompare(
"read-mask",option+1) == 0)
 
  939            if (i == (ssize_t) argc)
 
  940              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  943        if (LocaleCompare(
"regard-warnings",option+1) == 0)
 
  945        if (LocaleCompare(
"repage",option+1) == 0)
 
  950            if (i == (ssize_t) argc)
 
  951              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  952            if (IsGeometry(argv[i]) == MagickFalse)
 
  953              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  956        if (LocaleCompare(
"resize",option+1) == 0)
 
  961            if (i == (ssize_t) argc)
 
  962              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  963            if (IsGeometry(argv[i]) == MagickFalse)
 
  964              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  967        if (LocaleNCompare(
"respect-parentheses",option+1,17) == 0)
 
  969            respect_parentheses=(*option == 
'-') ? MagickTrue : MagickFalse;
 
  972        if (LocaleCompare(
"rotate",option+1) == 0)
 
  975            if (i == (ssize_t) argc)
 
  976              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  977            if (IsGeometry(argv[i]) == MagickFalse)
 
  978              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  981        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
  985        if (LocaleCompare(
"sampling-factor",option+1) == 0)
 
  990            if (i == (ssize_t) argc)
 
  991              ThrowCompareException(OptionError,
"MissingArgument",option);
 
  992            if (IsGeometry(argv[i]) == MagickFalse)
 
  993              ThrowCompareInvalidArgumentException(option,argv[i]);
 
  996        if (LocaleCompare(
"seed",option+1) == 0)
 
 1001            if (i == (ssize_t) argc)
 
 1002              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1003            if (IsGeometry(argv[i]) == MagickFalse)
 
 1004              ThrowCompareInvalidArgumentException(option,argv[i]);
 
 1007        if (LocaleCompare(
"separate",option+1) == 0)
 
 1009        if (LocaleCompare(
"set",option+1) == 0)
 
 1012            if (i == (ssize_t) argc)
 
 1013              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1017            if (i == (ssize_t) argc)
 
 1018              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1021        if (LocaleCompare(
"sigmoidal-contrast",option+1) == 0)
 
 1024            if (i == (ssize_t) argc)
 
 1025              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1026            if (IsGeometry(argv[i]) == MagickFalse)
 
 1027              ThrowCompareInvalidArgumentException(option,argv[i]);
 
 1030        if (LocaleCompare(
"similarity-threshold",option+1) == 0)
 
 1035            if (i == (ssize_t) argc)
 
 1036              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1037            if (IsGeometry(argv[i]) == MagickFalse)
 
 1038              ThrowCompareInvalidArgumentException(option,argv[i]);
 
 1040              similarity_threshold=DefaultSimilarityThreshold;
 
 1042              similarity_threshold=StringToDouble(argv[i],(
char **) NULL);
 
 1045        if (LocaleCompare(
"size",option+1) == 0)
 
 1050            if (i == (ssize_t) argc)
 
 1051              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1052            if (IsGeometry(argv[i]) == MagickFalse)
 
 1053              ThrowCompareInvalidArgumentException(option,argv[i]);
 
 1056        if (LocaleCompare(
"subimage-search",option+1) == 0)
 
 1060                subimage_search=MagickFalse;
 
 1063            subimage_search=MagickTrue;
 
 1066        if (LocaleCompare(
"synchronize",option+1) == 0)
 
 1068        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
 1072        if (LocaleCompare(
"taint",option+1) == 0)
 
 1074        if (LocaleCompare(
"transparent-color",option+1) == 0)
 
 1079            if (i == (ssize_t) argc)
 
 1080              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1083        if (LocaleCompare(
"trim",option+1) == 0)
 
 1085        if (LocaleCompare(
"type",option+1) == 0)
 
 1093            if (i == (ssize_t) argc)
 
 1094              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1095            type=ParseCommandOption(MagickTypeOptions,MagickFalse,argv[i]);
 
 1097              ThrowCompareException(OptionError,
"UnrecognizedImageType",
 
 1101        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
 1105        if (LocaleCompare(
"verbose",option+1) == 0)
 
 1107        if ((LocaleCompare(
"version",option+1) == 0) ||
 
 1108            (LocaleCompare(
"-version",option+1) == 0))
 
 1110            ListMagickVersion(stdout);
 
 1113        if (LocaleCompare(
"virtual-pixel",option+1) == 0)
 
 1121            if (i == (ssize_t) argc)
 
 1122              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1123            method=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
 
 1126              ThrowCompareException(OptionError,
 
 1127                "UnrecognizedVirtualPixelMethod",argv[i]);
 
 1130        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
 1134        if (LocaleCompare(
"write",option+1) == 0)
 
 1137            if (i == (ssize_t) argc)
 
 1138              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1141        if (LocaleCompare(
"write-mask",option+1) == 0)
 
 1146            if (i == (ssize_t) argc)
 
 1147              ThrowCompareException(OptionError,
"MissingArgument",option);
 
 1150        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
 1155        ThrowCompareException(OptionError,
"UnrecognizedOption",option)
 
 1157    fire=(GetCommandOptionFlags(MagickCommandOptions,MagickFalse,option) &
 
 1158      FireOptionFlag) == 0 ?  MagickFalse : MagickTrue;
 
 1159    if (fire != MagickFalse)
 
 1160      FireImageStack(MagickTrue,MagickTrue,MagickTrue);
 
 1163    ThrowCompareException(OptionError,
"UnbalancedParenthesis",argv[i]);
 
 1164  if (i-- != (ssize_t) (argc-1))
 
 1165    ThrowCompareException(OptionError,
"MissingAnImageFilename",argv[i]);
 
 1166  if ((image == (Image *) NULL) || (GetImageListLength(image) < 2))
 
 1167    ThrowCompareException(OptionError,
"MissingAnImageFilename",argv[i]);
 
 1168  FinalizeImageSettings(image_info,image,MagickTrue);
 
 1169  if ((image == (Image *) NULL) || (GetImageListLength(image) < 2))
 
 1170    ThrowCompareException(OptionError,
"MissingAnImageFilename",argv[i]);
 
 1171  image=GetImageFromList(image,0);
 
 1172  reconstruct_image=GetImageFromList(image,1);
 
 1175  if (subimage_search != MagickFalse)
 
 1177      similarity_image=SimilarityImage(image,reconstruct_image,metric,
 
 1178        similarity_threshold,&offset,&similarity_metric,exception);
 
 1179      if (similarity_image == (Image *) NULL)
 
 1180        return(MagickFalse);
 
 1181      if (similarity_metric >= dissimilarity_threshold)
 
 1182        (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
 
 1183          "ImagesTooDissimilar",
"`%s'",image->filename);
 
 1185  if (similarity_image == (Image *) NULL)
 
 1186    difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
 
 1196      composite_image=CloneImage(image,0,0,MagickTrue,exception);
 
 1197      if (composite_image == (Image *) NULL)
 
 1198        difference_image=CompareImages(image,reconstruct_image,metric,
 
 1199          &distortion,exception);
 
 1208          (void) CompositeImage(composite_image,reconstruct_image,
 
 1209            CopyCompositeOp,MagickTrue,offset.x,offset.y,exception);
 
 1210          difference_image=CompareImages(image,composite_image,metric,
 
 1211            &distortion,exception);
 
 1212          if (difference_image != (Image *) NULL)
 
 1214              difference_image->page.x=offset.x;
 
 1215              difference_image->page.y=offset.y;
 
 1217          composite_image=DestroyImage(composite_image);
 
 1218          page.width=reconstruct_image->columns;
 
 1219          page.height=reconstruct_image->rows;
 
 1222          distort_image=CropImage(image,&page,exception);
 
 1223          if (distort_image != (Image *) NULL)
 
 1228              (void) SetImageArtifact(distort_image,
"compare:virtual-pixels",
 
 1230              sans_image=CompareImages(distort_image,reconstruct_image,metric,
 
 1231                &distortion,exception);
 
 1232              if (sans_image != (Image *) NULL)
 
 1233                sans_image=DestroyImage(sans_image);
 
 1234              distort_image=DestroyImage(distort_image);
 
 1237      if (difference_image != (Image *) NULL)
 
 1239          AppendImageToList(&difference_image,similarity_image);
 
 1240          similarity_image=(Image *) NULL;
 
 1245    case AbsoluteErrorMetric:
 
 1251      SetImageCompareBounds(image,reconstruct_image,&columns,&rows);
 
 1252      scale=(double) columns*rows;
 
 1255    case DotProductCorrelationErrorMetric:
 
 1256    case PhaseCorrelationErrorMetric:
 
 1257    case NormalizedCrossCorrelationErrorMetric:
 
 1263      (void) GetImageRange(reconstruct_image,&minima,&maxima,exception);
 
 1264      if (fabs(maxima-minima) < MagickEpsilon)
 
 1265        (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
 
 1266          CompareConstantColorException,
"(%s)",CommandOptionToMnemonic(
 
 1267          MagickMetricOptions,(ssize_t) metric));
 
 1270    case PeakAbsoluteErrorMetric:
 
 1272      if ((subimage_search != MagickFalse) &&
 
 1273          (image->columns == reconstruct_image->columns) &&
 
 1274          (image->rows == reconstruct_image->rows))
 
 1275        (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
 
 1276          CompareEqualSizedException,
"(%s)",CommandOptionToMnemonic(
 
 1277          MagickMetricOptions,(ssize_t) metric));
 
 1280    case PerceptualHashErrorMetric:
 
 1282      if (subimage_search == MagickFalse)
 
 1288          (void) GetImageRange(reconstruct_image,&minima,&maxima,exception);
 
 1289          if (fabs(maxima-minima) < MagickEpsilon)
 
 1290            (void) ThrowMagickException(exception,GetMagickModule(),
 
 1291              ImageWarning,CompareConstantColorException,
"(%s)",
 
 1292              CommandOptionToMnemonic(MagickMetricOptions,(ssize_t) metric));
 
 1294      if ((subimage_search != MagickFalse) &&
 
 1295          (image->columns == reconstruct_image->columns) &&
 
 1296          (image->rows == reconstruct_image->rows))
 
 1297        (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
 
 1298          CompareEqualSizedException,
"(%s)",CommandOptionToMnemonic(
 
 1299          MagickMetricOptions,(ssize_t) metric));
 
 1302    case PeakSignalToNoiseRatioErrorMetric:
 
 1304      scale=MagickSafePSNRRecipicol(10.0);
 
 1310  if (fabs(distortion) > CompareEpsilon)
 
 1311    similar=MagickFalse;
 
 1312  if (difference_image == (Image *) NULL)
 
 1316      if (image_info->verbose != MagickFalse)
 
 1317        (void) SetImageColorMetric(image,reconstruct_image,exception);
 
 1318      if (*difference_image->magick == 
'\0')
 
 1319        (void) CopyMagickString(difference_image->magick,image->magick,
 
 1321      if (image_info->verbose == MagickFalse)
 
 1325            case AbsoluteErrorMetric:
 
 1327              (void) FormatLocaleFile(stderr,
"%.*g (%.*g)",GetMagickPrecision(),
 
 1328                ceil(scale*distortion),GetMagickPrecision(),distortion);
 
 1331            case MeanErrorPerPixelErrorMetric:
 
 1333              if (subimage_search == MagickFalse)
 
 1335                  (void) FormatLocaleFile(stderr,
"%.*g (%.*g, %.*g)",
 
 1336                    GetMagickPrecision(),scale*distortion,
 
 1337                    GetMagickPrecision(),distortion,GetMagickPrecision(),
 
 1338                    image->error.normalized_maximum_error);
 
 1345              (void) FormatLocaleFile(stderr,
"%.*g (%.*g)",GetMagickPrecision(),
 
 1346                scale*distortion,GetMagickPrecision(),distortion);
 
 1350          if (subimage_search != MagickFalse)
 
 1351            (void) FormatLocaleFile(stderr,
" @ %.20g,%.20g [%.*g]",
 
 1352              (
double) offset.x,(
double) offset.y,GetMagickPrecision(),
 
 1358            *channel_distortion;
 
 1360          channel_distortion=GetImageDistortions(image,reconstruct_image,
 
 1362          (void) FormatLocaleFile(stderr,
"Image: %s\n",image->filename);
 
 1363          if ((reconstruct_image->columns != image->columns) ||
 
 1364              (reconstruct_image->rows != image->rows))
 
 1365            (void) FormatLocaleFile(stderr,
"Offset: %.20g,%.20g\n",(
double)
 
 1366              difference_image->page.x,(
double) difference_image->page.y);
 
 1367          (void) FormatLocaleFile(stderr,
"  Channel distortion: %s\n",
 
 1368            CommandOptionToMnemonic(MagickMetricOptions,(ssize_t) metric));
 
 1371            case FuzzErrorMetric:
 
 1372            case MeanAbsoluteErrorMetric:
 
 1373            case MeanSquaredErrorMetric:
 
 1374            case PeakAbsoluteErrorMetric:
 
 1375            case RootMeanSquaredErrorMetric:
 
 1377              switch (image->colorspace)
 
 1382                  (void) FormatLocaleFile(stderr,
"    red: %.*g (%.*g)\n",
 
 1383                    GetMagickPrecision(),scale*
 
 1384                    channel_distortion[RedPixelChannel],GetMagickPrecision(),
 
 1385                    channel_distortion[RedPixelChannel]);
 
 1386                  (void) FormatLocaleFile(stderr,
"    green: %.*g (%.*g)\n",
 
 1387                    GetMagickPrecision(),scale*
 
 1388                    channel_distortion[GreenPixelChannel],GetMagickPrecision(),
 
 1389                    channel_distortion[GreenPixelChannel]);
 
 1390                  (void) FormatLocaleFile(stderr,
"    blue: %.*g (%.*g)\n",
 
 1391                    GetMagickPrecision(),scale*
 
 1392                    channel_distortion[BluePixelChannel],GetMagickPrecision(),
 
 1393                    channel_distortion[BluePixelChannel]);
 
 1394                  if (image->alpha_trait != UndefinedPixelTrait)
 
 1395                    (void) FormatLocaleFile(stderr,
"    alpha: %.*g (%.*g)\n",
 
 1396                      GetMagickPrecision(),scale*
 
 1397                      channel_distortion[AlphaPixelChannel],
 
 1398                      GetMagickPrecision(),
 
 1399                      channel_distortion[AlphaPixelChannel]);
 
 1402                case CMYKColorspace:
 
 1404                  (void) FormatLocaleFile(stderr,
"    cyan: %.*g (%.*g)\n",
 
 1405                    GetMagickPrecision(),scale*
 
 1406                    channel_distortion[CyanPixelChannel],GetMagickPrecision(),
 
 1407                    channel_distortion[CyanPixelChannel]);
 
 1408                  (void) FormatLocaleFile(stderr,
"    magenta: %.*g (%.*g)\n",
 
 1409                    GetMagickPrecision(),scale*
 
 1410                    channel_distortion[MagentaPixelChannel],
 
 1411                    GetMagickPrecision(),
 
 1412                    channel_distortion[MagentaPixelChannel]);
 
 1413                  (void) FormatLocaleFile(stderr,
"    yellow: %.*g (%.*g)\n",
 
 1414                    GetMagickPrecision(),scale*
 
 1415                    channel_distortion[YellowPixelChannel],GetMagickPrecision(),
 
 1416                    channel_distortion[YellowPixelChannel]);
 
 1417                  (void) FormatLocaleFile(stderr,
"    black: %.*g (%.*g)\n",
 
 1418                    GetMagickPrecision(),scale*
 
 1419                    channel_distortion[BlackPixelChannel],GetMagickPrecision(),
 
 1420                    channel_distortion[BlackPixelChannel]);
 
 1421                  if (image->alpha_trait != UndefinedPixelTrait)
 
 1422                    (void) FormatLocaleFile(stderr,
"    alpha: %.*g (%.*g)\n",
 
 1423                      GetMagickPrecision(),scale*
 
 1424                      channel_distortion[AlphaPixelChannel],
 
 1425                      GetMagickPrecision(),
 
 1426                      channel_distortion[AlphaPixelChannel]);
 
 1429                case LinearGRAYColorspace:
 
 1430                case GRAYColorspace:
 
 1432                  (void) FormatLocaleFile(stderr,
"    gray: %.*g (%.*g)\n",
 
 1433                    GetMagickPrecision(),scale*
 
 1434                    channel_distortion[GrayPixelChannel],GetMagickPrecision(),
 
 1435                    channel_distortion[GrayPixelChannel]);
 
 1436                  if (image->alpha_trait != UndefinedPixelTrait)
 
 1437                    (void) FormatLocaleFile(stderr,
"    alpha: %.*g (%.*g)\n",
 
 1438                      GetMagickPrecision(),scale*
 
 1439                      channel_distortion[AlphaPixelChannel],
 
 1440                      GetMagickPrecision(),
 
 1441                      channel_distortion[AlphaPixelChannel]);
 
 1445              (void) FormatLocaleFile(stderr,
"    all: %.*g (%.*g)\n",
 
 1446                GetMagickPrecision(),scale*channel_distortion[MaxPixelChannels],
 
 1447                GetMagickPrecision(),channel_distortion[MaxPixelChannels]);
 
 1450            case AbsoluteErrorMetric:
 
 1451            case DotProductCorrelationErrorMetric:
 
 1452            case NormalizedCrossCorrelationErrorMetric:
 
 1453            case PeakSignalToNoiseRatioErrorMetric:
 
 1454            case PerceptualHashErrorMetric:
 
 1455            case PhaseCorrelationErrorMetric:
 
 1456            case StructuralSimilarityErrorMetric:
 
 1457            case StructuralDissimilarityErrorMetric:
 
 1459              switch (image->colorspace)
 
 1464                  (void) FormatLocaleFile(stderr,
"    red: %.*g\n",
 
 1465                    GetMagickPrecision(),channel_distortion[RedPixelChannel]);
 
 1466                  (void) FormatLocaleFile(stderr,
"    green: %.*g\n",
 
 1467                    GetMagickPrecision(),channel_distortion[GreenPixelChannel]);
 
 1468                  (void) FormatLocaleFile(stderr,
"    blue: %.*g\n",
 
 1469                    GetMagickPrecision(),channel_distortion[BluePixelChannel]);
 
 1470                  if (image->alpha_trait != UndefinedPixelTrait)
 
 1471                    (void) FormatLocaleFile(stderr,
"    alpha: %.*g\n",
 
 1472                      GetMagickPrecision(),
 
 1473                      channel_distortion[AlphaPixelChannel]);
 
 1476                case CMYKColorspace:
 
 1478                  (void) FormatLocaleFile(stderr,
"    cyan: %.*g\n",
 
 1479                    GetMagickPrecision(),channel_distortion[CyanPixelChannel]);
 
 1480                  (void) FormatLocaleFile(stderr,
"    magenta: %.*g\n",
 
 1481                    GetMagickPrecision(),
 
 1482                    channel_distortion[MagentaPixelChannel]);
 
 1483                  (void) FormatLocaleFile(stderr,
"    yellow: %.*g\n",
 
 1484                    GetMagickPrecision(),
 
 1485                    channel_distortion[YellowPixelChannel]);
 
 1486                  (void) FormatLocaleFile(stderr,
"    black: %.*g\n",
 
 1487                    GetMagickPrecision(),
 
 1488                    channel_distortion[BlackPixelChannel]);
 
 1489                  if (image->alpha_trait != UndefinedPixelTrait)
 
 1490                    (void) FormatLocaleFile(stderr,
"    alpha: %.*g\n",
 
 1491                      GetMagickPrecision(),
 
 1492                      channel_distortion[AlphaPixelChannel]);
 
 1495                case LinearGRAYColorspace:
 
 1496                case GRAYColorspace:
 
 1498                  (void) FormatLocaleFile(stderr,
"    gray: %.*g\n",
 
 1499                    GetMagickPrecision(),channel_distortion[GrayPixelChannel]);
 
 1500                  if (image->alpha_trait != UndefinedPixelTrait)
 
 1501                    (void) FormatLocaleFile(stderr,
"    alpha: %.*g\n",
 
 1502                      GetMagickPrecision(),
 
 1503                      channel_distortion[AlphaPixelChannel]);
 
 1507              (void) FormatLocaleFile(stderr,
"    all: %.*g\n",
 
 1508                GetMagickPrecision(),channel_distortion[MaxPixelChannels]);
 
 1511            case MeanErrorPerPixelErrorMetric:
 
 1513              (void) FormatLocaleFile(stderr,
"    %.*g (%.*g, %.*g)\n",
 
 1514                GetMagickPrecision(),channel_distortion[MaxPixelChannels],
 
 1515                GetMagickPrecision(),channel_distortion[MaxPixelChannels],
 
 1516                GetMagickPrecision(),image->error.normalized_maximum_error);
 
 1519            case UndefinedErrorMetric:
 
 1522          channel_distortion=(
double *) RelinquishMagickMemory(
 
 1523            channel_distortion);
 
 1524          if (subimage_search != MagickFalse)
 
 1526              (void) FormatLocaleFile(stderr,
"   Offset: %.20g,%.20g\n",
 
 1527                (
double) difference_image->page.x,(
double)
 
 1528                difference_image->page.y);
 
 1529              (void) FormatLocaleFile(stderr,
"   Similarity metric: %*g\n",
 
 1530                GetMagickPrecision(),similarity_metric);
 
 1531              (void) FormatLocaleFile(stderr,
"   Similarity threshold: %*g\n",
 
 1532                GetMagickPrecision(),similarity_threshold);
 
 1533              (void) FormatLocaleFile(stderr,
 
 1534                "   Dissimilarity threshold: %*g\n",GetMagickPrecision(),
 
 1535                dissimilarity_threshold);
 
 1538      (void) ResetImagePage(difference_image,
"0x0+0+0");
 
 1539      if (difference_image->next != (Image *) NULL)
 
 1540        (void) ResetImagePage(difference_image->next,
"0x0+0+0");
 
 1541      status&=(MagickStatusType) WriteImages(image_info,difference_image,
 
 1542        argv[argc-1],exception);
 
 1543      if ((metadata != (
char **) NULL) && (format != (
char *) NULL))
 
 1548          text=InterpretImageProperties(image_info,difference_image,format,
 
 1550          if (text == (
char *) NULL)
 
 1551            ThrowCompareException(ResourceLimitError,
"MemoryAllocationFailed",
 
 1552              GetExceptionMessage(errno));
 
 1553          (void) ConcatenateString(&(*metadata),text);
 
 1554          text=DestroyString(text);
 
 1556      difference_image=DestroyImageList(difference_image);
 
 1559  if (similar == MagickFalse)
 
 1560    (void) SetImageOption(image_info,
"compare:dissimilar",
"true");
 
 1561  return(status != 0 ? MagickTrue : MagickFalse);