]> granicus.if.org Git - imagemagick/blob - tests/validate.c
2c52689c0a86fe587f7bbefdd4cb6da10c77d5f2
[imagemagick] / tests / validate.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                                                                             %
7 %           V   V   AAA   L      IIIII  DDDD    AAA   TTTTT  EEEEE            %
8 %           V   V  A   A  L        I    D   D  A   A    T    E                %
9 %           V   V  AAAAA  L        I    D   D  AAAAA    T    EEE              %
10 %            V V   A   A  L        I    D   D  A   A    T    E                %
11 %             V    A   A  LLLLL  IIIII  DDDD   A   A    T    EEEEE            %
12 %                                                                             %
13 %                                                                             %
14 %                        ImageMagick Validation Suite                         %
15 %                                                                             %
16 %                             Software Design                                 %
17 %                               John Cristy                                   %
18 %                               March 2001                                    %
19 %                                                                             %
20 %                                                                             %
21 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
22 %  dedicated to making software imaging solutions freely available.           %
23 %                                                                             %
24 %  You may not use this file except in compliance with the License.  You may  %
25 %  obtain a copy of the License at                                            %
26 %                                                                             %
27 %    http://www.imagemagick.org/script/license.php                            %
28 %                                                                             %
29 %  Unless required by applicable law or agreed to in writing, software        %
30 %  distributed under the License is distributed on an "AS IS" BASIS,          %
31 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
32 %  see the License for the specific language governing permissions and        %
33 %  limitations under the License.                                             %
34 %                                                                             %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 %
37 %
38 */
39 \f
40 /*
41   Include declarations.
42 */
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <ctype.h>
47 #include <math.h>
48 #include "MagickWand/MagickWand.h"
49 #include "MagickCore/colorspace-private.h"
50 #include "MagickCore/string-private.h"
51 #include "validate.h"
52 \f
53 /*
54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 %                                                                             %
56 %                                                                             %
57 %                                                                             %
58 %   V a l i d a t e C o m p a r e C o m m a n d                               %
59 %                                                                             %
60 %                                                                             %
61 %                                                                             %
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 %
64 %  ValidateCompareCommand() validates the ImageMagick compare command line
65 %  program and returns the number of validation tests that passed and failed.
66 %
67 %  The format of the ValidateCompareCommand method is:
68 %
69 %      size_t ValidateCompareCommand(ImageInfo *image_info,
70 %        const char *reference_filename,const char *output_filename,
71 %        size_t *fail,ExceptionInfo *exception)
72 %
73 %  A description of each parameter follows:
74 %
75 %    o image_info: the image info.
76 %
77 %    o reference_filename: the reference image filename.
78 %
79 %    o output_filename: the output image filename.
80 %
81 %    o fail: return the number of validation tests that pass.
82 %
83 %    o exception: return any errors or warnings in this structure.
84 %
85 */
86 static size_t ValidateCompareCommand(ImageInfo *image_info,
87   const char *reference_filename,const char *output_filename,size_t *fail,
88   ExceptionInfo *exception)
89 {
90   char
91     **arguments,
92     command[MaxTextExtent];
93
94   int
95     number_arguments;
96
97   MagickBooleanType
98     status;
99
100   register ssize_t
101     i,
102     j;
103
104   size_t
105     test;
106
107   test=0;
108   (void) FormatLocaleFile(stdout,"validate compare command line program:\n");
109   for (i=0; compare_options[i] != (char *) NULL; i++)
110   {
111     CatchException(exception);
112     (void) FormatLocaleFile(stdout,"  test %.20g: %s",(double) (test++),
113       compare_options[i]);
114     (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
115       compare_options[i],reference_filename,reference_filename,output_filename);
116     arguments=StringToArgv(command,&number_arguments);
117     if (arguments == (char **) NULL)
118       {
119         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
120           GetMagickModule());
121         (*fail)++;
122         continue;
123       }
124     status=CompareImagesCommand(image_info,number_arguments,arguments,
125       (char **) NULL,exception);
126     for (j=0; j < (ssize_t) number_arguments; j++)
127       arguments[j]=DestroyString(arguments[j]);
128     arguments=(char **) RelinquishMagickMemory(arguments);
129     if (status != MagickFalse)
130       {
131         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
132           GetMagickModule());
133         (*fail)++;
134         continue;
135       }
136     (void) FormatLocaleFile(stdout,"... pass.\n");
137   }
138   (void) FormatLocaleFile(stdout,
139     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
140     (double) (test-(*fail)),(double) *fail);
141   return(test);
142 }
143 \f
144 /*
145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146 %                                                                             %
147 %                                                                             %
148 %                                                                             %
149 %   V a l i d a t e C o m p o s i t e C o m m a n d                           %
150 %                                                                             %
151 %                                                                             %
152 %                                                                             %
153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154 %
155 %  ValidateCompositeCommand() validates the ImageMagick composite command line
156 %  program and returns the number of validation tests that passed and failed.
157 %
158 %  The format of the ValidateCompositeCommand method is:
159 %
160 %      size_t ValidateCompositeCommand(ImageInfo *image_info,
161 %        const char *reference_filename,const char *output_filename,
162 %        size_t *fail,ExceptionInfo *exception)
163 %
164 %  A description of each parameter follows:
165 %
166 %    o image_info: the image info.
167 %
168 %    o reference_filename: the reference image filename.
169 %
170 %    o output_filename: the output image filename.
171 %
172 %    o fail: return the number of validation tests that pass.
173 %
174 %    o exception: return any errors or warnings in this structure.
175 %
176 */
177 static size_t ValidateCompositeCommand(ImageInfo *image_info,
178   const char *reference_filename,const char *output_filename,size_t *fail,
179   ExceptionInfo *exception)
180 {
181   char
182     **arguments,
183     command[MaxTextExtent];
184
185   int
186     number_arguments;
187
188   MagickBooleanType
189     status;
190
191   register ssize_t
192     i,
193     j;
194
195   size_t
196     test;
197
198   test=0;
199   (void) FormatLocaleFile(stdout,"validate composite command line program:\n");
200   for (i=0; composite_options[i] != (char *) NULL; i++)
201   {
202     CatchException(exception);
203     (void) FormatLocaleFile(stdout,"  test %.20g: %s",(double) (test++),
204       composite_options[i]);
205     (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
206       reference_filename,composite_options[i],reference_filename,
207       output_filename);
208     arguments=StringToArgv(command,&number_arguments);
209     if (arguments == (char **) NULL)
210       {
211         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
212           GetMagickModule());
213         (*fail)++;
214         continue;
215       }
216     status=CompositeImageCommand(image_info,number_arguments,arguments,
217       (char **) NULL,exception);
218     for (j=0; j < (ssize_t) number_arguments; j++)
219       arguments[j]=DestroyString(arguments[j]);
220     arguments=(char **) RelinquishMagickMemory(arguments);
221     if (status != MagickFalse)
222       {
223         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
224           GetMagickModule());
225         (*fail)++;
226         continue;
227       }
228     (void) FormatLocaleFile(stdout,"... pass.\n");
229   }
230   (void) FormatLocaleFile(stdout,
231     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
232     (double) (test-(*fail)),(double) *fail);
233   return(test);
234 }
235 \f
236 /*
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 %                                                                             %
239 %                                                                             %
240 %                                                                             %
241 %   V a l i d a t e C o n v e r t C o m m a n d                               %
242 %                                                                             %
243 %                                                                             %
244 %                                                                             %
245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 %
247 %  ValidateConvertCommand() validates the ImageMagick convert command line
248 %  program and returns the number of validation tests that passed and failed.
249 %
250 %  The format of the ValidateConvertCommand method is:
251 %
252 %      size_t ValidateConvertCommand(ImageInfo *image_info,
253 %        const char *reference_filename,const char *output_filename,
254 %        size_t *fail,ExceptionInfo *exception)
255 %
256 %  A description of each parameter follows:
257 %
258 %    o image_info: the image info.
259 %
260 %    o reference_filename: the reference image filename.
261 %
262 %    o output_filename: the output image filename.
263 %
264 %    o fail: return the number of validation tests that pass.
265 %
266 %    o exception: return any errors or warnings in this structure.
267 %
268 */
269 static size_t ValidateConvertCommand(ImageInfo *image_info,
270   const char *reference_filename,const char *output_filename,size_t *fail,
271   ExceptionInfo *exception)
272 {
273   char
274     **arguments,
275     command[MaxTextExtent];
276
277   int
278     number_arguments;
279
280   MagickBooleanType
281     status;
282
283   register ssize_t
284     i,
285     j;
286
287   size_t
288     test;
289
290   test=0;
291   (void) FormatLocaleFile(stdout,"validate convert command line program:\n");
292   for (i=0; convert_options[i] != (char *) NULL; i++)
293   {
294     CatchException(exception);
295     (void) FormatLocaleFile(stdout,"  test %.20g: %s",(double) test++,
296       convert_options[i]);
297     (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
298       reference_filename,convert_options[i],reference_filename,output_filename);
299     arguments=StringToArgv(command,&number_arguments);
300     if (arguments == (char **) NULL)
301       {
302         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
303           GetMagickModule());
304         (*fail)++;
305         continue;
306       }
307     status=ConvertImageCommand(image_info,number_arguments,arguments,
308       (char **) NULL,exception);
309     for (j=0; j < (ssize_t) number_arguments; j++)
310       arguments[j]=DestroyString(arguments[j]);
311     arguments=(char **) RelinquishMagickMemory(arguments);
312     if (status != MagickFalse)
313       {
314         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
315           GetMagickModule());
316         (*fail)++;
317         continue;
318       }
319     (void) FormatLocaleFile(stdout,"... pass.\n");
320   }
321   (void) FormatLocaleFile(stdout,
322     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
323     (double) (test-(*fail)),(double) *fail);
324   return(test);
325 }
326 \f
327 /*
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 %                                                                             %
330 %                                                                             %
331 %                                                                             %
332 %   V a l i d a t e I d e n t i f y C o m m a n d                             %
333 %                                                                             %
334 %                                                                             %
335 %                                                                             %
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %
338 %  ValidateIdentifyCommand() validates the ImageMagick identify command line
339 %  program and returns the number of validation tests that passed and failed.
340 %
341 %  The format of the ValidateIdentifyCommand method is:
342 %
343 %      size_t ValidateIdentifyCommand(ImageInfo *image_info,
344 %        const char *reference_filename,const char *output_filename,
345 %        size_t *fail,ExceptionInfo *exception)
346 %
347 %  A description of each parameter follows:
348 %
349 %    o image_info: the image info.
350 %
351 %    o reference_filename: the reference image filename.
352 %
353 %    o output_filename: the output image filename.
354 %
355 %    o fail: return the number of validation tests that pass.
356 %
357 %    o exception: return any errors or warnings in this structure.
358 %
359 */
360 static size_t ValidateIdentifyCommand(ImageInfo *image_info,
361   const char *reference_filename,const char *output_filename,size_t *fail,
362   ExceptionInfo *exception)
363 {
364   char
365     **arguments,
366     command[MaxTextExtent];
367
368   int
369     number_arguments;
370
371   MagickBooleanType
372     status;
373
374   register ssize_t
375     i,
376     j;
377
378   size_t
379     test;
380
381   (void) output_filename;
382   test=0;
383   (void) FormatLocaleFile(stdout,"validate identify command line program:\n");
384   for (i=0; identify_options[i] != (char *) NULL; i++)
385   {
386     CatchException(exception);
387     (void) FormatLocaleFile(stdout,"  test %.20g: %s",(double) test++,
388       identify_options[i]);
389     (void) FormatLocaleString(command,MaxTextExtent,"%s %s",
390       identify_options[i],reference_filename);
391     arguments=StringToArgv(command,&number_arguments);
392     if (arguments == (char **) NULL)
393       {
394         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
395           GetMagickModule());
396         (*fail)++;
397         continue;
398       }
399     status=IdentifyImageCommand(image_info,number_arguments,arguments,
400       (char **) NULL,exception);
401     for (j=0; j < (ssize_t) number_arguments; j++)
402       arguments[j]=DestroyString(arguments[j]);
403     arguments=(char **) RelinquishMagickMemory(arguments);
404     if (status != MagickFalse)
405       {
406         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
407           GetMagickModule());
408         (*fail)++;
409         continue;
410       }
411     (void) FormatLocaleFile(stdout,"... pass.\n");
412   }
413   (void) FormatLocaleFile(stdout,
414     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
415     (double) (test-(*fail)),(double) *fail);
416   return(test);
417 }
418 \f
419 /*
420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
421 %                                                                             %
422 %                                                                             %
423 %                                                                             %
424 %   V a l i d a t e I m a g e F o r m a t s I n M e m o r y                   %
425 %                                                                             %
426 %                                                                             %
427 %                                                                             %
428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429 %
430 %  ValidateImageFormatsInMemory() validates the ImageMagick image formats in
431 %  memory and returns the number of validation tests that passed and failed.
432 %
433 %  The format of the ValidateImageFormatsInMemory method is:
434 %
435 %      size_t ValidateImageFormatsInMemory(ImageInfo *image_info,
436 %        const char *reference_filename,const char *output_filename,
437 %        size_t *fail,ExceptionInfo *exception)
438 %
439 %  A description of each parameter follows:
440 %
441 %    o image_info: the image info.
442 %
443 %    o reference_filename: the reference image filename.
444 %
445 %    o output_filename: the output image filename.
446 %
447 %    o fail: return the number of validation tests that pass.
448 %
449 %    o exception: return any errors or warnings in this structure.
450 %
451 */
452 static size_t ValidateImageFormatsInMemory(ImageInfo *image_info,
453   const char *reference_filename,const char *output_filename,size_t *fail,
454   ExceptionInfo *exception)
455 {
456   char
457     size[MaxTextExtent];
458
459   const MagickInfo
460     *magick_info;
461
462   double
463     distortion,
464     fuzz;
465
466   Image
467     *difference_image,
468     *ping_image,
469     *reconstruct_image,
470     *reference_image;
471
472   MagickBooleanType
473     status;
474
475   register ssize_t
476     i,
477     j;
478
479   size_t
480     length,
481     test;
482
483   unsigned char
484     *blob;
485
486   test=0;
487   (void) FormatLocaleFile(stdout,"validate image formats in memory:\n");
488   for (i=0; reference_formats[i].magick != (char *) NULL; i++)
489   {
490     magick_info=GetMagickInfo(reference_formats[i].magick,exception);
491     if ((magick_info == (const MagickInfo *) NULL) ||
492         (magick_info->decoder == (DecodeImageHandler *) NULL) ||
493         (magick_info->encoder == (EncodeImageHandler *) NULL))
494       continue;
495     for (j=0; reference_types[j].type != UndefinedType; j++)
496     {
497       /*
498         Generate reference image.
499       */
500       CatchException(exception);
501       (void) FormatLocaleFile(stdout,"  test %.20g: %s/%s/%s/%.20g-bits",
502         (double) (test++),reference_formats[i].magick,CommandOptionToMnemonic(
503         MagickCompressOptions,reference_formats[i].compression),
504         CommandOptionToMnemonic(MagickTypeOptions,reference_types[j].type),
505         (double) reference_types[j].depth);
506       (void) CopyMagickString(image_info->filename,reference_filename,
507         MaxTextExtent);
508       reference_image=ReadImage(image_info,exception);
509       if (reference_image == (Image *) NULL)
510         {
511           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
512             GetMagickModule());
513           (*fail)++;
514           continue;
515         }
516       /*
517         Write reference image.
518       */
519       (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",
520         (double) reference_image->columns,(double) reference_image->rows);
521       (void) CloneString(&image_info->size,size);
522       image_info->depth=reference_types[j].depth;
523       (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
524         reference_formats[i].magick,output_filename);
525       status=SetImageType(reference_image,reference_types[j].type,exception);
526       if (status == MagickFalse)
527         {
528           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
529             GetMagickModule());
530           (*fail)++;
531           reference_image=DestroyImage(reference_image);
532           continue;
533         }
534       status=SetImageDepth(reference_image,reference_types[j].depth,exception);
535       if (status == MagickFalse)
536         {
537           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
538             GetMagickModule());
539           (*fail)++;
540           reference_image=DestroyImage(reference_image);
541           continue;
542         }
543       reference_image->compression=reference_formats[i].compression;
544       status=WriteImage(image_info,reference_image,exception);
545       reference_image=DestroyImage(reference_image);
546       if (status == MagickFalse)
547         {
548           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
549             GetMagickModule());
550           (*fail)++;
551           continue;
552         }
553       /*
554         Ping reference image.
555       */
556       (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
557         reference_formats[i].magick,output_filename);
558       ping_image=PingImage(image_info,exception);
559       if (ping_image == (Image *) NULL)
560         {
561           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
562             GetMagickModule());
563           (*fail)++;
564           continue;
565         }
566       ping_image=DestroyImage(ping_image);
567       /*
568         Read reference image.
569       */
570       reference_image=ReadImage(image_info,exception);
571       if (reference_image == (Image *) NULL)
572         {
573           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
574             GetMagickModule());
575           (*fail)++;
576           continue;
577         }
578       /*
579         Write reference image.
580       */
581       (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
582         reference_formats[i].magick,output_filename);
583       (void) CopyMagickString(image_info->magick,reference_formats[i].magick,
584         MaxTextExtent);
585       reference_image->depth=reference_types[j].depth;
586       reference_image->compression=reference_formats[i].compression;
587       length=8192;
588       blob=ImageToBlob(image_info,reference_image,&length,exception);
589       if (blob == (unsigned char *) NULL)
590         {
591           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
592             GetMagickModule());
593           (*fail)++;
594           reference_image=DestroyImage(reference_image);
595           continue;
596         }
597       /*
598         Ping reference blob.
599       */
600       ping_image=PingBlob(image_info,blob,length,exception);
601       if (ping_image == (Image *) NULL)
602         {
603           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
604             GetMagickModule());
605           (*fail)++;
606           blob=(unsigned char *) RelinquishMagickMemory(blob);
607           continue;
608         }
609       ping_image=DestroyImage(ping_image);
610       /*
611         Read reconstruct image.
612       */
613       (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
614         reference_formats[i].magick,output_filename);
615       reconstruct_image=BlobToImage(image_info,blob,length,exception);
616       blob=(unsigned char *) RelinquishMagickMemory(blob);
617       if (reconstruct_image == (Image *) NULL)
618         {
619           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
620             GetMagickModule());
621           (*fail)++;
622           reference_image=DestroyImage(reference_image);
623           continue;
624         }
625       /*
626         Compare reference to reconstruct image.
627       */
628       fuzz=0.0;
629       if (reference_formats[i].fuzz != 0.0)
630         fuzz=reference_formats[i].fuzz;
631 #if defined(MAGICKCORE_HDRI_SUPPORT)
632       fuzz+=0.003;
633 #endif
634       if (IssRGBColorspace(reference_image->colorspace) == MagickFalse)
635         fuzz+=0.3;
636       fuzz+=MagickEpsilon;
637       difference_image=CompareImages(reference_image,reconstruct_image,
638         RootMeanSquaredErrorMetric,&distortion,exception);
639       reconstruct_image=DestroyImage(reconstruct_image);
640       reference_image=DestroyImage(reference_image);
641       if (difference_image == (Image *) NULL)
642         {
643           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
644             GetMagickModule());
645           (*fail)++;
646           continue;
647         }
648       difference_image=DestroyImage(difference_image);
649       if ((QuantumScale*distortion) > fuzz)
650         {
651           (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
652             QuantumScale*distortion);
653           (*fail)++;
654           continue;
655         }
656       (void) FormatLocaleFile(stdout,"... pass.\n");
657     }
658   }
659   (void) FormatLocaleFile(stdout,
660     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
661     (double) (test-(*fail)),(double) *fail);
662   return(test);
663 }
664 \f
665 /*
666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 %                                                                             %
668 %                                                                             %
669 %                                                                             %
670 %   V a l i d a t e I m a g e F o r m a t s O n D i s k                       %
671 %                                                                             %
672 %                                                                             %
673 %                                                                             %
674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675 %
676 %  ValidateImageFormatsOnDisk() validates the ImageMagick image formats on disk
677 %  and returns the number of validation tests that passed and failed.
678 %
679 %  The format of the ValidateImageFormatsOnDisk method is:
680 %
681 %      size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
682 %        const char *reference_filename,const char *output_filename,
683 %        size_t *fail,ExceptionInfo *exception)
684 %
685 %  A description of each parameter follows:
686 %
687 %    o image_info: the image info.
688 %
689 %    o reference_filename: the reference image filename.
690 %
691 %    o output_filename: the output image filename.
692 %
693 %    o fail: return the number of validation tests that pass.
694 %
695 %    o exception: return any errors or warnings in this structure.
696 %
697 */
698 static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
699   const char *reference_filename,const char *output_filename,size_t *fail,
700   ExceptionInfo *exception)
701 {
702   char
703     size[MaxTextExtent];
704
705   const MagickInfo
706     *magick_info;
707
708   double
709     distortion,
710     fuzz;
711
712   Image
713     *difference_image,
714     *reference_image,
715     *reconstruct_image;
716
717   MagickBooleanType
718     status;
719
720   register ssize_t
721     i,
722     j;
723
724   size_t
725     test;
726
727   test=0;
728   (void) FormatLocaleFile(stdout,"validate image formats on disk:\n");
729   for (i=0; reference_formats[i].magick != (char *) NULL; i++)
730   {
731     magick_info=GetMagickInfo(reference_formats[i].magick,exception);
732     if ((magick_info == (const MagickInfo *) NULL) ||
733         (magick_info->decoder == (DecodeImageHandler *) NULL) ||
734         (magick_info->encoder == (EncodeImageHandler *) NULL))
735       continue;
736     for (j=0; reference_types[j].type != UndefinedType; j++)
737     {
738       /*
739         Generate reference image.
740       */
741       CatchException(exception);
742       (void) FormatLocaleFile(stdout,"  test %.20g: %s/%s/%s/%.20g-bits",
743         (double) (test++),reference_formats[i].magick,CommandOptionToMnemonic(
744         MagickCompressOptions,reference_formats[i].compression),
745         CommandOptionToMnemonic(MagickTypeOptions,reference_types[j].type),
746         (double) reference_types[j].depth);
747       (void) CopyMagickString(image_info->filename,reference_filename,
748         MaxTextExtent);
749       reference_image=ReadImage(image_info,exception);
750       if (reference_image == (Image *) NULL)
751         {
752           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
753             GetMagickModule());
754           (*fail)++;
755           continue;
756         }
757       /*
758         Write reference image.
759       */
760       (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",
761         (double) reference_image->columns,(double) reference_image->rows);
762       (void) CloneString(&image_info->size,size);
763       image_info->depth=reference_types[j].depth;
764       (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
765         reference_formats[i].magick,output_filename);
766       status=SetImageType(reference_image,reference_types[j].type,exception);
767       if (status == MagickFalse)
768         {
769           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
770             GetMagickModule());
771           (*fail)++;
772           reference_image=DestroyImage(reference_image);
773           continue;
774         }
775       status=SetImageDepth(reference_image,reference_types[j].depth,exception);
776       if (status == MagickFalse)
777         {
778           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
779             GetMagickModule());
780           (*fail)++;
781           reference_image=DestroyImage(reference_image);
782           continue;
783         }
784       reference_image->compression=reference_formats[i].compression;
785       status=WriteImage(image_info,reference_image,exception);
786       reference_image=DestroyImage(reference_image);
787       if (status == MagickFalse)
788         {
789           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
790             GetMagickModule());
791           (*fail)++;
792           continue;
793         }
794       /*
795         Read reference image.
796       */
797       (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
798         reference_formats[i].magick,output_filename);
799       reference_image=ReadImage(image_info,exception);
800       if (reference_image == (Image *) NULL)
801         {
802           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
803             GetMagickModule());
804           (*fail)++;
805           continue;
806         }
807       /*
808         Write reference image.
809       */
810       (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
811         reference_formats[i].magick,output_filename);
812       reference_image->depth=reference_types[j].depth;
813       reference_image->compression=reference_formats[i].compression;
814       status=WriteImage(image_info,reference_image,exception);
815       if (status == MagickFalse)
816         {
817           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
818             GetMagickModule());
819           (*fail)++;
820           reference_image=DestroyImage(reference_image);
821           continue;
822         }
823       /*
824         Read reconstruct image.
825       */
826       (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
827         reference_formats[i].magick,output_filename);
828       reconstruct_image=ReadImage(image_info,exception);
829       if (reconstruct_image == (Image *) NULL)
830         {
831           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
832             GetMagickModule());
833           (*fail)++;
834           reference_image=DestroyImage(reference_image);
835           continue;
836         }
837       /*
838         Compare reference to reconstruct image.
839       */
840       fuzz=0.0;
841       if (reference_formats[i].fuzz != 0.0)
842         fuzz=reference_formats[i].fuzz;
843 #if defined(MAGICKCORE_HDRI_SUPPORT)
844       fuzz+=0.003;
845 #endif
846       if (IssRGBColorspace(reference_image->colorspace) == MagickFalse)
847         fuzz+=0.3;
848       fuzz+=MagickEpsilon;
849       difference_image=CompareImages(reference_image,reconstruct_image,
850         RootMeanSquaredErrorMetric,&distortion,exception);
851       reconstruct_image=DestroyImage(reconstruct_image);
852       reference_image=DestroyImage(reference_image);
853       if (difference_image == (Image *) NULL)
854         {
855           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
856             GetMagickModule());
857           (*fail)++;
858           continue;
859         }
860       difference_image=DestroyImage(difference_image);
861       if ((QuantumScale*distortion) > fuzz)
862         {
863           (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
864             QuantumScale*distortion);
865           (*fail)++;
866           continue;
867         }
868       (void) FormatLocaleFile(stdout,"... pass.\n");
869     }
870   }
871   (void) FormatLocaleFile(stdout,
872     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
873     (double) (test-(*fail)),(double) *fail);
874   return(test);
875 }
876 \f
877 /*
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
879 %                                                                             %
880 %                                                                             %
881 %                                                                             %
882 %   V a l i d a t e I m p o r t E x p o r t P i x e l s                       %
883 %                                                                             %
884 %                                                                             %
885 %                                                                             %
886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
887 %
888 %  ValidateImportExportPixels() validates the pixel import and export methods.
889 %  It returns the number of validation tests that passed and failed.
890 %
891 %  The format of the ValidateImportExportPixels method is:
892 %
893 %      size_t ValidateImportExportPixels(ImageInfo *image_info,
894 %        const char *reference_filename,const char *output_filename,
895 %        size_t *fail,ExceptionInfo *exception)
896 %
897 %  A description of each parameter follows:
898 %
899 %    o image_info: the image info.
900 %
901 %    o reference_filename: the reference image filename.
902 %
903 %    o output_filename: the output image filename.
904 %
905 %    o fail: return the number of validation tests that pass.
906 %
907 %    o exception: return any errors or warnings in this structure.
908 %
909 */
910 static size_t ValidateImportExportPixels(ImageInfo *image_info,
911   const char *reference_filename,const char *output_filename,size_t *fail,
912   ExceptionInfo *exception)
913 {
914   double
915     distortion;
916
917   Image
918     *difference_image,
919     *reference_image,
920     *reconstruct_image;
921
922   MagickBooleanType
923     status;
924
925   register ssize_t
926     i,
927     j;
928
929   size_t
930     length;
931
932   unsigned char
933     *pixels;
934
935   size_t
936     test;
937
938   (void) output_filename;
939   test=0;
940   (void) FormatLocaleFile(stdout,
941     "validate the import and export of image pixels:\n");
942   for (i=0; reference_map[i] != (char *) NULL; i++)
943   {
944     for (j=0; reference_storage[j].type != UndefinedPixel; j++)
945     {
946       /*
947         Generate reference image.
948       */
949       CatchException(exception);
950       (void) FormatLocaleFile(stdout,"  test %.20g: %s/%s",(double) (test++),
951         reference_map[i],CommandOptionToMnemonic(MagickStorageOptions,
952         reference_storage[j].type));
953       (void) CopyMagickString(image_info->filename,reference_filename,
954         MaxTextExtent);
955       reference_image=ReadImage(image_info,exception);
956       if (reference_image == (Image *) NULL)
957         {
958           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
959             GetMagickModule());
960           (*fail)++;
961           continue;
962         }
963       if (LocaleNCompare(reference_map[i],"cmy",3) == 0)
964         (void) SetImageColorspace(reference_image,CMYKColorspace,exception);
965       length=strlen(reference_map[i])*reference_image->columns*
966         reference_image->rows*reference_storage[j].quantum;
967       pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
968       if (pixels == (unsigned char *) NULL)
969         {
970           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
971             GetMagickModule());
972           (*fail)++;
973           reference_image=DestroyImage(reference_image);
974           continue;
975         }
976       (void) ResetMagickMemory(pixels,0,length*sizeof(*pixels));
977       status=ExportImagePixels(reference_image,0,0,reference_image->columns,
978         reference_image->rows,reference_map[i],reference_storage[j].type,pixels,
979         exception);
980       if (status == MagickFalse)
981         {
982           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
983             GetMagickModule());
984           (*fail)++;
985           pixels=(unsigned char *) RelinquishMagickMemory(pixels);
986           reference_image=DestroyImage(reference_image);
987           continue;
988         }
989       (void) SetImageBackgroundColor(reference_image,exception);
990       status=ImportImagePixels(reference_image,0,0,reference_image->columns,
991         reference_image->rows,reference_map[i],reference_storage[j].type,
992         pixels,exception);
993       if (status == MagickFalse)
994         {
995           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
996             GetMagickModule());
997           (*fail)++;
998            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
999           reference_image=DestroyImage(reference_image);
1000           continue;
1001         }
1002       /*
1003         Read reconstruct image.
1004       */
1005       reconstruct_image=AcquireImage(image_info,exception);
1006       (void) SetImageExtent(reconstruct_image,reference_image->columns,
1007         reference_image->rows,exception);
1008       (void) SetImageColorspace(reconstruct_image,reference_image->colorspace,
1009         exception);
1010       (void) SetImageBackgroundColor(reconstruct_image,exception);
1011       status=ImportImagePixels(reconstruct_image,0,0,reconstruct_image->columns,
1012         reconstruct_image->rows,reference_map[i],reference_storage[j].type,
1013         pixels,exception);
1014       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1015       if (status == MagickFalse)
1016         {
1017           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1018             GetMagickModule());
1019           (*fail)++;
1020           reference_image=DestroyImage(reference_image);
1021           continue;
1022         }
1023       /*
1024         Compare reference to reconstruct image.
1025       */
1026       difference_image=CompareImages(reference_image,reconstruct_image,
1027         RootMeanSquaredErrorMetric,&distortion,exception);
1028       reconstruct_image=DestroyImage(reconstruct_image);
1029       reference_image=DestroyImage(reference_image);
1030       if (difference_image == (Image *) NULL)
1031         {
1032           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1033             GetMagickModule());
1034           (*fail)++;
1035           continue;
1036         }
1037       difference_image=DestroyImage(difference_image);
1038       if ((QuantumScale*distortion) > 0.0)
1039         {
1040           (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
1041             QuantumScale*distortion);
1042           (*fail)++;
1043           continue;
1044         }
1045       (void) FormatLocaleFile(stdout,"... pass.\n");
1046     }
1047   }
1048   (void) FormatLocaleFile(stdout,
1049     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1050     (double) (test-(*fail)),(double) *fail);
1051   return(test);
1052 }
1053 \f
1054 /*
1055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1056 %                                                                             %
1057 %                                                                             %
1058 %                                                                             %
1059 %   V a l i d a t e M o n t a g e C o m m a n d                               %
1060 %                                                                             %
1061 %                                                                             %
1062 %                                                                             %
1063 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1064 %
1065 %  ValidateMontageCommand() validates the ImageMagick montage command line
1066 %  program and returns the number of validation tests that passed and failed.
1067 %
1068 %  The format of the ValidateMontageCommand method is:
1069 %
1070 %      size_t ValidateMontageCommand(ImageInfo *image_info,
1071 %        const char *reference_filename,const char *output_filename,
1072 %        size_t *fail,ExceptionInfo *exception)
1073 %
1074 %  A description of each parameter follows:
1075 %
1076 %    o image_info: the image info.
1077 %
1078 %    o reference_filename: the reference image filename.
1079 %
1080 %    o output_filename: the output image filename.
1081 %
1082 %    o fail: return the number of validation tests that pass.
1083 %
1084 %    o exception: return any errors or warnings in this structure.
1085 %
1086 */
1087 static size_t ValidateMontageCommand(ImageInfo *image_info,
1088   const char *reference_filename,const char *output_filename,size_t *fail,
1089   ExceptionInfo *exception)
1090 {
1091   char
1092     **arguments,
1093     command[MaxTextExtent];
1094
1095   int
1096     number_arguments;
1097
1098   MagickBooleanType
1099     status;
1100
1101   register ssize_t
1102     i,
1103     j;
1104
1105   size_t
1106     test;
1107
1108   test=0;
1109   (void) FormatLocaleFile(stdout,"validate montage command line program:\n");
1110   for (i=0; montage_options[i] != (char *) NULL; i++)
1111   {
1112     CatchException(exception);
1113     (void) FormatLocaleFile(stdout,"  test %.20g: %s",(double) (test++),
1114       montage_options[i]);
1115     (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
1116       reference_filename,montage_options[i],reference_filename,
1117       output_filename);
1118     arguments=StringToArgv(command,&number_arguments);
1119     if (arguments == (char **) NULL)
1120       {
1121         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1122             GetMagickModule());
1123         (*fail)++;
1124         continue;
1125       }
1126     status=MontageImageCommand(image_info,number_arguments,arguments,
1127       (char **) NULL,exception);
1128     for (j=0; j < (ssize_t) number_arguments; j++)
1129       arguments[j]=DestroyString(arguments[j]);
1130     arguments=(char **) RelinquishMagickMemory(arguments);
1131     if (status != MagickFalse)
1132       {
1133         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1134             GetMagickModule());
1135         (*fail)++;
1136         continue;
1137       }
1138     (void) FormatLocaleFile(stdout,"... pass.\n");
1139   }
1140   (void) FormatLocaleFile(stdout,
1141     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1142     (double) (test-(*fail)),(double) *fail);
1143   return(test);
1144 }
1145 \f
1146 /*
1147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1148 %                                                                             %
1149 %                                                                             %
1150 %                                                                             %
1151 %   V a l i d a t e S t r e a m C o m m a n d                                 %
1152 %                                                                             %
1153 %                                                                             %
1154 %                                                                             %
1155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1156 %
1157 %  ValidateStreamCommand() validates the ImageMagick stream command line
1158 %  program and returns the number of validation tests that passed and failed.
1159 %
1160 %  The format of the ValidateStreamCommand method is:
1161 %
1162 %      size_t ValidateStreamCommand(ImageInfo *image_info,
1163 %        const char *reference_filename,const char *output_filename,
1164 %        size_t *fail,ExceptionInfo *exception)
1165 %
1166 %  A description of each parameter follows:
1167 %
1168 %    o image_info: the image info.
1169 %
1170 %    o reference_filename: the reference image filename.
1171 %
1172 %    o output_filename: the output image filename.
1173 %
1174 %    o fail: return the number of validation tests that pass.
1175 %
1176 %    o exception: return any errors or warnings in this structure.
1177 %
1178 */
1179 static size_t ValidateStreamCommand(ImageInfo *image_info,
1180   const char *reference_filename,const char *output_filename,size_t *fail,
1181   ExceptionInfo *exception)
1182 {
1183   char
1184     **arguments,
1185     command[MaxTextExtent];
1186
1187   int
1188     number_arguments;
1189
1190   MagickBooleanType
1191     status;
1192
1193   register ssize_t
1194     i,
1195     j;
1196
1197   size_t
1198     test;
1199
1200   test=0;
1201   (void) FormatLocaleFile(stdout,"validate stream command line program:\n");
1202   for (i=0; stream_options[i] != (char *) NULL; i++)
1203   {
1204     CatchException(exception);
1205     (void) FormatLocaleFile(stdout,"  test %.20g: %s",(double) (test++),
1206       stream_options[i]);
1207     (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s",
1208       stream_options[i],reference_filename,output_filename);
1209     arguments=StringToArgv(command,&number_arguments);
1210     if (arguments == (char **) NULL)
1211       {
1212         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1213             GetMagickModule());
1214         (*fail)++;
1215         continue;
1216       }
1217     status=StreamImageCommand(image_info,number_arguments,arguments,
1218       (char **) NULL,exception);
1219     for (j=0; j < (ssize_t) number_arguments; j++)
1220       arguments[j]=DestroyString(arguments[j]);
1221     arguments=(char **) RelinquishMagickMemory(arguments);
1222     if (status != MagickFalse)
1223       {
1224         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1225             GetMagickModule());
1226         (*fail)++;
1227         continue;
1228       }
1229     (void) FormatLocaleFile(stdout,"... pass.\n");
1230   }
1231   (void) FormatLocaleFile(stdout,
1232     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1233     (double) (test-(*fail)),(double) *fail);
1234   return(test);
1235 }
1236 \f
1237 /*
1238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1239 %                                                                             %
1240 %                                                                             %
1241 %                                                                             %
1242 %  M a i n                                                                    %
1243 %                                                                             %
1244 %                                                                             %
1245 %                                                                             %
1246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1247 %
1248 %
1249 */
1250
1251 static MagickBooleanType ValidateUsage(void)
1252 {
1253   const char
1254     **p;
1255
1256   static const char
1257     *miscellaneous[]=
1258     {
1259       "-debug events        display copious debugging information",
1260       "-help                print program options",
1261       "-log format          format of debugging information",
1262       "-validate type       validation type",
1263       "-version             print version information",
1264       (char *) NULL
1265     },
1266     *settings[]=
1267     {
1268       "-regard-warnings     pay attention to warning messages",
1269       "-verbose             print detailed information about the image",
1270       (char *) NULL
1271     };
1272
1273   (void) printf("Version: %s\n",GetMagickVersion((size_t *) NULL));
1274   (void) printf("Copyright: %s\n\n",GetMagickCopyright());
1275   (void) printf("Features: %s\n",GetMagickFeatures());
1276   (void) printf("Usage: %s [options ...] reference-file\n",GetClientName());
1277   (void) printf("\nValidate Settings:\n");
1278   for (p=settings; *p != (char *) NULL; p++)
1279     (void) printf("  %s\n",*p);
1280   (void) printf("\nMiscellaneous Options:\n");
1281   for (p=miscellaneous; *p != (char *) NULL; p++)
1282     (void) printf("  %s\n",*p);
1283   return(MagickTrue);
1284 }
1285
1286 int main(int argc,char **argv)
1287 {
1288 #define DestroyValidate() \
1289 { \
1290   image_info=DestroyImageInfo(image_info); \
1291   exception=DestroyExceptionInfo(exception); \
1292 }
1293 #define ThrowValidateException(asperity,tag,option) \
1294 { \
1295   (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
1296     option); \
1297   CatchException(exception); \
1298   DestroyValidate(); \
1299   return(MagickFalse); \
1300 }
1301
1302   char
1303     output_filename[MaxTextExtent],
1304     reference_filename[MaxTextExtent],
1305     *option;
1306
1307   double
1308     elapsed_time,
1309     user_time;
1310
1311   ExceptionInfo
1312     *exception;
1313
1314   Image
1315     *reference_image;
1316
1317   ImageInfo
1318     *image_info;
1319
1320   MagickBooleanType
1321     regard_warnings,
1322     status;
1323
1324   MagickSizeType
1325     memory_resource,
1326     map_resource;
1327
1328   register ssize_t
1329     i;
1330
1331   TimerInfo
1332     *timer;
1333
1334   size_t
1335     fail,
1336     iterations,
1337     tests;
1338
1339   ValidateType
1340     type;
1341
1342   /*
1343     Validate the ImageMagick image processing suite.
1344   */
1345   MagickCoreGenesis(*argv,MagickFalse);
1346   iterations=1;
1347   status=MagickFalse;
1348   type=AllValidate;
1349   regard_warnings=MagickFalse;
1350   (void) regard_warnings;
1351   exception=AcquireExceptionInfo();
1352   image_info=AcquireImageInfo();
1353   (void) CopyMagickString(image_info->filename,ReferenceFilename,MaxTextExtent);
1354   for (i=1; i < (ssize_t) argc; i++)
1355   {
1356     option=argv[i];
1357     if (IsCommandOption(option) == MagickFalse)
1358       {
1359         (void) CopyMagickString(image_info->filename,option,MaxTextExtent);
1360         continue;
1361       }
1362     switch (*(option+1))
1363     {
1364       case 'b':
1365       {
1366         if (LocaleCompare("bench",option+1) == 0)
1367           {
1368             iterations=StringToUnsignedLong(argv[++i]);
1369             break;
1370           }
1371         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1372       }
1373       case 'd':
1374       {
1375         if (LocaleCompare("debug",option+1) == 0)
1376           {
1377             (void) SetLogEventMask(argv[++i]);
1378             break;
1379           }
1380         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1381       }
1382       case 'h':
1383       {
1384         if (LocaleCompare("help",option+1) == 0)
1385           {
1386             (void) ValidateUsage();
1387             return(0);
1388           }
1389         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1390       }
1391       case 'l':
1392       {
1393         if (LocaleCompare("log",option+1) == 0)
1394           {
1395             if (*option != '+')
1396               (void) SetLogFormat(argv[i+1]);
1397             break;
1398           }
1399         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1400       }
1401       case 'r':
1402       {
1403         if (LocaleCompare("regard-warnings",option+1) == 0)
1404           {
1405             regard_warnings=MagickTrue;
1406             break;
1407           }
1408         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1409       }
1410       case 'v':
1411       {
1412         if (LocaleCompare("validate",option+1) == 0)
1413           {
1414             ssize_t
1415               validate;
1416
1417             if (*option == '+')
1418               break;
1419             i++;
1420             if (i == (ssize_t) argc)
1421               ThrowValidateException(OptionError,"MissingArgument",option);
1422             validate=ParseCommandOption(MagickValidateOptions,MagickFalse,
1423               argv[i]);
1424             if (validate < 0)
1425               ThrowValidateException(OptionError,"UnrecognizedValidateType",
1426                 argv[i]);
1427             type=(ValidateType) validate;
1428             break;
1429           }
1430         if ((LocaleCompare("version",option+1) == 0) ||
1431             (LocaleCompare("-version",option+1) == 0))
1432           {
1433             (void) FormatLocaleFile(stdout,"Version: %s\n",
1434               GetMagickVersion((size_t *) NULL));
1435             (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
1436               GetMagickCopyright());
1437             (void) FormatLocaleFile(stdout,"Features: %s\n\n",
1438               GetMagickFeatures());
1439             return(0);
1440           }
1441         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1442       }
1443       default:
1444         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1445     }
1446   }
1447   timer=(TimerInfo *) NULL;
1448   if (iterations > 1)
1449     timer=AcquireTimerInfo();
1450   reference_image=ReadImage(image_info,exception);
1451   tests=0;
1452   fail=0;
1453   if (reference_image == (Image *) NULL)
1454     fail++;
1455   else
1456     {
1457       if (LocaleCompare(image_info->filename,ReferenceFilename) == 0)
1458         (void) CopyMagickString(reference_image->magick,ReferenceImageFormat,
1459           MaxTextExtent);
1460       (void) AcquireUniqueFilename(reference_filename);
1461       (void) AcquireUniqueFilename(output_filename);
1462       (void) CopyMagickString(reference_image->filename,reference_filename,
1463         MaxTextExtent);
1464       status=WriteImage(image_info,reference_image,exception);
1465       reference_image=DestroyImage(reference_image);
1466       if (status == MagickFalse)
1467         fail++;
1468       else
1469         {
1470           (void) FormatLocaleFile(stdout,"Version: %s\n",
1471             GetMagickVersion((size_t *) NULL));
1472           (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
1473             GetMagickCopyright());
1474           (void) FormatLocaleFile(stdout,
1475             "ImageMagick Validation Suite (%s)\n\n",CommandOptionToMnemonic(
1476             MagickValidateOptions,(ssize_t) type));
1477           if ((type & CompareValidate) != 0)
1478             tests+=ValidateCompareCommand(image_info,reference_filename,
1479               output_filename,&fail,exception);
1480           if ((type & CompositeValidate) != 0)
1481             tests+=ValidateCompositeCommand(image_info,reference_filename,
1482               output_filename,&fail,exception);
1483           if ((type & ConvertValidate) != 0)
1484             tests+=ValidateConvertCommand(image_info,reference_filename,
1485               output_filename,&fail,exception);
1486           if ((type & FormatsInMemoryValidate) != 0)
1487             {
1488               (void) FormatLocaleFile(stdout,"[pixel-cache: memory] ");
1489               tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
1490                 output_filename,&fail,exception);
1491               (void) FormatLocaleFile(stdout,"[pixel-cache: memory-mapped] ");
1492               memory_resource=SetMagickResourceLimit(MemoryResource,0);
1493               tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
1494                 output_filename,&fail,exception);
1495               (void) FormatLocaleFile(stdout,"[pixel-cache: disk] ");
1496               map_resource=SetMagickResourceLimit(MapResource,0);
1497               tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
1498                 output_filename,&fail,exception);
1499               (void) SetMagickResourceLimit(MemoryResource,memory_resource);
1500               (void) SetMagickResourceLimit(MapResource,map_resource);
1501             }
1502           if ((type & FormatsOnDiskValidate) != 0)
1503             {
1504               (void) FormatLocaleFile(stdout,"[pixel-cache: memory] ");
1505               tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
1506                 output_filename,&fail,exception);
1507               (void) FormatLocaleFile(stdout,"[pixel-cache: memory-mapped] ");
1508               memory_resource=SetMagickResourceLimit(MemoryResource,0);
1509               tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
1510                 output_filename,&fail,exception);
1511               (void) FormatLocaleFile(stdout,"[pixel-cache: disk] ");
1512               map_resource=SetMagickResourceLimit(MapResource,0);
1513               tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
1514                 output_filename,&fail,exception);
1515               (void) SetMagickResourceLimit(MemoryResource,memory_resource);
1516               (void) SetMagickResourceLimit(MapResource,map_resource);
1517             }
1518           if ((type & IdentifyValidate) != 0)
1519             tests+=ValidateIdentifyCommand(image_info,reference_filename,
1520               output_filename,&fail,exception);
1521           if ((type & ImportExportValidate) != 0)
1522             tests+=ValidateImportExportPixels(image_info,reference_filename,
1523               output_filename,&fail,exception);
1524           if ((type & MontageValidate) != 0)
1525             tests+=ValidateMontageCommand(image_info,reference_filename,
1526               output_filename,&fail,exception);
1527           if ((type & StreamValidate) != 0)
1528             tests+=ValidateStreamCommand(image_info,reference_filename,
1529               output_filename,&fail,exception);
1530           (void) FormatLocaleFile(stdout,
1531             "validation suite: %.20g tests; %.20g passed; %.20g failed.\n",
1532             (double) tests,(double) (tests-fail),(double) fail);
1533         }
1534       (void) RelinquishUniqueFileResource(output_filename);
1535       (void) RelinquishUniqueFileResource(reference_filename);
1536     }
1537   if (exception->severity != UndefinedException)
1538     CatchException(exception);
1539   if (iterations > 1)
1540     {
1541       elapsed_time=GetElapsedTime(timer);
1542       user_time=GetUserTime(timer);
1543       (void) FormatLocaleFile(stderr,
1544         "Performance: %.20gi %gips %0.3fu %ld:%02ld.%03ld\n",(double)
1545         iterations,1.0*iterations/elapsed_time,user_time,(long)
1546         (elapsed_time/60.0),(long) ceil(fmod(elapsed_time,60.0)),
1547         (long) (1000.0*(elapsed_time-floor(elapsed_time))));
1548       timer=DestroyTimerInfo(timer);
1549     }
1550   DestroyValidate();
1551   MagickCoreTerminus();
1552   return(fail == 0 ? 0 : 1);
1553 }