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