]> 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       length=strlen(reference_map[i])*reference_image->columns*
946         reference_image->rows*reference_storage[j].quantum;
947       pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
948       if (pixels == (unsigned char *) NULL)
949         {
950           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
951             GetMagickModule());
952           (*fail)++;
953           reference_image=DestroyImage(reference_image);
954           continue;
955         }
956       (void) ResetMagickMemory(pixels,0,length*sizeof(*pixels));
957       status=ExportImagePixels(reference_image,0,0,reference_image->columns,
958         reference_image->rows,reference_map[i],reference_storage[j].type,pixels,
959         exception);
960       if (status == MagickFalse)
961         {
962           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
963             GetMagickModule());
964           (*fail)++;
965           pixels=(unsigned char *) RelinquishMagickMemory(pixels);
966           reference_image=DestroyImage(reference_image);
967           continue;
968         }
969       (void) SetImageBackgroundColor(reference_image);
970       status=ImportImagePixels(reference_image,0,0,reference_image->columns,
971         reference_image->rows,reference_map[i],reference_storage[j].type,
972         pixels,exception);
973       if (status == MagickFalse)
974         {
975           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
976             GetMagickModule());
977           (*fail)++;
978            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
979           reference_image=DestroyImage(reference_image);
980           continue;
981         }
982       /*
983         Read reconstruct image.
984       */
985       reconstruct_image=AcquireImage(image_info,exception);
986       (void) SetImageExtent(reconstruct_image,reference_image->columns,
987         reference_image->rows,exception);
988       (void) SetImageColorspace(reconstruct_image,reference_image->colorspace,
989         exception);
990       (void) SetImageBackgroundColor(reconstruct_image);
991       status=ImportImagePixels(reconstruct_image,0,0,reconstruct_image->columns,
992         reconstruct_image->rows,reference_map[i],reference_storage[j].type,
993         pixels,exception);
994       InheritException(exception,&reconstruct_image->exception);
995       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
996       if (status == MagickFalse)
997         {
998           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
999             GetMagickModule());
1000           (*fail)++;
1001           reference_image=DestroyImage(reference_image);
1002           continue;
1003         }
1004       /*
1005         Compare reference to reconstruct image.
1006       */
1007       difference_image=CompareImages(reference_image,reconstruct_image,
1008         MeanSquaredErrorMetric,&distortion,exception);
1009       reconstruct_image=DestroyImage(reconstruct_image);
1010       reference_image=DestroyImage(reference_image);
1011       if (difference_image == (Image *) NULL)
1012         {
1013           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1014             GetMagickModule());
1015           (*fail)++;
1016           continue;
1017         }
1018       difference_image=DestroyImage(difference_image);
1019       if ((distortion/QuantumRange) > 0.0)
1020         {
1021           (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
1022             distortion/QuantumRange);
1023           (*fail)++;
1024           continue;
1025         }
1026       (void) FormatLocaleFile(stdout,"... pass.\n");
1027     }
1028   }
1029   (void) FormatLocaleFile(stdout,
1030     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1031     (double) (test-(*fail)),(double) *fail);
1032   return(test);
1033 }
1034 \f
1035 /*
1036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037 %                                                                             %
1038 %                                                                             %
1039 %                                                                             %
1040 %   V a l i d a t e M o n t a g e C o m m a n d                               %
1041 %                                                                             %
1042 %                                                                             %
1043 %                                                                             %
1044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1045 %
1046 %  ValidateMontageCommand() validates the ImageMagick montage command line
1047 %  program and returns the number of validation tests that passed and failed.
1048 %
1049 %  The format of the ValidateMontageCommand method is:
1050 %
1051 %      size_t ValidateMontageCommand(ImageInfo *image_info,
1052 %        const char *reference_filename,const char *output_filename,
1053 %        size_t *fail,ExceptionInfo *exception)
1054 %
1055 %  A description of each parameter follows:
1056 %
1057 %    o image_info: the image info.
1058 %
1059 %    o reference_filename: the reference image filename.
1060 %
1061 %    o output_filename: the output image filename.
1062 %
1063 %    o fail: return the number of validation tests that pass.
1064 %
1065 %    o exception: return any errors or warnings in this structure.
1066 %
1067 */
1068 static size_t ValidateMontageCommand(ImageInfo *image_info,
1069   const char *reference_filename,const char *output_filename,
1070   size_t *fail,ExceptionInfo *exception)
1071 {
1072   char
1073     **arguments,
1074     command[MaxTextExtent];
1075
1076   int
1077     number_arguments;
1078
1079   MagickBooleanType
1080     status;
1081
1082   register ssize_t
1083     i,
1084     j;
1085
1086   size_t
1087     test;
1088
1089   test=0;
1090   (void) FormatLocaleFile(stdout,"validate montage command line program:\n");
1091   for (i=0; montage_options[i] != (char *) NULL; i++)
1092   {
1093     CatchException(exception);
1094     (void) FormatLocaleFile(stdout,"  test %.20g: %s",(double) (test++),
1095       montage_options[i]);
1096     (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
1097       reference_filename,montage_options[i],reference_filename,
1098       output_filename);
1099     arguments=StringToArgv(command,&number_arguments);
1100     if (arguments == (char **) NULL)
1101       {
1102         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1103             GetMagickModule());
1104         (*fail)++;
1105         continue;
1106       }
1107     status=MontageImageCommand(image_info,number_arguments,arguments,
1108       (char **) NULL,exception);
1109     for (j=0; j < number_arguments; j++)
1110       arguments[j]=DestroyString(arguments[j]);
1111     arguments=(char **) RelinquishMagickMemory(arguments);
1112     if (status != MagickFalse)
1113       {
1114         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1115             GetMagickModule());
1116         (*fail)++;
1117         continue;
1118       }
1119     (void) FormatLocaleFile(stdout,"... pass.\n");
1120   }
1121   (void) FormatLocaleFile(stdout,
1122     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1123     (double) (test-(*fail)),(double) *fail);
1124   return(test);
1125 }
1126 \f
1127 /*
1128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1129 %                                                                             %
1130 %                                                                             %
1131 %                                                                             %
1132 %   V a l i d a t e S t r e a m C o m m a n d                                 %
1133 %                                                                             %
1134 %                                                                             %
1135 %                                                                             %
1136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1137 %
1138 %  ValidateStreamCommand() validates the ImageMagick stream command line
1139 %  program and returns the number of validation tests that passed and failed.
1140 %
1141 %  The format of the ValidateStreamCommand method is:
1142 %
1143 %      size_t ValidateStreamCommand(ImageInfo *image_info,
1144 %        const char *reference_filename,const char *output_filename,
1145 %        size_t *fail,ExceptionInfo *exception)
1146 %
1147 %  A description of each parameter follows:
1148 %
1149 %    o image_info: the image info.
1150 %
1151 %    o reference_filename: the reference image filename.
1152 %
1153 %    o output_filename: the output image filename.
1154 %
1155 %    o fail: return the number of validation tests that pass.
1156 %
1157 %    o exception: return any errors or warnings in this structure.
1158 %
1159 */
1160 static size_t ValidateStreamCommand(ImageInfo *image_info,
1161   const char *reference_filename,const char *output_filename,
1162   size_t *fail,ExceptionInfo *exception)
1163 {
1164   char
1165     **arguments,
1166     command[MaxTextExtent];
1167
1168   int
1169     number_arguments;
1170
1171   MagickBooleanType
1172     status;
1173
1174   register ssize_t
1175     i,
1176     j;
1177
1178   size_t
1179     test;
1180
1181   test=0;
1182   (void) FormatLocaleFile(stdout,"validate stream command line program:\n");
1183   for (i=0; stream_options[i] != (char *) NULL; i++)
1184   {
1185     CatchException(exception);
1186     (void) FormatLocaleFile(stdout,"  test %.20g: %s",(double) (test++),
1187       stream_options[i]);
1188     (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s",
1189       stream_options[i],reference_filename,output_filename);
1190     arguments=StringToArgv(command,&number_arguments);
1191     if (arguments == (char **) NULL)
1192       {
1193         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1194             GetMagickModule());
1195         (*fail)++;
1196         continue;
1197       }
1198     status=StreamImageCommand(image_info,number_arguments,arguments,
1199       (char **) NULL,exception);
1200     for (j=0; j < number_arguments; j++)
1201       arguments[j]=DestroyString(arguments[j]);
1202     arguments=(char **) RelinquishMagickMemory(arguments);
1203     if (status != MagickFalse)
1204       {
1205         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1206             GetMagickModule());
1207         (*fail)++;
1208         continue;
1209       }
1210     (void) FormatLocaleFile(stdout,"... pass.\n");
1211   }
1212   (void) FormatLocaleFile(stdout,
1213     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1214     (double) (test-(*fail)),(double) *fail);
1215   return(test);
1216 }
1217 \f
1218 /*
1219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220 %                                                                             %
1221 %                                                                             %
1222 %                                                                             %
1223 %  M a i n                                                                    %
1224 %                                                                             %
1225 %                                                                             %
1226 %                                                                             %
1227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1228 %
1229 %
1230 */
1231
1232 static MagickBooleanType ValidateUsage(void)
1233 {
1234   const char
1235     **p;
1236
1237   static const char
1238     *miscellaneous[]=
1239     {
1240       "-debug events        display copious debugging information",
1241       "-help                print program options",
1242       "-log format          format of debugging information",
1243       "-validate type       validation type",
1244       "-version             print version information",
1245       (char *) NULL
1246     },
1247     *settings[]=
1248     {
1249       "-regard-warnings     pay attention to warning messages",
1250       "-verbose             print detailed information about the image",
1251       (char *) NULL
1252     };
1253
1254   (void) printf("Version: %s\n",GetMagickVersion((size_t *) NULL));
1255   (void) printf("Copyright: %s\n\n",GetMagickCopyright());
1256   (void) printf("Features: %s\n",GetMagickFeatures());
1257   (void) printf("Usage: %s [options ...] reference-file\n",GetClientName());
1258   (void) printf("\nValidate Settings:\n");
1259   for (p=settings; *p != (char *) NULL; p++)
1260     (void) printf("  %s\n",*p);
1261   (void) printf("\nMiscellaneous Options:\n");
1262   for (p=miscellaneous; *p != (char *) NULL; p++)
1263     (void) printf("  %s\n",*p);
1264   return(MagickTrue);
1265 }
1266
1267 int main(int argc,char **argv)
1268 {
1269 #define DestroyValidate() \
1270 { \
1271   image_info=DestroyImageInfo(image_info); \
1272   exception=DestroyExceptionInfo(exception); \
1273 }
1274 #define ThrowValidateException(asperity,tag,option) \
1275 { \
1276   (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
1277     option); \
1278   CatchException(exception); \
1279   DestroyValidate(); \
1280   return(MagickFalse); \
1281 }
1282
1283   char
1284     output_filename[MaxTextExtent],
1285     reference_filename[MaxTextExtent],
1286     *option;
1287
1288   double
1289     elapsed_time,
1290     user_time;
1291
1292   ExceptionInfo
1293     *exception;
1294
1295   Image
1296     *reference_image;
1297
1298   ImageInfo
1299     *image_info;
1300
1301   MagickBooleanType
1302     regard_warnings,
1303     status;
1304
1305   register ssize_t
1306     i;
1307
1308   TimerInfo
1309     *timer;
1310
1311   size_t
1312     fail,
1313     iterations,
1314     tests;
1315
1316   ValidateType
1317     type;
1318
1319   /*
1320     Validate the ImageMagick image processing suite.
1321   */
1322   MagickCoreGenesis(*argv,MagickFalse);
1323   iterations=1;
1324   status=MagickFalse;
1325   type=AllValidate;
1326   regard_warnings=MagickFalse;
1327   (void) regard_warnings;
1328   exception=AcquireExceptionInfo();
1329   image_info=AcquireImageInfo();
1330   (void) CopyMagickString(image_info->filename,ReferenceFilename,MaxTextExtent);
1331   for (i=1; i < (ssize_t) argc; i++)
1332   {
1333     option=argv[i];
1334     if (IsCommandOption(option) == MagickFalse)
1335       {
1336         (void) CopyMagickString(image_info->filename,option,MaxTextExtent);
1337         continue;
1338       }
1339     switch (*(option+1))
1340     {
1341       case 'b':
1342       {
1343         if (LocaleCompare("bench",option+1) == 0)
1344           {
1345             iterations=StringToUnsignedLong(argv[++i]);
1346             break;
1347           }
1348         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1349       }
1350       case 'd':
1351       {
1352         if (LocaleCompare("debug",option+1) == 0)
1353           {
1354             (void) SetLogEventMask(argv[++i]);
1355             break;
1356           }
1357         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1358       }
1359       case 'h':
1360       {
1361         if (LocaleCompare("help",option+1) == 0)
1362           {
1363             (void) ValidateUsage();
1364             return(0);
1365           }
1366         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1367       }
1368       case 'l':
1369       {
1370         if (LocaleCompare("log",option+1) == 0)
1371           {
1372             if (*option != '+')
1373               (void) SetLogFormat(argv[i+1]);
1374             break;
1375           }
1376         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1377       }
1378       case 'r':
1379       {
1380         if (LocaleCompare("regard-warnings",option+1) == 0)
1381           {
1382             regard_warnings=MagickTrue;
1383             break;
1384           }
1385         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1386       }
1387       case 'v':
1388       {
1389         if (LocaleCompare("validate",option+1) == 0)
1390           {
1391             ssize_t
1392               validate;
1393
1394             if (*option == '+')
1395               break;
1396             i++;
1397             if (i == (ssize_t) argc)
1398               ThrowValidateException(OptionError,"MissingArgument",option);
1399             validate=ParseCommandOption(MagickValidateOptions,MagickFalse,
1400               argv[i]);
1401             if (validate < 0)
1402               ThrowValidateException(OptionError,"UnrecognizedValidateType",
1403                 argv[i]);
1404             type=(ValidateType) validate;
1405             break;
1406           }
1407         if ((LocaleCompare("version",option+1) == 0) ||
1408             (LocaleCompare("-version",option+1) == 0))
1409           {
1410             (void) FormatLocaleFile(stdout,"Version: %s\n",
1411               GetMagickVersion((size_t *) NULL));
1412             (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
1413               GetMagickCopyright());
1414             (void) FormatLocaleFile(stdout,"Features: %s\n\n",
1415               GetMagickFeatures());
1416             return(0);
1417           }
1418         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1419       }
1420       default:
1421         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1422     }
1423   }
1424   timer=(TimerInfo *) NULL;
1425   if (iterations > 1)
1426     timer=AcquireTimerInfo();
1427   reference_image=ReadImage(image_info,exception);
1428   tests=0;
1429   fail=0;
1430   if (reference_image == (Image *) NULL)
1431     fail++;
1432   else
1433     {
1434       if (LocaleCompare(image_info->filename,ReferenceFilename) == 0)
1435         (void) CopyMagickString(reference_image->magick,ReferenceImageFormat,
1436           MaxTextExtent);
1437       (void) AcquireUniqueFilename(reference_filename);
1438       (void) AcquireUniqueFilename(output_filename);
1439       (void) CopyMagickString(reference_image->filename,reference_filename,
1440         MaxTextExtent);
1441       status=WriteImage(image_info,reference_image,exception);
1442       reference_image=DestroyImage(reference_image);
1443       if (status == MagickFalse)
1444         fail++;
1445       else
1446         {
1447           (void) FormatLocaleFile(stdout,"Version: %s\n",
1448             GetMagickVersion((size_t *) NULL));
1449           (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
1450             GetMagickCopyright());
1451           (void) FormatLocaleFile(stdout,
1452             "ImageMagick Validation Suite (%s)\n\n",CommandOptionToMnemonic(
1453             MagickValidateOptions,(ssize_t) type));
1454           if ((type & CompareValidate) != 0)
1455             tests+=ValidateCompareCommand(image_info,reference_filename,
1456               output_filename,&fail,exception);
1457           if ((type & CompositeValidate) != 0)
1458             tests+=ValidateCompositeCommand(image_info,reference_filename,
1459               output_filename,&fail,exception);
1460           if ((type & ConvertValidate) != 0)
1461             tests+=ValidateConvertCommand(image_info,reference_filename,
1462               output_filename,&fail,exception);
1463           if ((type & FormatsInMemoryValidate) != 0)
1464             tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
1465               output_filename,&fail,exception);
1466           if ((type & FormatsOnDiskValidate) != 0)
1467             tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
1468               output_filename,&fail,exception);
1469           if ((type & IdentifyValidate) != 0)
1470             tests+=ValidateIdentifyCommand(image_info,reference_filename,
1471               output_filename,&fail,exception);
1472           if ((type & ImportExportValidate) != 0)
1473             tests+=ValidateImportExportPixels(image_info,reference_filename,
1474               output_filename,&fail,exception);
1475           if ((type & MontageValidate) != 0)
1476             tests+=ValidateMontageCommand(image_info,reference_filename,
1477               output_filename,&fail,exception);
1478           if ((type & StreamValidate) != 0)
1479             tests+=ValidateStreamCommand(image_info,reference_filename,
1480               output_filename,&fail,exception);
1481           (void) FormatLocaleFile(stdout,
1482             "validation suite: %.20g tests; %.20g passed; %.20g failed.\n",
1483             (double) tests,(double) (tests-fail),(double) fail);
1484         }
1485       (void) RelinquishUniqueFileResource(output_filename);
1486       (void) RelinquishUniqueFileResource(reference_filename);
1487     }
1488   if (exception->severity != UndefinedException)
1489     CatchException(exception);
1490   if (iterations > 1)
1491     {
1492       elapsed_time=GetElapsedTime(timer);
1493       user_time=GetUserTime(timer);
1494       (void) FormatLocaleFile(stderr,
1495         "Performance: %.20gi %gips %0.3fu %ld:%02ld.%03ld\n",(double)
1496         iterations,1.0*iterations/elapsed_time,user_time,(long)
1497         (elapsed_time/60.0),(long) ceil(fmod(elapsed_time,60.0)),
1498         (long) (1000.0*(elapsed_time-floor(elapsed_time))));
1499       timer=DestroyTimerInfo(timer);
1500     }
1501   DestroyValidate();
1502   MagickCoreTerminus();
1503   return(fail == 0 ? 0 : 1);
1504 }