00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include "wand/studio.h"
00045 #include "wand/MagickWand.h"
00046 #include "wand/mogrify-private.h"
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 static MagickBooleanType CompareUsage(void)
00083 {
00084 const char
00085 **p;
00086
00087 static const char
00088 *miscellaneous[]=
00089 {
00090 "-debug events display copious debugging information",
00091 "-help print program options",
00092 "-list type print a list of supported option arguments",
00093 "-log format format of debugging information",
00094 (char *) NULL
00095 },
00096 *settings[]=
00097 {
00098 "-alpha option on, activate, off, deactivate, set, opaque, copy",
00099 " transparent, extract, background, or shape",
00100 "-authenticate password",
00101 " decipher image with this password",
00102 "-channel type apply option to select image channels",
00103 "-colorspace type alternate image colorspace",
00104 "-compose operator set image composite operator",
00105 "-compress type type of pixel compression when writing the image",
00106 "-decipher filename convert cipher pixels to plain pixels",
00107 "-define format:option",
00108 " define one or more image format options",
00109 "-density geometry horizontal and vertical density of the image",
00110 "-depth value image depth",
00111 "-dissimilarity-threshold value",
00112 " maximum RMSE for (sub)image match",
00113 "-encipher filename convert plain pixels to cipher pixels",
00114 "-extract geometry extract area from image",
00115 "-format \"string\" output formatted image characteristics",
00116 "-fuzz distance colors within this distance are considered equal",
00117 "-highlight-color color",
00118 " empasize pixel differences with this color",
00119 "-identify identify the format and characteristics of the image",
00120 "-interlace type type of image interlacing scheme",
00121 "-limit type value pixel cache resource limit",
00122 "-lowlight-color color",
00123 " de-emphasize pixel differences with this color",
00124 "-metric type measure differences between images with this metric",
00125 "-monitor monitor progress",
00126 "-passphrase filename get the passphrase from this file",
00127 "-profile filename add, delete, or apply an image profile",
00128 "-quality value JPEG/MIFF/PNG compression level",
00129 "-quiet suppress all warning messages",
00130 "-quantize colorspace reduce colors in this colorspace",
00131 "-regard-warnings pay attention to warning messages",
00132 "-respect-parentheses settings remain in effect until parenthesis boundary",
00133 "-sampling-factor geometry",
00134 " horizontal and vertical sampling factor",
00135 "-seed value seed a new sequence of pseudo-random numbers",
00136 "-set attribute value set an image attribute",
00137 "-quality value JPEG/MIFF/PNG compression level",
00138 "-size geometry width and height of image",
00139 "-transparent-color color",
00140 " transparent color",
00141 "-type type image type",
00142 "-verbose print detailed information about the image",
00143 "-version print version information",
00144 "-virtual-pixel method",
00145 " virtual pixel access method",
00146 (char *) NULL
00147 };
00148
00149 (void) printf("Version: %s\n",GetMagickVersion((unsigned long *) NULL));
00150 (void) printf("Copyright: %s\n",GetMagickCopyright());
00151 (void) printf("Features: %s\n\n",GetMagickFeatures());
00152 (void) printf("Usage: %s [options ...] image reconstruct difference\n",
00153 GetClientName());
00154 (void) printf("\nImage Settings:\n");
00155 for (p=settings; *p != (char *) NULL; p++)
00156 (void) printf(" %s\n",*p);
00157 (void) printf("\nMiscellaneous Options:\n");
00158 for (p=miscellaneous; *p != (char *) NULL; p++)
00159 (void) printf(" %s\n",*p);
00160 (void) printf(
00161 "\nBy default, the image format of `file' is determined by its magic\n");
00162 (void) printf(
00163 "number. To specify a particular image format, precede the filename\n");
00164 (void) printf(
00165 "with an image format name and a colon (i.e. ps:image) or specify the\n");
00166 (void) printf(
00167 "image type as the filename suffix (i.e. image.ps). Specify 'file' as\n");
00168 (void) printf("'-' for standard input or output.\n");
00169 return(MagickFalse);
00170 }
00171
00172 WandExport MagickBooleanType CompareImageCommand(ImageInfo *image_info,
00173 int argc,char **argv,char **metadata,ExceptionInfo *exception)
00174 {
00175 #define DefaultDissimilarityThreshold 0.2
00176 #define DestroyCompare() \
00177 { \
00178 if (similarity_image != (Image *) NULL) \
00179 similarity_image=DestroyImageList(similarity_image); \
00180 if (difference_image != (Image *) NULL) \
00181 difference_image=DestroyImageList(difference_image); \
00182 DestroyImageStack(); \
00183 for (i=0; i < (long) argc; i++) \
00184 argv[i]=DestroyString(argv[i]); \
00185 argv=(char **) RelinquishMagickMemory(argv); \
00186 }
00187 #define ThrowCompareException(asperity,tag,option) \
00188 { \
00189 if (exception->severity < (asperity)) \
00190 (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag, \
00191 "`%s'",option); \
00192 DestroyCompare(); \
00193 return(MagickFalse); \
00194 }
00195 #define ThrowCompareInvalidArgumentException(option,argument) \
00196 { \
00197 (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \
00198 "InvalidArgument","`%s': %s",option,argument); \
00199 DestroyCompare(); \
00200 return(MagickFalse); \
00201 }
00202
00203 char
00204 *filename,
00205 *option;
00206
00207 const char
00208 *format;
00209
00210 ChannelType
00211 channels;
00212
00213 double
00214 dissimilarity_threshold,
00215 distortion,
00216 similarity_metric;
00217
00218 Image
00219 *difference_image,
00220 *image,
00221 *reconstruct_image,
00222 *similarity_image;
00223
00224 ImageStack
00225 image_stack[MaxImageStackDepth+1];
00226
00227 long
00228 j,
00229 k;
00230
00231 MagickBooleanType
00232 fire,
00233 pend;
00234
00235 MagickStatusType
00236 status;
00237
00238 MetricType
00239 metric;
00240
00241 RectangleInfo
00242 offset;
00243
00244 register long
00245 i;
00246
00247
00248
00249
00250 assert(image_info != (ImageInfo *) NULL);
00251 assert(image_info->signature == MagickSignature);
00252 if (image_info->debug != MagickFalse)
00253 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00254 assert(exception != (ExceptionInfo *) NULL);
00255 if (argc == 2)
00256 {
00257 option=argv[1];
00258 if ((LocaleCompare("version",option+1) == 0) ||
00259 (LocaleCompare("-version",option+1) == 0))
00260 {
00261 (void) fprintf(stdout,"Version: %s\n",
00262 GetMagickVersion((unsigned long *) NULL));
00263 (void) fprintf(stdout,"Copyright: %s\n",GetMagickCopyright());
00264 (void) fprintf(stdout,"Features: %s\n\n",GetMagickFeatures());
00265 return(MagickFalse);
00266 }
00267 }
00268 if (argc < 3)
00269 {
00270 (void) CompareUsage();
00271 return(MagickTrue);
00272 }
00273 channels=AllChannels;
00274 difference_image=NewImageList();
00275 similarity_image=NewImageList();
00276 dissimilarity_threshold=DefaultDissimilarityThreshold;
00277 distortion=0.0;
00278 format=(char *) NULL;
00279 j=1;
00280 k=0;
00281 metric=UndefinedMetric;
00282 NewImageStack();
00283 option=(char *) NULL;
00284 pend=MagickFalse;
00285 reconstruct_image=NewImageList();
00286 status=MagickTrue;
00287
00288
00289
00290 ReadCommandlLine(argc,&argv);
00291 status=ExpandFilenames(&argc,&argv);
00292 if (status == MagickFalse)
00293 ThrowCompareException(ResourceLimitError,"MemoryAllocationFailed",
00294 GetExceptionMessage(errno));
00295 for (i=1; i < (long) (argc-1); i++)
00296 {
00297 option=argv[i];
00298 if (LocaleCompare(option,"(") == 0)
00299 {
00300 FireImageStack(MagickTrue,MagickTrue,pend);
00301 if (k == MaxImageStackDepth)
00302 ThrowCompareException(OptionError,"ParenthesisNestedTooDeeply",
00303 option);
00304 PushImageStack();
00305 continue;
00306 }
00307 if (LocaleCompare(option,")") == 0)
00308 {
00309 FireImageStack(MagickTrue,MagickTrue,MagickTrue);
00310 if (k == 0)
00311 ThrowCompareException(OptionError,"UnableToParseExpression",option);
00312 PopImageStack();
00313 continue;
00314 }
00315 if (IsMagickOption(option) == MagickFalse)
00316 {
00317 Image
00318 *images;
00319
00320
00321
00322
00323 FireImageStack(MagickFalse,MagickFalse,pend);
00324 filename=argv[i];
00325 if ((LocaleCompare(filename,"--") == 0) && (i < (argc-1)))
00326 filename=argv[++i];
00327 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
00328 images=ReadImages(image_info,exception);
00329 status&=(images != (Image *) NULL) &&
00330 (exception->severity < ErrorException);
00331 if (images == (Image *) NULL)
00332 continue;
00333 AppendImageStack(images);
00334 continue;
00335 }
00336 pend=image != (Image *) NULL ? MagickTrue : MagickFalse;
00337 switch (*(option+1))
00338 {
00339 case 'a':
00340 {
00341 if (LocaleCompare("alpha",option+1) == 0)
00342 {
00343 long
00344 type;
00345
00346 if (*option == '+')
00347 break;
00348 i++;
00349 if (i == (long) argc)
00350 ThrowCompareException(OptionError,"MissingArgument",option);
00351 type=ParseMagickOption(MagickAlphaOptions,MagickFalse,argv[i]);
00352 if (type < 0)
00353 ThrowCompareException(OptionError,"UnrecognizedAlphaChannelType",
00354 argv[i]);
00355 break;
00356 }
00357 if (LocaleCompare("authenticate",option+1) == 0)
00358 {
00359 if (*option == '+')
00360 break;
00361 i++;
00362 if (i == (long) argc)
00363 ThrowCompareException(OptionError,"MissingArgument",option);
00364 break;
00365 }
00366 ThrowCompareException(OptionError,"UnrecognizedOption",option);
00367 }
00368 case 'c':
00369 {
00370 if (LocaleCompare("cache",option+1) == 0)
00371 {
00372 if (*option == '+')
00373 break;
00374 i++;
00375 if (i == (long) argc)
00376 ThrowCompareException(OptionError,"MissingArgument",option);
00377 if (IsGeometry(argv[i]) == MagickFalse)
00378 ThrowCompareInvalidArgumentException(option,argv[i]);
00379 break;
00380 }
00381 if (LocaleCompare("channel",option+1) == 0)
00382 {
00383 long
00384 channel;
00385
00386 if (*option == '+')
00387 break;
00388 i++;
00389 if (i == (long) (argc-1))
00390 ThrowCompareException(OptionError,"MissingArgument",option);
00391 channel=ParseChannelOption(argv[i]);
00392 if (channel < 0)
00393 ThrowCompareException(OptionError,"UnrecognizedChannelType",
00394 argv[i]);
00395 channels=(ChannelType) channel;
00396 break;
00397 }
00398 if (LocaleCompare("colorspace",option+1) == 0)
00399 {
00400 long
00401 colorspace;
00402
00403 if (*option == '+')
00404 break;
00405 i++;
00406 if (i == (long) (argc-1))
00407 ThrowCompareException(OptionError,"MissingArgument",option);
00408 colorspace=ParseMagickOption(MagickColorspaceOptions,MagickFalse,
00409 argv[i]);
00410 if (colorspace < 0)
00411 ThrowCompareException(OptionError,"UnrecognizedColorspace",
00412 argv[i]);
00413 break;
00414 }
00415 if (LocaleCompare("compose",option+1) == 0)
00416 {
00417 long
00418 compose;
00419
00420 if (*option == '+')
00421 break;
00422 i++;
00423 if (i == (long) argc)
00424 ThrowCompareException(OptionError,"MissingArgument",option);
00425 compose=ParseMagickOption(MagickComposeOptions,MagickFalse,
00426 argv[i]);
00427 if (compose < 0)
00428 ThrowCompareException(OptionError,"UnrecognizedComposeOperator",
00429 argv[i]);
00430 break;
00431 }
00432 if (LocaleCompare("compress",option+1) == 0)
00433 {
00434 long
00435 compress;
00436
00437 if (*option == '+')
00438 break;
00439 i++;
00440 if (i == (long) (argc-1))
00441 ThrowCompareException(OptionError,"MissingArgument",option);
00442 compress=ParseMagickOption(MagickCompressOptions,MagickFalse,
00443 argv[i]);
00444 if (compress < 0)
00445 ThrowCompareException(OptionError,"UnrecognizedImageCompression",
00446 argv[i]);
00447 break;
00448 }
00449 if (LocaleCompare("concurrent",option+1) == 0)
00450 break;
00451 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00452 }
00453 case 'd':
00454 {
00455 if (LocaleCompare("debug",option+1) == 0)
00456 {
00457 LogEventType
00458 event_mask;
00459
00460 if (*option == '+')
00461 break;
00462 i++;
00463 if (i == (long) argc)
00464 ThrowCompareException(OptionError,"MissingArgument",option);
00465 event_mask=SetLogEventMask(argv[i]);
00466 if (event_mask == UndefinedEvents)
00467 ThrowCompareException(OptionError,"UnrecognizedEventType",
00468 argv[i]);
00469 break;
00470 }
00471 if (LocaleCompare("decipher",option+1) == 0)
00472 {
00473 if (*option == '+')
00474 break;
00475 i++;
00476 if (i == (long) (argc-1))
00477 ThrowCompareException(OptionError,"MissingArgument",option);
00478 break;
00479 }
00480 if (LocaleCompare("define",option+1) == 0)
00481 {
00482 i++;
00483 if (i == (long) argc)
00484 ThrowCompareException(OptionError,"MissingArgument",option);
00485 if (*option == '+')
00486 {
00487 const char
00488 *define;
00489
00490 define=GetImageOption(image_info,argv[i]);
00491 if (define == (const char *) NULL)
00492 ThrowCompareException(OptionError,"NoSuchOption",argv[i]);
00493 break;
00494 }
00495 break;
00496 }
00497 if (LocaleCompare("density",option+1) == 0)
00498 {
00499 if (*option == '+')
00500 break;
00501 i++;
00502 if (i == (long) argc)
00503 ThrowCompareException(OptionError,"MissingArgument",option);
00504 if (IsGeometry(argv[i]) == MagickFalse)
00505 ThrowCompareInvalidArgumentException(option,argv[i]);
00506 break;
00507 }
00508 if (LocaleCompare("depth",option+1) == 0)
00509 {
00510 if (*option == '+')
00511 break;
00512 i++;
00513 if (i == (long) argc)
00514 ThrowCompareException(OptionError,"MissingArgument",option);
00515 if (IsGeometry(argv[i]) == MagickFalse)
00516 ThrowCompareInvalidArgumentException(option,argv[i]);
00517 break;
00518 }
00519 if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
00520 {
00521 if (*option == '+')
00522 break;
00523 i++;
00524 if (i == (long) argc)
00525 ThrowCompareException(OptionError,"MissingArgument",option);
00526 if (IsGeometry(argv[i]) == MagickFalse)
00527 ThrowCompareInvalidArgumentException(option,argv[i]);
00528 if (*option == '+')
00529 dissimilarity_threshold=DefaultDissimilarityThreshold;
00530 else
00531 dissimilarity_threshold=atof(argv[i]);
00532 break;
00533 }
00534 if (LocaleCompare("duration",option+1) == 0)
00535 {
00536 if (*option == '+')
00537 break;
00538 i++;
00539 if (i == (long) (argc-1))
00540 ThrowCompareException(OptionError,"MissingArgument",option);
00541 if (IsGeometry(argv[i]) == MagickFalse)
00542 ThrowCompareInvalidArgumentException(option,argv[i]);
00543 break;
00544 }
00545 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00546 }
00547 case 'e':
00548 {
00549 if (LocaleCompare("encipher",option+1) == 0)
00550 {
00551 if (*option == '+')
00552 break;
00553 i++;
00554 if (i == (long) (argc-1))
00555 ThrowCompareException(OptionError,"MissingArgument",option);
00556 break;
00557 }
00558 if (LocaleCompare("extract",option+1) == 0)
00559 {
00560 if (*option == '+')
00561 break;
00562 i++;
00563 if (i == (long) (argc-1))
00564 ThrowCompareException(OptionError,"MissingArgument",option);
00565 if (IsGeometry(argv[i]) == MagickFalse)
00566 ThrowCompareInvalidArgumentException(option,argv[i]);
00567 break;
00568 }
00569 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00570 }
00571 case 'f':
00572 {
00573 if (LocaleCompare("format",option+1) == 0)
00574 {
00575 if (*option == '+')
00576 break;
00577 i++;
00578 if (i == (long) argc)
00579 ThrowCompareException(OptionError,"MissingArgument",option);
00580 format=argv[i];
00581 break;
00582 }
00583 if (LocaleCompare("fuzz",option+1) == 0)
00584 {
00585 if (*option == '+')
00586 break;
00587 i++;
00588 if (i == (long) (argc-1))
00589 ThrowCompareException(OptionError,"MissingArgument",option);
00590 if (IsGeometry(argv[i]) == MagickFalse)
00591 ThrowCompareInvalidArgumentException(option,argv[i]);
00592 break;
00593 }
00594 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00595 }
00596 case 'h':
00597 {
00598 if ((LocaleCompare("help",option+1) == 0) ||
00599 (LocaleCompare("-help",option+1) == 0))
00600 return(CompareUsage());
00601 if (LocaleCompare("highlight-color",option+1) == 0)
00602 {
00603 if (*option == '+')
00604 break;
00605 i++;
00606 if (i == (long) (argc-1))
00607 ThrowCompareException(OptionError,"MissingArgument",option);
00608 break;
00609 }
00610 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00611 }
00612 case 'i':
00613 {
00614 if (LocaleCompare("identify",option+1) == 0)
00615 break;
00616 if (LocaleCompare("interlace",option+1) == 0)
00617 {
00618 long
00619 interlace;
00620
00621 if (*option == '+')
00622 break;
00623 i++;
00624 if (i == (long) argc)
00625 ThrowCompareException(OptionError,"MissingArgument",option);
00626 interlace=ParseMagickOption(MagickInterlaceOptions,MagickFalse,
00627 argv[i]);
00628 if (interlace < 0)
00629 ThrowCompareException(OptionError,"UnrecognizedInterlaceType",
00630 argv[i]);
00631 break;
00632 }
00633 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00634 }
00635 case 'l':
00636 {
00637 if (LocaleCompare("limit",option+1) == 0)
00638 {
00639 char
00640 *p;
00641
00642 double
00643 value;
00644
00645 long
00646 resource;
00647
00648 if (*option == '+')
00649 break;
00650 i++;
00651 if (i == (long) argc)
00652 ThrowCompareException(OptionError,"MissingArgument",option);
00653 resource=ParseMagickOption(MagickResourceOptions,MagickFalse,
00654 argv[i]);
00655 if (resource < 0)
00656 ThrowCompareException(OptionError,"UnrecognizedResourceType",
00657 argv[i]);
00658 i++;
00659 if (i == (long) argc)
00660 ThrowCompareException(OptionError,"MissingArgument",option);
00661 value=strtod(argv[i],&p);
00662 if ((p == argv[i]) && (LocaleCompare("unlimited",argv[i]) != 0))
00663 ThrowCompareInvalidArgumentException(option,argv[i]);
00664 break;
00665 }
00666 if (LocaleCompare("list",option+1) == 0)
00667 {
00668 long
00669 list;
00670
00671 if (*option == '+')
00672 break;
00673 i++;
00674 if (i == (long) argc)
00675 ThrowCompareException(OptionError,"MissingArgument",option);
00676 list=ParseMagickOption(MagickListOptions,MagickFalse,argv[i]);
00677 if (list < 0)
00678 ThrowCompareException(OptionError,"UnrecognizedListType",argv[i]);
00679 (void) MogrifyImageInfo(image_info,(int) (i-j+1),(const char **)
00680 argv+j,exception);
00681 DestroyCompare();
00682 return(MagickTrue);
00683 }
00684 if (LocaleCompare("log",option+1) == 0)
00685 {
00686 if (*option == '+')
00687 break;
00688 i++;
00689 if ((i == (long) argc) || (strchr(argv[i],'%') == (char *) NULL))
00690 ThrowCompareException(OptionError,"MissingArgument",option);
00691 break;
00692 }
00693 if (LocaleCompare("lowlight-color",option+1) == 0)
00694 {
00695 if (*option == '+')
00696 break;
00697 i++;
00698 if (i == (long) (argc-1))
00699 ThrowCompareException(OptionError,"MissingArgument",option);
00700 break;
00701 }
00702 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00703 }
00704 case 'm':
00705 {
00706 if (LocaleCompare("matte",option+1) == 0)
00707 break;
00708 if (LocaleCompare("metric",option+1) == 0)
00709 {
00710 long
00711 type;
00712
00713 if (*option == '+')
00714 break;
00715 i++;
00716 if (i == (long) argc)
00717 ThrowCompareException(OptionError,"MissingArgument",option);
00718 type=ParseMagickOption(MagickMetricOptions,MagickTrue,argv[i]);
00719 if (type < 0)
00720 ThrowCompareException(OptionError,"UnrecognizedMetricType",
00721 argv[i]);
00722 metric=(MetricType) type;
00723 break;
00724 }
00725 if (LocaleCompare("monitor",option+1) == 0)
00726 break;
00727 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00728 }
00729 case 'p':
00730 {
00731 if (LocaleCompare("passphrase",option+1) == 0)
00732 {
00733 if (*option == '+')
00734 break;
00735 i++;
00736 if (i == (long) argc)
00737 ThrowCompareException(OptionError,"MissingArgument",option);
00738 break;
00739 }
00740 if (LocaleCompare("profile",option+1) == 0)
00741 {
00742 i++;
00743 if (i == (long) (argc-1))
00744 ThrowCompareException(OptionError,"MissingArgument",option);
00745 break;
00746 }
00747 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00748 }
00749 case 'q':
00750 {
00751 if (LocaleCompare("quality",option+1) == 0)
00752 {
00753 if (*option == '+')
00754 break;
00755 i++;
00756 if (i == (long) (argc-1))
00757 ThrowCompareException(OptionError,"MissingArgument",option);
00758 if (IsGeometry(argv[i]) == MagickFalse)
00759 ThrowCompareInvalidArgumentException(option,argv[i]);
00760 break;
00761 }
00762 if (LocaleCompare("quantize",option+1) == 0)
00763 {
00764 long
00765 colorspace;
00766
00767 if (*option == '+')
00768 break;
00769 i++;
00770 if (i == (long) (argc-1))
00771 ThrowCompareException(OptionError,"MissingArgument",option);
00772 colorspace=ParseMagickOption(MagickColorspaceOptions,
00773 MagickFalse,argv[i]);
00774 if (colorspace < 0)
00775 ThrowCompareException(OptionError,"UnrecognizedColorspace",
00776 argv[i]);
00777 break;
00778 }
00779 if (LocaleCompare("quiet",option+1) == 0)
00780 break;
00781 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00782 }
00783 case 'r':
00784 {
00785 if (LocaleCompare("regard-warnings",option+1) == 0)
00786 break;
00787 if (LocaleNCompare("respect-parentheses",option+1,17) == 0)
00788 {
00789 respect_parenthesis=(*option == '-') ? MagickTrue : MagickFalse;
00790 break;
00791 }
00792 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00793 }
00794 case 's':
00795 {
00796 if (LocaleCompare("sampling-factor",option+1) == 0)
00797 {
00798 if (*option == '+')
00799 break;
00800 i++;
00801 if (i == (long) argc)
00802 ThrowCompareException(OptionError,"MissingArgument",option);
00803 if (IsGeometry(argv[i]) == MagickFalse)
00804 ThrowCompareInvalidArgumentException(option,argv[i]);
00805 break;
00806 }
00807 if (LocaleCompare("seed",option+1) == 0)
00808 {
00809 if (*option == '+')
00810 break;
00811 i++;
00812 if (i == (long) (argc-1))
00813 ThrowCompareException(OptionError,"MissingArgument",option);
00814 if (IsGeometry(argv[i]) == MagickFalse)
00815 ThrowCompareInvalidArgumentException(option,argv[i]);
00816 break;
00817 }
00818 if (LocaleCompare("set",option+1) == 0)
00819 {
00820 i++;
00821 if (i == (long) argc)
00822 ThrowCompareException(OptionError,"MissingArgument",option);
00823 if (*option == '+')
00824 break;
00825 i++;
00826 if (i == (long) argc)
00827 ThrowCompareException(OptionError,"MissingArgument",option);
00828 break;
00829 }
00830 if (LocaleCompare("size",option+1) == 0)
00831 {
00832 if (*option == '+')
00833 break;
00834 i++;
00835 if (i == (long) argc)
00836 ThrowCompareException(OptionError,"MissingArgument",option);
00837 if (IsGeometry(argv[i]) == MagickFalse)
00838 ThrowCompareInvalidArgumentException(option,argv[i]);
00839 break;
00840 }
00841 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00842 }
00843 case 't':
00844 {
00845 if (LocaleCompare("transparent-color",option+1) == 0)
00846 {
00847 if (*option == '+')
00848 break;
00849 i++;
00850 if (i == (long) (argc-1))
00851 ThrowCompareException(OptionError,"MissingArgument",option);
00852 break;
00853 }
00854 if (LocaleCompare("type",option+1) == 0)
00855 {
00856 long
00857 type;
00858
00859 if (*option == '+')
00860 break;
00861 i++;
00862 if (i == (long) argc)
00863 ThrowCompareException(OptionError,"MissingArgument",option);
00864 type=ParseMagickOption(MagickTypeOptions,MagickFalse,argv[i]);
00865 if (type < 0)
00866 ThrowCompareException(OptionError,"UnrecognizedImageType",
00867 argv[i]);
00868 break;
00869 }
00870 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00871 }
00872 case 'v':
00873 {
00874 if (LocaleCompare("verbose",option+1) == 0)
00875 break;
00876 if ((LocaleCompare("version",option+1) == 0) ||
00877 (LocaleCompare("-version",option+1) == 0))
00878 {
00879 (void) fprintf(stdout,"Version: %s\n",
00880 GetMagickVersion((unsigned long *) NULL));
00881 (void) fprintf(stdout,"Copyright: %s\n",GetMagickCopyright());
00882 (void) fprintf(stdout,"Features: %s\n\n",GetMagickFeatures());
00883 break;
00884 }
00885 if (LocaleCompare("virtual-pixel",option+1) == 0)
00886 {
00887 long
00888 method;
00889
00890 if (*option == '+')
00891 break;
00892 i++;
00893 if (i == (long) (argc-1))
00894 ThrowCompareException(OptionError,"MissingArgument",option);
00895 method=ParseMagickOption(MagickVirtualPixelOptions,MagickFalse,
00896 argv[i]);
00897 if (method < 0)
00898 ThrowCompareException(OptionError,
00899 "UnrecognizedVirtualPixelMethod",argv[i]);
00900 break;
00901 }
00902 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00903 }
00904 case '?':
00905 break;
00906 default:
00907 ThrowCompareException(OptionError,"UnrecognizedOption",option)
00908 }
00909 fire=ParseMagickOption(MagickImageListOptions,MagickFalse,option+1) < 0 ?
00910 MagickFalse : MagickTrue;
00911 if (fire != MagickFalse)
00912 FireImageStack(MagickTrue,MagickTrue,MagickTrue);
00913 }
00914 if (k != 0)
00915 ThrowCompareException(OptionError,"UnbalancedParenthesis",argv[i]);
00916 if (i-- != (long) (argc-1))
00917 ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]);
00918 if ((image == (Image *) NULL) || (GetImageListLength(image) < 2))
00919 ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]);
00920 FinalizeImageSettings(image_info,image,MagickTrue);
00921 if ((image == (Image *) NULL) || (GetImageListLength(image) < 2))
00922 ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]);
00923 image=GetImageFromList(image,0);
00924 reconstruct_image=GetImageFromList(image,1);
00925 similarity_image=SimilarityImage(image,reconstruct_image,&offset,
00926 &similarity_metric,exception);
00927 if (similarity_metric > dissimilarity_threshold)
00928 ThrowCompareException(ImageError,"ImagesTooDissimilar",image->filename);
00929 if ((reconstruct_image->columns == image->columns) &&
00930 (reconstruct_image->rows == image->rows))
00931 difference_image=CompareImageChannels(image,reconstruct_image,channels,
00932 metric,&distortion,exception);
00933 else
00934 if (similarity_image != (Image *) NULL)
00935 {
00936 Image
00937 *composite_image;
00938
00939
00940
00941
00942 composite_image=CloneImage(image,0,0,MagickTrue,exception);
00943 if (composite_image == (Image *) NULL)
00944 difference_image=CompareImageChannels(image,reconstruct_image,
00945 channels,metric,&distortion,exception);
00946 else
00947 {
00948 (void) CompositeImage(composite_image,CopyCompositeOp,
00949 reconstruct_image,offset.x,offset.y);
00950 difference_image=CompareImageChannels(image,composite_image,
00951 channels,metric,&distortion,exception);
00952 if (difference_image != (Image *) NULL)
00953 {
00954 difference_image->page.x=offset.x;
00955 difference_image->page.y=offset.y;
00956 }
00957 composite_image=DestroyImage(composite_image);
00958 }
00959 if (difference_image == (Image *) NULL)
00960 similarity_image=DestroyImage(similarity_image);
00961 else
00962 {
00963 AppendImageToList(&difference_image,similarity_image);
00964 similarity_image=(Image *) NULL;
00965 }
00966 }
00967 if (difference_image == (Image *) NULL)
00968 status=0;
00969 else
00970 {
00971 if (image_info->verbose != MagickFalse)
00972 (void) IsImagesEqual(image,reconstruct_image);
00973 if (*difference_image->magick == '\0')
00974 (void) CopyMagickString(difference_image->magick,image->magick,
00975 MaxTextExtent);
00976 if (image_info->verbose == MagickFalse)
00977 {
00978 switch (metric)
00979 {
00980 case MeanAbsoluteErrorMetric:
00981 case MeanSquaredErrorMetric:
00982 case RootMeanSquaredErrorMetric:
00983 case PeakAbsoluteErrorMetric:
00984 {
00985 (void) fprintf(stderr,"%g (%g)",QuantumRange*distortion,(double)
00986 distortion);
00987 if ((reconstruct_image->columns != image->columns) ||
00988 (reconstruct_image->rows != image->rows))
00989 (void) fprintf(stderr," @ %ld,%ld",difference_image->page.x,
00990 difference_image->page.y);
00991 (void) fprintf(stderr,"\n");
00992 break;
00993 }
00994 case AbsoluteErrorMetric:
00995 case PeakSignalToNoiseRatioMetric:
00996 {
00997 (void) fprintf(stderr,"%g",distortion);
00998 if ((reconstruct_image->columns != image->columns) ||
00999 (reconstruct_image->rows != image->rows))
01000 (void) fprintf(stderr," @ %ld,%ld",difference_image->page.x,
01001 difference_image->page.y);
01002 (void) fprintf(stderr,"\n");
01003 break;
01004 }
01005 case MeanErrorPerPixelMetric:
01006 {
01007 (void) fprintf(stderr,"%g (%g, %g)",distortion,
01008 image->error.normalized_mean_error,
01009 image->error.normalized_maximum_error);
01010 if ((reconstruct_image->columns != image->columns) ||
01011 (reconstruct_image->rows != image->rows))
01012 (void) fprintf(stderr," @ %ld,%ld",difference_image->page.x,
01013 difference_image->page.y);
01014 (void) fprintf(stderr,"\n");
01015 break;
01016 }
01017 case UndefinedMetric:
01018 break;
01019 }
01020 }
01021 else
01022 {
01023 double
01024 *channel_distortion;
01025
01026 channel_distortion=GetImageChannelDistortions(image,reconstruct_image,
01027 metric,&image->exception);
01028 (void) fprintf(stderr,"Image: %s\n",image->filename);
01029 if ((reconstruct_image->columns != image->columns) ||
01030 (reconstruct_image->rows != image->rows))
01031 (void) fprintf(stderr,"Offset: %ld,%ld\n",difference_image->page.x,
01032 difference_image->page.y);
01033 (void) fprintf(stderr," Channel distortion: %s\n",
01034 MagickOptionToMnemonic(MagickMetricOptions,(long) metric));
01035 switch (metric)
01036 {
01037 case MeanAbsoluteErrorMetric:
01038 case MeanSquaredErrorMetric:
01039 case RootMeanSquaredErrorMetric:
01040 case PeakAbsoluteErrorMetric:
01041 {
01042 switch (image->colorspace)
01043 {
01044 case RGBColorspace:
01045 default:
01046 {
01047 (void) fprintf(stderr," red: %g (%g)\n",
01048 QuantumRange*channel_distortion[RedChannel],
01049 channel_distortion[RedChannel]);
01050 (void) fprintf(stderr," green: %g (%g)\n",
01051 QuantumRange*channel_distortion[GreenChannel],
01052 channel_distortion[GreenChannel]);
01053 (void) fprintf(stderr," blue: %g (%g)\n",
01054 QuantumRange*channel_distortion[BlueChannel],
01055 channel_distortion[BlueChannel]);
01056 if (image->matte != MagickFalse)
01057 (void) fprintf(stderr," alpha: %g (%g)\n",
01058 QuantumRange*channel_distortion[OpacityChannel],
01059 channel_distortion[OpacityChannel]);
01060 break;
01061 }
01062 case CMYKColorspace:
01063 {
01064 (void) fprintf(stderr," cyan: %g (%g)\n",
01065 QuantumRange*channel_distortion[CyanChannel],
01066 channel_distortion[CyanChannel]);
01067 (void) fprintf(stderr," magenta: %g (%g)\n",
01068 QuantumRange*channel_distortion[MagentaChannel],
01069 channel_distortion[MagentaChannel]);
01070 (void) fprintf(stderr," yellow: %g (%g)\n",
01071 QuantumRange*channel_distortion[YellowChannel],
01072 channel_distortion[YellowChannel]);
01073 (void) fprintf(stderr," black: %g (%g)\n",
01074 QuantumRange*channel_distortion[BlackChannel],
01075 channel_distortion[BlackChannel]);
01076 if (image->matte != MagickFalse)
01077 (void) fprintf(stderr," alpha: %g (%g)\n",
01078 QuantumRange*channel_distortion[OpacityChannel],
01079 channel_distortion[OpacityChannel]);
01080 break;
01081 }
01082 case GRAYColorspace:
01083 {
01084 (void) fprintf(stderr," gray: %g (%g)\n",
01085 QuantumRange*channel_distortion[GrayChannel],
01086 channel_distortion[GrayChannel]);
01087 if (image->matte != MagickFalse)
01088 (void) fprintf(stderr," alpha: %g (%g)\n",
01089 QuantumRange*channel_distortion[OpacityChannel],
01090 channel_distortion[OpacityChannel]);
01091 break;
01092 }
01093 }
01094 (void) fprintf(stderr," all: %g (%g)\n",
01095 QuantumRange*channel_distortion[AllChannels],
01096 channel_distortion[AllChannels]);
01097 break;
01098 }
01099 case AbsoluteErrorMetric:
01100 case PeakSignalToNoiseRatioMetric:
01101 {
01102 switch (image->colorspace)
01103 {
01104 case RGBColorspace:
01105 default:
01106 {
01107 (void) fprintf(stderr," red: %g\n",
01108 channel_distortion[RedChannel]);
01109 (void) fprintf(stderr," green: %g\n",
01110 channel_distortion[GreenChannel]);
01111 (void) fprintf(stderr," blue: %g\n",
01112 channel_distortion[BlueChannel]);
01113 if (image->matte != MagickFalse)
01114 (void) fprintf(stderr," alpha: %g\n",
01115 channel_distortion[OpacityChannel]);
01116 break;
01117 }
01118 case CMYKColorspace:
01119 {
01120 (void) fprintf(stderr," cyan: %g\n",
01121 channel_distortion[CyanChannel]);
01122 (void) fprintf(stderr," magenta: %g\n",
01123 channel_distortion[MagentaChannel]);
01124 (void) fprintf(stderr," yellow: %g\n",
01125 channel_distortion[YellowChannel]);
01126 (void) fprintf(stderr," black: %g\n",
01127 channel_distortion[BlackChannel]);
01128 if (image->matte != MagickFalse)
01129 (void) fprintf(stderr," alpha: %g\n",
01130 channel_distortion[OpacityChannel]);
01131 break;
01132 }
01133 case GRAYColorspace:
01134 {
01135 (void) fprintf(stderr," gray: %g\n",
01136 channel_distortion[GrayChannel]);
01137 if (image->matte != MagickFalse)
01138 (void) fprintf(stderr," alpha: %g\n",
01139 channel_distortion[OpacityChannel]);
01140 break;
01141 }
01142 }
01143 (void) fprintf(stderr," all: %g\n",
01144 channel_distortion[AllChannels]);
01145 break;
01146 }
01147 case MeanErrorPerPixelMetric:
01148 {
01149 (void) fprintf(stderr," %g (%g, %g)\n",
01150 channel_distortion[AllChannels],
01151 image->error.normalized_mean_error,
01152 image->error.normalized_maximum_error);
01153 break;
01154 }
01155 case UndefinedMetric:
01156 break;
01157 }
01158 channel_distortion=(double *) RelinquishMagickMemory(
01159 channel_distortion);
01160 }
01161 status&=WriteImages(image_info,difference_image,argv[argc-1],exception);
01162 if ((metadata != (char **) NULL) && (format != (char *) NULL))
01163 {
01164 char
01165 *text;
01166
01167 text=InterpretImageProperties(image_info,difference_image,format);
01168 if (text == (char *) NULL)
01169 ThrowCompareException(ResourceLimitError,"MemoryAllocationFailed",
01170 GetExceptionMessage(errno));
01171 (void) ConcatenateString(&(*metadata),text);
01172 (void) ConcatenateString(&(*metadata),"\n");
01173 text=DestroyString(text);
01174 }
01175 difference_image=DestroyImageList(difference_image);
01176 }
01177 DestroyCompare();
01178 return(status != 0 ? MagickTrue : MagickFalse);
01179 }