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