PageRenderTime 46ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/MagickWand/compare.c

https://gitlab.com/ImageMagick/ImageMagick
C | 1428 lines | 1301 code | 40 blank | 87 comment | 510 complexity | 0f20a87f24e92b94bf04924b995aa496 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. % %
  4. % %
  5. % %
  6. % CCCC OOO M M PPPP AAA RRRR EEEEE %
  7. % C O O MM MM P P A A R R E %
  8. % C O O M M M PPPP AAAAA RRRR EEE %
  9. % C O O M M P A A R R E %
  10. % CCCC OOO M M P A A R R EEEEE %
  11. % %
  12. % %
  13. % Image Comparison Methods %
  14. % %
  15. % Software Design %
  16. % Cristy %
  17. % December 2003 %
  18. % %
  19. % %
  20. % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
  21. % dedicated to making software imaging solutions freely available. %
  22. % %
  23. % You may not use this file except in compliance with the License. You may %
  24. % obtain a copy of the License at %
  25. % %
  26. % https://imagemagick.org/script/license.php %
  27. % %
  28. % Unless required by applicable law or agreed to in writing, software %
  29. % distributed under the License is distributed on an "AS IS" BASIS, %
  30. % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
  31. % See the License for the specific language governing permissions and %
  32. % limitations under the License. %
  33. % %
  34. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  35. %
  36. % Use the compare program to mathematically and visually annotate the
  37. % difference between an image and its reconstruction.
  38. %
  39. */
  40. /*
  41. Include declarations.
  42. */
  43. #include "MagickWand/studio.h"
  44. #include "MagickWand/MagickWand.h"
  45. #include "MagickWand/mogrify-private.h"
  46. #include "MagickCore/string-private.h"
  47. /*
  48. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  49. % %
  50. % %
  51. % %
  52. % C o m p a r e I m a g e C o m m a n d %
  53. % %
  54. % %
  55. % %
  56. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  57. %
  58. % CompareImagesCommand() compares two images and returns the difference between
  59. % them as a distortion metric and as a new image visually annotating their
  60. % differences.
  61. %
  62. % The format of the CompareImagesCommand method is:
  63. %
  64. % MagickBooleanType CompareImagesCommand(ImageInfo *image_info,int argc,
  65. % char **argv,char **metadata,ExceptionInfo *exception)
  66. %
  67. % A description of each parameter follows:
  68. %
  69. % o image_info: the image info.
  70. %
  71. % o argc: the number of elements in the argument vector.
  72. %
  73. % o argv: A text array containing the command line arguments.
  74. %
  75. % o metadata: any metadata is returned here.
  76. %
  77. % o exception: return any errors or warnings in this structure.
  78. %
  79. */
  80. static MagickBooleanType CompareUsage(void)
  81. {
  82. static const char
  83. channel_operators[] =
  84. " -separate separate an image channel into a grayscale image",
  85. miscellaneous[] =
  86. " -channel mask set the image channel mask\n"
  87. " -debug events display copious debugging information\n"
  88. " -help print program options\n"
  89. " -list type print a list of supported option arguments\n"
  90. " -log format format of debugging information",
  91. operators[] =
  92. " -brightness-contrast geometry\n"
  93. " improve brightness / contrast of the image\n"
  94. " -distort method args\n"
  95. " distort images according to given method and args\n"
  96. " -level value adjust the level of image contrast\n"
  97. " -resize geometry resize the image\n"
  98. " -rotate degrees apply Paeth rotation to the image\n"
  99. " -sigmoidal-contrast geometry\n"
  100. " increase the contrast without saturating highlights or\n"
  101. " -trim trim image edges\n"
  102. " -write filename write images to this file",
  103. sequence_operators[] =
  104. " -crop geometry cut out a rectangular region of the image",
  105. settings[] =
  106. " -alpha option on, activate, off, deactivate, set, opaque, copy\n"
  107. " transparent, extract, background, or shape\n"
  108. " -authenticate password\n"
  109. " decipher image with this password\n"
  110. " -background color background color\n"
  111. " -colorspace type alternate image colorspace\n"
  112. " -compose operator set image composite operator\n"
  113. " -compress type type of pixel compression when writing the image\n"
  114. " -decipher filename convert cipher pixels to plain pixels\n"
  115. " -define format:option\n"
  116. " define one or more image format options\n"
  117. " -density geometry horizontal and vertical density of the image\n"
  118. " -depth value image depth\n"
  119. " -dissimilarity-threshold value\n"
  120. " maximum distortion for (sub)image match\n"
  121. " -encipher filename convert plain pixels to cipher pixels\n"
  122. " -extract geometry extract area from image\n"
  123. " -format \"string\" output formatted image characteristics\n"
  124. " -fuzz distance colors within this distance are considered equal\n"
  125. " -gravity type horizontal and vertical text placement\n"
  126. " -highlight-color color\n"
  127. " empasize pixel differences with this color\n"
  128. " -identify identify the format and characteristics of the image\n"
  129. " -interlace type type of image interlacing scheme\n"
  130. " -limit type value pixel cache resource limit\n"
  131. " -lowlight-color color\n"
  132. " de-emphasize pixel differences with this color\n"
  133. " -metric type measure differences between images with this metric\n"
  134. " -monitor monitor progress\n"
  135. " -negate replace every pixel with its complementary color \n"
  136. " -profile filename add, delete, or apply an image profile\n"
  137. " -quality value JPEG/MIFF/PNG compression level\n"
  138. " -quiet suppress all warning messages\n"
  139. " -quantize colorspace reduce colors in this colorspace\n"
  140. " -read-mask filename associate a read mask with the image\n"
  141. " -regard-warnings pay attention to warning messages\n"
  142. " -respect-parentheses settings remain in effect until parenthesis boundary\n"
  143. " -sampling-factor geometry\n"
  144. " horizontal and vertical sampling factor\n"
  145. " -seed value seed a new sequence of pseudo-random numbers\n"
  146. " -set attribute value set an image attribute\n"
  147. " -quality value JPEG/MIFF/PNG compression level\n"
  148. " -repage geometry size and location of an image canvas\n"
  149. " -similarity-threshold value\n"
  150. " minimum distortion for (sub)image match\n"
  151. " -size geometry width and height of image\n"
  152. " -subimage-search search for subimage\n"
  153. " -synchronize synchronize image to storage device\n"
  154. " -taint declare the image as modified\n"
  155. " -transparent-color color\n"
  156. " transparent color\n"
  157. " -type type image type\n"
  158. " -verbose print detailed information about the image\n"
  159. " -version print version information\n"
  160. " -virtual-pixel method\n"
  161. " virtual pixel access method\n"
  162. " -write-mask filename associate a write mask with the image",
  163. stack_operators[] =
  164. " -delete indexes delete the image from the image sequence";
  165. ListMagickVersion(stdout);
  166. (void) printf("Usage: %s [options ...] image reconstruct difference\n",
  167. GetClientName());
  168. (void) printf("\nImage Settings:\n");
  169. (void) puts(settings);
  170. (void) printf("\nImage Operators:\n");
  171. (void) puts(operators);
  172. (void) printf("\nImage Channel Operators:\n");
  173. (void) puts(channel_operators);
  174. (void) printf("\nImage Sequence Operators:\n");
  175. (void) puts(sequence_operators);
  176. (void) printf("\nImage Stack Operators:\n");
  177. (void) puts(stack_operators);
  178. (void) printf("\nMiscellaneous Options:\n");
  179. (void) puts(miscellaneous);
  180. (void) printf(
  181. "\nBy default, the image format of 'file' is determined by its magic\n");
  182. (void) printf(
  183. "number. To specify a particular image format, precede the filename\n");
  184. (void) printf(
  185. "with an image format name and a colon (i.e. ps:image) or specify the\n");
  186. (void) printf(
  187. "image type as the filename suffix (i.e. image.ps). Specify 'file' as\n");
  188. (void) printf("'-' for standard input or output.\n");
  189. return(MagickFalse);
  190. }
  191. WandExport MagickBooleanType CompareImagesCommand(ImageInfo *image_info,
  192. int argc,char **argv,char **metadata,ExceptionInfo *exception)
  193. {
  194. #define CompareEpsilon (1.0e-06)
  195. #define DefaultDissimilarityThreshold 0.31830988618379067154
  196. #define DefaultSimilarityThreshold (-1.0)
  197. #define DestroyCompare() \
  198. { \
  199. if (similarity_image != (Image *) NULL) \
  200. similarity_image=DestroyImageList(similarity_image); \
  201. if (difference_image != (Image *) NULL) \
  202. difference_image=DestroyImageList(difference_image); \
  203. DestroyImageStack(); \
  204. for (i=0; i < (ssize_t) argc; i++) \
  205. argv[i]=DestroyString(argv[i]); \
  206. argv=(char **) RelinquishMagickMemory(argv); \
  207. }
  208. #define ThrowCompareException(asperity,tag,option) \
  209. { \
  210. if (exception->severity < (asperity)) \
  211. (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag, \
  212. "`%s'",option); \
  213. DestroyCompare(); \
  214. return(MagickFalse); \
  215. }
  216. #define ThrowCompareInvalidArgumentException(option,argument) \
  217. { \
  218. (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \
  219. "InvalidArgument","'%s': %s",option,argument); \
  220. DestroyCompare(); \
  221. return(MagickFalse); \
  222. }
  223. char
  224. *filename,
  225. *option;
  226. const char
  227. *format;
  228. double
  229. dissimilarity_threshold,
  230. distortion,
  231. similarity_metric,
  232. similarity_threshold;
  233. Image
  234. *difference_image,
  235. *image,
  236. *reconstruct_image,
  237. *similarity_image;
  238. ImageStack
  239. image_stack[MaxImageStackDepth+1];
  240. MagickBooleanType
  241. fire,
  242. pend,
  243. respect_parenthesis,
  244. subimage_search;
  245. MagickStatusType
  246. status;
  247. MetricType
  248. metric;
  249. RectangleInfo
  250. offset;
  251. register ssize_t
  252. i;
  253. ssize_t
  254. j,
  255. k;
  256. /*
  257. Set defaults.
  258. */
  259. assert(image_info != (ImageInfo *) NULL);
  260. assert(image_info->signature == MagickCoreSignature);
  261. if (image_info->debug != MagickFalse)
  262. (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
  263. assert(exception != (ExceptionInfo *) NULL);
  264. if (argc == 2)
  265. {
  266. option=argv[1];
  267. if ((LocaleCompare("version",option+1) == 0) ||
  268. (LocaleCompare("-version",option+1) == 0))
  269. {
  270. ListMagickVersion(stdout);
  271. return(MagickTrue);
  272. }
  273. }
  274. if (argc < 3)
  275. return(CompareUsage());
  276. difference_image=NewImageList();
  277. similarity_image=NewImageList();
  278. dissimilarity_threshold=DefaultDissimilarityThreshold;
  279. similarity_threshold=DefaultSimilarityThreshold;
  280. distortion=0.0;
  281. format=(char *) NULL;
  282. j=1;
  283. k=0;
  284. metric=UndefinedErrorMetric;
  285. NewImageStack();
  286. option=(char *) NULL;
  287. pend=MagickFalse;
  288. reconstruct_image=NewImageList();
  289. respect_parenthesis=MagickFalse;
  290. status=MagickTrue;
  291. subimage_search=MagickFalse;
  292. /*
  293. Compare an image.
  294. */
  295. ReadCommandlLine(argc,&argv);
  296. status=ExpandFilenames(&argc,&argv);
  297. if (status == MagickFalse)
  298. ThrowCompareException(ResourceLimitError,"MemoryAllocationFailed",
  299. GetExceptionMessage(errno));
  300. for (i=1; i < (ssize_t) (argc-1); i++)
  301. {
  302. option=argv[i];
  303. if (LocaleCompare(option,"(") == 0)
  304. {
  305. FireImageStack(MagickTrue,MagickTrue,pend);
  306. if (k == MaxImageStackDepth)
  307. ThrowCompareException(OptionError,"ParenthesisNestedTooDeeply",
  308. option);
  309. PushImageStack();
  310. continue;
  311. }
  312. if (LocaleCompare(option,")") == 0)
  313. {
  314. FireImageStack(MagickTrue,MagickTrue,MagickTrue);
  315. if (k == 0)
  316. ThrowCompareException(OptionError,"UnableToParseExpression",option);
  317. PopImageStack();
  318. continue;
  319. }
  320. if (IsCommandOption(option) == MagickFalse)
  321. {
  322. Image
  323. *images;
  324. /*
  325. Read input image.
  326. */
  327. FireImageStack(MagickFalse,MagickFalse,pend);
  328. filename=argv[i];
  329. if ((LocaleCompare(filename,"--") == 0) && (i < (ssize_t) (argc-1)))
  330. filename=argv[++i];
  331. images=ReadImages(image_info,filename,exception);
  332. status&=(images != (Image *) NULL) &&
  333. (exception->severity < ErrorException);
  334. if (images == (Image *) NULL)
  335. continue;
  336. AppendImageStack(images);
  337. continue;
  338. }
  339. pend=image != (Image *) NULL ? MagickTrue : MagickFalse;
  340. switch (*(option+1))
  341. {
  342. case 'a':
  343. {
  344. if (LocaleCompare("alpha",option+1) == 0)
  345. {
  346. ssize_t
  347. type;
  348. if (*option == '+')
  349. break;
  350. i++;
  351. if (i == (ssize_t) argc)
  352. ThrowCompareException(OptionError,"MissingArgument",option);
  353. type=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,
  354. argv[i]);
  355. if (type < 0)
  356. ThrowCompareException(OptionError,
  357. "UnrecognizedAlphaChannelOption",argv[i]);
  358. break;
  359. }
  360. if (LocaleCompare("authenticate",option+1) == 0)
  361. {
  362. if (*option == '+')
  363. break;
  364. i++;
  365. if (i == (ssize_t) argc)
  366. ThrowCompareException(OptionError,"MissingArgument",option);
  367. break;
  368. }
  369. ThrowCompareException(OptionError,"UnrecognizedOption",option);
  370. }
  371. case 'b':
  372. {
  373. if (LocaleCompare("background",option+1) == 0)
  374. {
  375. if (*option == '+')
  376. break;
  377. i++;
  378. if (i == (ssize_t) argc)
  379. ThrowCompareException(OptionError,"MissingArgument",option);
  380. break;
  381. }
  382. if (LocaleCompare("brightness-contrast",option+1) == 0)
  383. {
  384. i++;
  385. if (i == (ssize_t) argc)
  386. ThrowCompareException(OptionError,"MissingArgument",option);
  387. if (IsGeometry(argv[i]) == MagickFalse)
  388. ThrowCompareInvalidArgumentException(option,argv[i]);
  389. break;
  390. }
  391. ThrowCompareException(OptionError,"UnrecognizedOption",option);
  392. }
  393. case 'c':
  394. {
  395. if (LocaleCompare("cache",option+1) == 0)
  396. {
  397. if (*option == '+')
  398. break;
  399. i++;
  400. if (i == (ssize_t) argc)
  401. ThrowCompareException(OptionError,"MissingArgument",option);
  402. if (IsGeometry(argv[i]) == MagickFalse)
  403. ThrowCompareInvalidArgumentException(option,argv[i]);
  404. break;
  405. }
  406. if (LocaleCompare("channel",option+1) == 0)
  407. {
  408. ssize_t
  409. channel;
  410. if (*option == '+')
  411. break;
  412. i++;
  413. if (i == (ssize_t) argc)
  414. ThrowCompareException(OptionError,"MissingArgument",option);
  415. channel=ParseChannelOption(argv[i]);
  416. if (channel < 0)
  417. ThrowCompareException(OptionError,"UnrecognizedChannelType",
  418. argv[i]);
  419. break;
  420. }
  421. if (LocaleCompare("colorspace",option+1) == 0)
  422. {
  423. ssize_t
  424. colorspace;
  425. if (*option == '+')
  426. break;
  427. i++;
  428. if (i == (ssize_t) argc)
  429. ThrowCompareException(OptionError,"MissingArgument",option);
  430. colorspace=ParseCommandOption(MagickColorspaceOptions,MagickFalse,
  431. argv[i]);
  432. if (colorspace < 0)
  433. ThrowCompareException(OptionError,"UnrecognizedColorspace",
  434. argv[i]);
  435. break;
  436. }
  437. if (LocaleCompare("compose",option+1) == 0)
  438. {
  439. ssize_t
  440. compose;
  441. if (*option == '+')
  442. break;
  443. i++;
  444. if (i == (ssize_t) argc)
  445. ThrowCompareException(OptionError,"MissingArgument",option);
  446. compose=ParseCommandOption(MagickComposeOptions,MagickFalse,
  447. argv[i]);
  448. if (compose < 0)
  449. ThrowCompareException(OptionError,"UnrecognizedComposeOperator",
  450. argv[i]);
  451. break;
  452. }
  453. if (LocaleCompare("compress",option+1) == 0)
  454. {
  455. ssize_t
  456. compress;
  457. if (*option == '+')
  458. break;
  459. i++;
  460. if (i == (ssize_t) argc)
  461. ThrowCompareException(OptionError,"MissingArgument",option);
  462. compress=ParseCommandOption(MagickCompressOptions,MagickFalse,
  463. argv[i]);
  464. if (compress < 0)
  465. ThrowCompareException(OptionError,"UnrecognizedImageCompression",
  466. argv[i]);
  467. break;
  468. }
  469. if (LocaleCompare("concurrent",option+1) == 0)
  470. break;
  471. if (LocaleCompare("crop",option+1) == 0)
  472. {
  473. if (*option == '+')
  474. break;
  475. i++;
  476. if (i == (ssize_t) argc)
  477. ThrowCompareException(OptionError,"MissingArgument",option);
  478. if (IsGeometry(argv[i]) == MagickFalse)
  479. ThrowCompareInvalidArgumentException(option,argv[i]);
  480. break;
  481. }
  482. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  483. }
  484. case 'd':
  485. {
  486. if (LocaleCompare("debug",option+1) == 0)
  487. {
  488. LogEventType
  489. event_mask;
  490. if (*option == '+')
  491. break;
  492. i++;
  493. if (i == (ssize_t) argc)
  494. ThrowCompareException(OptionError,"MissingArgument",option);
  495. event_mask=SetLogEventMask(argv[i]);
  496. if (event_mask == UndefinedEvents)
  497. ThrowCompareException(OptionError,"UnrecognizedEventType",
  498. argv[i]);
  499. break;
  500. }
  501. if (LocaleCompare("decipher",option+1) == 0)
  502. {
  503. if (*option == '+')
  504. break;
  505. i++;
  506. if (i == (ssize_t) argc)
  507. ThrowCompareException(OptionError,"MissingArgument",option);
  508. break;
  509. }
  510. if (LocaleCompare("define",option+1) == 0)
  511. {
  512. i++;
  513. if (i == (ssize_t) argc)
  514. ThrowCompareException(OptionError,"MissingArgument",option);
  515. if (*option == '+')
  516. {
  517. const char
  518. *define;
  519. define=GetImageOption(image_info,argv[i]);
  520. if (define == (const char *) NULL)
  521. ThrowCompareException(OptionError,"NoSuchOption",argv[i]);
  522. break;
  523. }
  524. break;
  525. }
  526. if (LocaleCompare("delete",option+1) == 0)
  527. {
  528. if (*option == '+')
  529. break;
  530. i++;
  531. if (i == (ssize_t) argc)
  532. ThrowCompareException(OptionError,"MissingArgument",option);
  533. if (IsSceneGeometry(argv[i],MagickFalse) == MagickFalse)
  534. ThrowCompareInvalidArgumentException(option,argv[i]);
  535. break;
  536. }
  537. if (LocaleCompare("density",option+1) == 0)
  538. {
  539. if (*option == '+')
  540. break;
  541. i++;
  542. if (i == (ssize_t) argc)
  543. ThrowCompareException(OptionError,"MissingArgument",option);
  544. if (IsGeometry(argv[i]) == MagickFalse)
  545. ThrowCompareInvalidArgumentException(option,argv[i]);
  546. break;
  547. }
  548. if (LocaleCompare("depth",option+1) == 0)
  549. {
  550. if (*option == '+')
  551. break;
  552. i++;
  553. if (i == (ssize_t) argc)
  554. ThrowCompareException(OptionError,"MissingArgument",option);
  555. if (IsGeometry(argv[i]) == MagickFalse)
  556. ThrowCompareInvalidArgumentException(option,argv[i]);
  557. break;
  558. }
  559. if (LocaleCompare("dissimilarity-threshold",option+1) == 0)
  560. {
  561. if (*option == '+')
  562. break;
  563. i++;
  564. if (i == (ssize_t) argc)
  565. ThrowCompareException(OptionError,"MissingArgument",option);
  566. if (IsGeometry(argv[i]) == MagickFalse)
  567. ThrowCompareInvalidArgumentException(option,argv[i]);
  568. if (*option == '+')
  569. dissimilarity_threshold=DefaultDissimilarityThreshold;
  570. else
  571. dissimilarity_threshold=StringToDouble(argv[i],(char **) NULL);
  572. break;
  573. }
  574. if (LocaleCompare("distort",option+1) == 0)
  575. {
  576. ssize_t
  577. op;
  578. i++;
  579. if (i == (ssize_t) argc)
  580. ThrowCompareException(OptionError,"MissingArgument",option);
  581. op=ParseCommandOption(MagickDistortOptions,MagickFalse,argv[i]);
  582. if (op < 0)
  583. ThrowCompareException(OptionError,"UnrecognizedDistortMethod",
  584. argv[i]);
  585. i++;
  586. if (i == (ssize_t) argc)
  587. ThrowCompareException(OptionError,"MissingArgument",option);
  588. break;
  589. }
  590. if (LocaleCompare("duration",option+1) == 0)
  591. {
  592. if (*option == '+')
  593. break;
  594. i++;
  595. if (i == (ssize_t) argc)
  596. ThrowCompareException(OptionError,"MissingArgument",option);
  597. if (IsGeometry(argv[i]) == MagickFalse)
  598. ThrowCompareInvalidArgumentException(option,argv[i]);
  599. break;
  600. }
  601. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  602. }
  603. case 'e':
  604. {
  605. if (LocaleCompare("encipher",option+1) == 0)
  606. {
  607. if (*option == '+')
  608. break;
  609. i++;
  610. if (i == (ssize_t) argc)
  611. ThrowCompareException(OptionError,"MissingArgument",option);
  612. break;
  613. }
  614. if (LocaleCompare("extract",option+1) == 0)
  615. {
  616. if (*option == '+')
  617. break;
  618. i++;
  619. if (i == (ssize_t) argc)
  620. ThrowCompareException(OptionError,"MissingArgument",option);
  621. if (IsGeometry(argv[i]) == MagickFalse)
  622. ThrowCompareInvalidArgumentException(option,argv[i]);
  623. break;
  624. }
  625. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  626. }
  627. case 'f':
  628. {
  629. if (LocaleCompare("format",option+1) == 0)
  630. {
  631. if (*option == '+')
  632. break;
  633. i++;
  634. if (i == (ssize_t) argc)
  635. ThrowCompareException(OptionError,"MissingArgument",option);
  636. format=argv[i];
  637. break;
  638. }
  639. if (LocaleCompare("fuzz",option+1) == 0)
  640. {
  641. if (*option == '+')
  642. break;
  643. i++;
  644. if (i == (ssize_t) argc)
  645. ThrowCompareException(OptionError,"MissingArgument",option);
  646. if (IsGeometry(argv[i]) == MagickFalse)
  647. ThrowCompareInvalidArgumentException(option,argv[i]);
  648. break;
  649. }
  650. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  651. }
  652. case 'g':
  653. {
  654. if (LocaleCompare("gravity",option+1) == 0)
  655. {
  656. ssize_t
  657. gravity;
  658. if (*option == '+')
  659. break;
  660. i++;
  661. if (i == (ssize_t) argc)
  662. ThrowCompareException(OptionError,"MissingArgument",option);
  663. gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
  664. argv[i]);
  665. if (gravity < 0)
  666. ThrowCompareException(OptionError,"UnrecognizedGravityType",
  667. argv[i]);
  668. break;
  669. }
  670. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  671. }
  672. case 'h':
  673. {
  674. if ((LocaleCompare("help",option+1) == 0) ||
  675. (LocaleCompare("-help",option+1) == 0))
  676. return(CompareUsage());
  677. if (LocaleCompare("highlight-color",option+1) == 0)
  678. {
  679. if (*option == '+')
  680. break;
  681. i++;
  682. if (i == (ssize_t) argc)
  683. ThrowCompareException(OptionError,"MissingArgument",option);
  684. break;
  685. }
  686. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  687. }
  688. case 'i':
  689. {
  690. if (LocaleCompare("identify",option+1) == 0)
  691. break;
  692. if (LocaleCompare("interlace",option+1) == 0)
  693. {
  694. ssize_t
  695. interlace;
  696. if (*option == '+')
  697. break;
  698. i++;
  699. if (i == (ssize_t) argc)
  700. ThrowCompareException(OptionError,"MissingArgument",option);
  701. interlace=ParseCommandOption(MagickInterlaceOptions,MagickFalse,
  702. argv[i]);
  703. if (interlace < 0)
  704. ThrowCompareException(OptionError,"UnrecognizedInterlaceType",
  705. argv[i]);
  706. break;
  707. }
  708. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  709. }
  710. case 'l':
  711. {
  712. if (LocaleCompare("level",option+1) == 0)
  713. {
  714. i++;
  715. if (i == (ssize_t) argc)
  716. ThrowCompareException(OptionError,"MissingArgument",option);
  717. if (IsGeometry(argv[i]) == MagickFalse)
  718. ThrowCompareInvalidArgumentException(option,argv[i]);
  719. break;
  720. }
  721. if (LocaleCompare("limit",option+1) == 0)
  722. {
  723. char
  724. *p;
  725. double
  726. value;
  727. ssize_t
  728. resource;
  729. if (*option == '+')
  730. break;
  731. i++;
  732. if (i == (ssize_t) argc)
  733. ThrowCompareException(OptionError,"MissingArgument",option);
  734. resource=ParseCommandOption(MagickResourceOptions,MagickFalse,
  735. argv[i]);
  736. if (resource < 0)
  737. ThrowCompareException(OptionError,"UnrecognizedResourceType",
  738. argv[i]);
  739. i++;
  740. if (i == (ssize_t) argc)
  741. ThrowCompareException(OptionError,"MissingArgument",option);
  742. value=StringToDouble(argv[i],&p);
  743. (void) value;
  744. if ((p == argv[i]) && (LocaleCompare("unlimited",argv[i]) != 0))
  745. ThrowCompareInvalidArgumentException(option,argv[i]);
  746. break;
  747. }
  748. if (LocaleCompare("list",option+1) == 0)
  749. {
  750. ssize_t
  751. list;
  752. if (*option == '+')
  753. break;
  754. i++;
  755. if (i == (ssize_t) argc)
  756. ThrowCompareException(OptionError,"MissingArgument",option);
  757. list=ParseCommandOption(MagickListOptions,MagickFalse,argv[i]);
  758. if (list < 0)
  759. ThrowCompareException(OptionError,"UnrecognizedListType",argv[i]);
  760. status=MogrifyImageInfo(image_info,(int) (i-j+1),(const char **)
  761. argv+j,exception);
  762. DestroyCompare();
  763. return(status == 0 ? MagickFalse : MagickTrue);
  764. }
  765. if (LocaleCompare("log",option+1) == 0)
  766. {
  767. if (*option == '+')
  768. break;
  769. i++;
  770. if ((i == (ssize_t) argc) || (strchr(argv[i],'%') == (char *) NULL))
  771. ThrowCompareException(OptionError,"MissingArgument",option);
  772. break;
  773. }
  774. if (LocaleCompare("lowlight-color",option+1) == 0)
  775. {
  776. if (*option == '+')
  777. break;
  778. i++;
  779. if (i == (ssize_t) argc)
  780. ThrowCompareException(OptionError,"MissingArgument",option);
  781. break;
  782. }
  783. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  784. }
  785. case 'm':
  786. {
  787. if (LocaleCompare("matte",option+1) == 0)
  788. break;
  789. if (LocaleCompare("metric",option+1) == 0)
  790. {
  791. ssize_t
  792. type;
  793. if (*option == '+')
  794. break;
  795. i++;
  796. if (i == (ssize_t) argc)
  797. ThrowCompareException(OptionError,"MissingArgument",option);
  798. type=ParseCommandOption(MagickMetricOptions,MagickTrue,argv[i]);
  799. if (type < 0)
  800. ThrowCompareException(OptionError,"UnrecognizedMetricType",
  801. argv[i]);
  802. metric=(MetricType) type;
  803. break;
  804. }
  805. if (LocaleCompare("monitor",option+1) == 0)
  806. break;
  807. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  808. }
  809. case 'n':
  810. {
  811. if (LocaleCompare("negate",option+1) == 0)
  812. break;
  813. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  814. }
  815. case 'p':
  816. {
  817. if (LocaleCompare("profile",option+1) == 0)
  818. {
  819. i++;
  820. if (i == (ssize_t) argc)
  821. ThrowCompareException(OptionError,"MissingArgument",option);
  822. break;
  823. }
  824. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  825. }
  826. case 'q':
  827. {
  828. if (LocaleCompare("quality",option+1) == 0)
  829. {
  830. if (*option == '+')
  831. break;
  832. i++;
  833. if (i == (ssize_t) argc)
  834. ThrowCompareException(OptionError,"MissingArgument",option);
  835. if (IsGeometry(argv[i]) == MagickFalse)
  836. ThrowCompareInvalidArgumentException(option,argv[i]);
  837. break;
  838. }
  839. if (LocaleCompare("quantize",option+1) == 0)
  840. {
  841. ssize_t
  842. colorspace;
  843. if (*option == '+')
  844. break;
  845. i++;
  846. if (i == (ssize_t) argc)
  847. ThrowCompareException(OptionError,"MissingArgument",option);
  848. colorspace=ParseCommandOption(MagickColorspaceOptions,
  849. MagickFalse,argv[i]);
  850. if (colorspace < 0)
  851. ThrowCompareException(OptionError,"UnrecognizedColorspace",
  852. argv[i]);
  853. break;
  854. }
  855. if (LocaleCompare("quiet",option+1) == 0)
  856. break;
  857. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  858. }
  859. case 'r':
  860. {
  861. if (LocaleCompare("read-mask",option+1) == 0)
  862. {
  863. if (*option == '+')
  864. break;
  865. i++;
  866. if (i == (ssize_t) argc)
  867. ThrowCompareException(OptionError,"MissingArgument",option);
  868. break;
  869. }
  870. if (LocaleCompare("regard-warnings",option+1) == 0)
  871. break;
  872. if (LocaleCompare("repage",option+1) == 0)
  873. {
  874. if (*option == '+')
  875. break;
  876. i++;
  877. if (i == (ssize_t) argc)
  878. ThrowCompareException(OptionError,"MissingArgument",option);
  879. if (IsGeometry(argv[i]) == MagickFalse)
  880. ThrowCompareInvalidArgumentException(option,argv[i]);
  881. break;
  882. }
  883. if (LocaleCompare("resize",option+1) == 0)
  884. {
  885. if (*option == '+')
  886. break;
  887. i++;
  888. if (i == (ssize_t) argc)
  889. ThrowCompareException(OptionError,"MissingArgument",option);
  890. if (IsGeometry(argv[i]) == MagickFalse)
  891. ThrowCompareInvalidArgumentException(option,argv[i]);
  892. break;
  893. }
  894. if (LocaleNCompare("respect-parentheses",option+1,17) == 0)
  895. {
  896. respect_parenthesis=(*option == '-') ? MagickTrue : MagickFalse;
  897. break;
  898. }
  899. if (LocaleCompare("rotate",option+1) == 0)
  900. {
  901. i++;
  902. if (i == (ssize_t) argc)
  903. ThrowCompareException(OptionError,"MissingArgument",option);
  904. if (IsGeometry(argv[i]) == MagickFalse)
  905. ThrowCompareInvalidArgumentException(option,argv[i]);
  906. break;
  907. }
  908. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  909. }
  910. case 's':
  911. {
  912. if (LocaleCompare("sampling-factor",option+1) == 0)
  913. {
  914. if (*option == '+')
  915. break;
  916. i++;
  917. if (i == (ssize_t) argc)
  918. ThrowCompareException(OptionError,"MissingArgument",option);
  919. if (IsGeometry(argv[i]) == MagickFalse)
  920. ThrowCompareInvalidArgumentException(option,argv[i]);
  921. break;
  922. }
  923. if (LocaleCompare("seed",option+1) == 0)
  924. {
  925. if (*option == '+')
  926. break;
  927. i++;
  928. if (i == (ssize_t) argc)
  929. ThrowCompareException(OptionError,"MissingArgument",option);
  930. if (IsGeometry(argv[i]) == MagickFalse)
  931. ThrowCompareInvalidArgumentException(option,argv[i]);
  932. break;
  933. }
  934. if (LocaleCompare("separate",option+1) == 0)
  935. break;
  936. if (LocaleCompare("set",option+1) == 0)
  937. {
  938. i++;
  939. if (i == (ssize_t) argc)
  940. ThrowCompareException(OptionError,"MissingArgument",option);
  941. if (*option == '+')
  942. break;
  943. i++;
  944. if (i == (ssize_t) argc)
  945. ThrowCompareException(OptionError,"MissingArgument",option);
  946. break;
  947. }
  948. if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
  949. {
  950. i++;
  951. if (i == (ssize_t) argc)
  952. ThrowCompareException(OptionError,"MissingArgument",option);
  953. if (IsGeometry(argv[i]) == MagickFalse)
  954. ThrowCompareInvalidArgumentException(option,argv[i]);
  955. break;
  956. }
  957. if (LocaleCompare("similarity-threshold",option+1) == 0)
  958. {
  959. if (*option == '+')
  960. break;
  961. i++;
  962. if (i == (ssize_t) argc)
  963. ThrowCompareException(OptionError,"MissingArgument",option);
  964. if (IsGeometry(argv[i]) == MagickFalse)
  965. ThrowCompareInvalidArgumentException(option,argv[i]);
  966. if (*option == '+')
  967. similarity_threshold=DefaultSimilarityThreshold;
  968. else
  969. similarity_threshold=StringToDouble(argv[i],(char **) NULL);
  970. break;
  971. }
  972. if (LocaleCompare("size",option+1) == 0)
  973. {
  974. if (*option == '+')
  975. break;
  976. i++;
  977. if (i == (ssize_t) argc)
  978. ThrowCompareException(OptionError,"MissingArgument",option);
  979. if (IsGeometry(argv[i]) == MagickFalse)
  980. ThrowCompareInvalidArgumentException(option,argv[i]);
  981. break;
  982. }
  983. if (LocaleCompare("subimage-search",option+1) == 0)
  984. {
  985. if (*option == '+')
  986. {
  987. subimage_search=MagickFalse;
  988. break;
  989. }
  990. subimage_search=MagickTrue;
  991. break;
  992. }
  993. if (LocaleCompare("synchronize",option+1) == 0)
  994. break;
  995. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  996. }
  997. case 't':
  998. {
  999. if (LocaleCompare("taint",option+1) == 0)
  1000. break;
  1001. if (LocaleCompare("transparent-color",option+1) == 0)
  1002. {
  1003. if (*option == '+')
  1004. break;
  1005. i++;
  1006. if (i == (ssize_t) argc)
  1007. ThrowCompareException(OptionError,"MissingArgument",option);
  1008. break;
  1009. }
  1010. if (LocaleCompare("trim",option+1) == 0)
  1011. break;
  1012. if (LocaleCompare("type",option+1) == 0)
  1013. {
  1014. ssize_t
  1015. type;
  1016. if (*option == '+')
  1017. break;
  1018. i++;
  1019. if (i == (ssize_t) argc)
  1020. ThrowCompareException(OptionError,"MissingArgument",option);
  1021. type=ParseCommandOption(MagickTypeOptions,MagickFalse,argv[i]);
  1022. if (type < 0)
  1023. ThrowCompareException(OptionError,"UnrecognizedImageType",
  1024. argv[i]);
  1025. break;
  1026. }
  1027. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  1028. }
  1029. case 'v':
  1030. {
  1031. if (LocaleCompare("verbose",option+1) == 0)
  1032. break;
  1033. if ((LocaleCompare("version",option+1) == 0) ||
  1034. (LocaleCompare("-version",option+1) == 0))
  1035. {
  1036. ListMagickVersion(stdout);
  1037. break;
  1038. }
  1039. if (LocaleCompare("virtual-pixel",option+1) == 0)
  1040. {
  1041. ssize_t
  1042. method;
  1043. if (*option == '+')
  1044. break;
  1045. i++;
  1046. if (i == (ssize_t) argc)
  1047. ThrowCompareException(OptionError,"MissingArgument",option);
  1048. method=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
  1049. argv[i]);
  1050. if (method < 0)
  1051. ThrowCompareException(OptionError,
  1052. "UnrecognizedVirtualPixelMethod",argv[i]);
  1053. break;
  1054. }
  1055. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  1056. }
  1057. case 'w':
  1058. {
  1059. if (LocaleCompare("write",option+1) == 0)
  1060. {
  1061. i++;
  1062. if (i == (ssize_t) argc)
  1063. ThrowCompareException(OptionError,"MissingArgument",option);
  1064. break;
  1065. }
  1066. if (LocaleCompare("write-mask",option+1) == 0)
  1067. {
  1068. if (*option == '+')
  1069. break;
  1070. i++;
  1071. if (i == (ssize_t) argc)
  1072. ThrowCompareException(OptionError,"MissingArgument",option);
  1073. break;
  1074. }
  1075. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  1076. }
  1077. case '?':
  1078. break;
  1079. default:
  1080. ThrowCompareException(OptionError,"UnrecognizedOption",option)
  1081. }
  1082. fire=(GetCommandOptionFlags(MagickCommandOptions,MagickFalse,option) &
  1083. FireOptionFlag) == 0 ? MagickFalse : MagickTrue;
  1084. if (fire != MagickFalse)
  1085. FireImageStack(MagickTrue,MagickTrue,MagickTrue);
  1086. }
  1087. if (k != 0)
  1088. ThrowCompareException(OptionError,"UnbalancedParenthesis",argv[i]);
  1089. if (i-- != (ssize_t) (argc-1))
  1090. ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]);
  1091. if ((image == (Image *) NULL) || (GetImageListLength(image) < 2))
  1092. ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]);
  1093. FinalizeImageSettings(image_info,image,MagickTrue);
  1094. if ((image == (Image *) NULL) || (GetImageListLength(image) < 2))
  1095. ThrowCompareException(OptionError,"MissingAnImageFilename",argv[i]);
  1096. image=GetImageFromList(image,0);
  1097. reconstruct_image=GetImageFromList(image,1);
  1098. offset.x=0;
  1099. offset.y=0;
  1100. if (subimage_search != MagickFalse)
  1101. {
  1102. similarity_image=SimilarityImage(image,reconstruct_image,metric,
  1103. similarity_threshold,&offset,&similarity_metric,exception);
  1104. if (similarity_metric > dissimilarity_threshold)
  1105. ThrowCompareException(ImageError,"ImagesTooDissimilar",image->filename);
  1106. }
  1107. if ((reconstruct_image->columns == image->columns) &&
  1108. (reconstruct_image->rows == image->rows))
  1109. difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
  1110. exception);
  1111. else
  1112. if (similarity_image == (Image *) NULL)
  1113. difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
  1114. exception);
  1115. else
  1116. {
  1117. Image
  1118. *composite_image;
  1119. /*
  1120. Determine if reconstructed image is a subimage of the image.
  1121. */
  1122. composite_image=CloneImage(image,0,0,MagickTrue,exception);
  1123. if (composite_image == (Image *) NULL)
  1124. difference_image=CompareImages(image,reconstruct_image,metric,
  1125. &distortion,exception);
  1126. else
  1127. {
  1128. Image
  1129. *distort_image;
  1130. RectangleInfo
  1131. page;
  1132. (void) CompositeImage(composite_image,reconstruct_image,
  1133. CopyCompositeOp,MagickTrue,offset.x,offset.y,exception);
  1134. difference_image=CompareImages(image,composite_image,metric,
  1135. &distortion,exception);
  1136. if (difference_image != (Image *) NULL)
  1137. {
  1138. difference_image->page.x=offset.x;
  1139. difference_image->page.y=offset.y;
  1140. }
  1141. composite_image=DestroyImage(composite_image);
  1142. page.width=reconstruct_image->columns;
  1143. page.height=reconstruct_image->rows;
  1144. page.x=offset.x;
  1145. page.y=offset.y;
  1146. distort_image=CropImage(image,&page,exception);
  1147. if (distort_image != (Image *) NULL)
  1148. {
  1149. Image
  1150. *sans_image;
  1151. sans_image=CompareImages(distort_image,reconstruct_image,metric,
  1152. &distortion,exception);
  1153. distort_image=DestroyImage(distort_image);
  1154. if (sans_image != (Image *) NULL)
  1155. sans_image=DestroyImage(sans_image);
  1156. }
  1157. }
  1158. if (difference_image != (Image *) NULL)
  1159. {
  1160. AppendImageToList(&difference_image,similarity_image);
  1161. similarity_image=(Image *) NULL;
  1162. }
  1163. }
  1164. if (difference_image == (Image *) NULL)
  1165. status=0;
  1166. else
  1167. {
  1168. if (image_info->verbose != MagickFalse)
  1169. (void) SetImageColorMetric(image,reconstruct_image,exception);
  1170. if (*difference_image->magick == '\0')
  1171. (void) CopyMagickString(difference_image->magick,image->magick,
  1172. MagickPathExtent);
  1173. if (image_info->verbose == MagickFalse)
  1174. {
  1175. switch (metric)
  1176. {
  1177. case FuzzErrorMetric:
  1178. case MeanAbsoluteErrorMetric:
  1179. case MeanSquaredErrorMetric:
  1180. case PeakAbsoluteErrorMetric:
  1181. case RootMeanSquaredErrorMetric:
  1182. {
  1183. (void) FormatLocaleFile(stderr,"%g (%g)",QuantumRange*distortion,
  1184. (double) distortion);
  1185. break;
  1186. }
  1187. case AbsoluteErrorMetric:
  1188. case NormalizedCrossCorrelationErrorMetric:
  1189. case PeakSignalToNoiseRatioErrorMetric:
  1190. case PerceptualHashErrorMetric:
  1191. case StructuralSimilarityErrorMetric:
  1192. case StructuralDissimilarityErrorMetric:
  1193. {
  1194. (void) FormatLocaleFile(stderr,"%g",distortion);
  1195. break;
  1196. }
  1197. case MeanErrorPerPixelErrorMetric:
  1198. {
  1199. (void) FormatLocaleFile(stderr,"%g (%g, %g)",distortion,
  1200. image->error.normalized_mean_error,
  1201. image->error.normalized_maximum_error);
  1202. break;
  1203. }
  1204. case UndefinedErrorMetric:
  1205. break;
  1206. }
  1207. if (subimage_search != MagickFalse)
  1208. (void) FormatLocaleFile(stderr," @ %.20g,%.20g",(double)
  1209. difference_image->page.x,(double) difference_image->page.y);
  1210. }
  1211. else
  1212. {
  1213. double
  1214. *channel_distortion;
  1215. channel_distortion=GetImageDistortions(image,reconstruct_image,
  1216. metric,exception);
  1217. (void) FormatLocaleFile(stderr,"Image: %s\n",image->filename);
  1218. if ((reconstruct_image->columns != image->columns) ||
  1219. (reconstruct_image->rows != image->rows))
  1220. (void) FormatLocaleFile(stderr,"Offset: %.20g,%.20g\n",(double)
  1221. difference_image->page.x,(double) difference_image->page.y);
  1222. (void) FormatLocaleFile(stderr," Channel distortion: %s\n",
  1223. CommandOptionToMnemonic(MagickMetricOptions,(ssize_t) metric));
  1224. switch (metric)
  1225. {
  1226. case FuzzErrorMetric:
  1227. case MeanAbsoluteErrorMetric:
  1228. case MeanSquaredErrorMetric:
  1229. case PeakAbsoluteErrorMetric:
  1230. case RootMeanSquaredErrorMetric:
  1231. {
  1232. switch (image->colorspace)
  1233. {
  1234. case RGBColorspace:
  1235. default:
  1236. {
  1237. (void) FormatLocaleFile(stderr," red: %g (%g)\n",
  1238. QuantumRange*channel_distortion[RedPixelChannel],
  1239. channel_distortion[RedPixelChannel]);
  1240. (void) FormatLocaleFile(stderr," green: %g (%g)\n",
  1241. QuantumRange*channel_distortion[GreenPixelChannel],
  1242. channel_distortion[GreenPixelChannel]);
  1243. (void) FormatLocaleFile(stderr," blue: %g (%g)\n",
  1244. QuantumRange*channel_distortion[BluePixelChannel],
  1245. channel_distortion[BluePixelChannel]);
  1246. if (image->alpha_trait != UndefinedPixelTrait)
  1247. (void) FormatLocaleFile(stderr," alpha: %g (%g)\n",
  1248. QuantumRange*channel_distortion[AlphaPixelChannel],
  1249. channel_distortion[AlphaPixelChannel]);
  1250. break;
  1251. }
  1252. case CMYKColorspace:
  1253. {
  1254. (void) FormatLocaleFile(stderr," cyan: %g (%g)\n",
  1255. QuantumRange*channel_distortion[CyanPixelChannel],
  1256. channel_distortion[CyanPixelChannel]);
  1257. (void) FormatLocaleFile(stderr," magenta: %g (%g)\n",
  1258. QuantumRange*channel_distortion[MagentaPixelChannel],
  1259. channel_distortion[MagentaPixelChannel]);
  1260. (void) FormatLocaleFile(stderr," yellow: %g (%g)\n",
  1261. QuantumRange*channel_distortion[YellowPixelChannel],
  1262. channel_distortion[YellowPixelChannel]);
  1263. (void) FormatLocaleFile(stderr," black: %g (%g)\n",
  1264. QuantumRange*channel_distortion[BlackPixelChannel],
  1265. channel_distortion[BlackPixelChannel]);
  1266. if (image->alpha_trait != UndefinedPixelTrait)
  1267. (void) FormatLocaleFile(stderr," alpha: %g (%g)\n",
  1268. QuantumRange*channel_distortion[AlphaPixelChannel],
  1269. channel_distortion[AlphaPixelChannel]);
  1270. break;
  1271. }
  1272. case LinearGRAYColorspace:
  1273. case GRAYColorspace:
  1274. {
  1275. (void) FormatLocaleFile(stderr," gray: %g (%g)\n",
  1276. QuantumRange*channel_distortion[GrayPixelChannel],
  1277. channel_distortion[GrayPixelChannel]);
  1278. if (image->alpha_trait != UndefinedPixelTrait)
  1279. (void) FormatLocaleFile(stderr," alpha: %g (%g)\n",
  1280. QuantumRange*channel_distortion[AlphaPixelChannel],
  1281. channel_distortion[AlphaPixelChannel]);
  1282. break;
  1283. }
  1284. }
  1285. (void) FormatLocaleFile(stderr," all: %g (%g)\n",
  1286. QuantumRange*channel_distortion[MaxPixelChannels],
  1287. channel_distortion[MaxPixelChannels]);
  1288. break;
  1289. }
  1290. case AbsoluteErrorMetric:
  1291. case NormalizedCrossCorrelationErrorMetric:
  1292. case PeakSignalToNoiseRatioErrorMetric:
  1293. case PerceptualHashErrorMetric:
  1294. case StructuralSimilarityErrorMetric:
  1295. case StructuralDissimilarityErrorMetric:
  1296. {
  1297. switch (image->colorspace)
  1298. {
  1299. case RGBColorspace:
  1300. default:
  1301. {
  1302. (void) FormatLocaleFile(stderr," red: %g\n",
  1303. channel_distortion[RedPixelChannel]);
  1304. (void) FormatLocaleFile(stderr," green: %g\n",
  1305. channel_distortion[GreenPixelChannel]);
  1306. (void) FormatLocaleFile(stderr," blue: %g\n",
  1307. channel_distortion[BluePixelChannel]);
  1308. if (image->alpha_trait != UndefinedPixelTrait)

Large files files are truncated, but you can click here to view the full file