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