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