]> 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);
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);
548       InheritException(exception,&reference_image->exception);
549       reference_image=DestroyImage(reference_image);
550       if (status == MagickFalse)
551         {
552           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
553             GetMagickModule());
554           (*fail)++;
555           continue;
556         }
557       /*
558         Read reference image.
559       */
560       (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
561         reference_formats[i].magick,output_filename);
562       reference_image=ReadImage(image_info,exception);
563       if (reference_image == (Image *) NULL)
564         {
565           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
566             GetMagickModule());
567           (*fail)++;
568           continue;
569         }
570       /*
571         Write reference image.
572       */
573       (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
574         reference_formats[i].magick,output_filename);
575       (void) CopyMagickString(image_info->magick,reference_formats[i].magick,
576         MaxTextExtent);
577       reference_image->depth=reference_types[j].depth;
578       reference_image->compression=reference_formats[i].compression;
579       length=8192;
580       blob=ImageToBlob(image_info,reference_image,&length,exception);
581       if (blob == (unsigned char *) NULL)
582         {
583           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
584             GetMagickModule());
585           (*fail)++;
586           reference_image=DestroyImage(reference_image);
587           continue;
588         }
589       /*
590         Read reconstruct image.
591       */
592       (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
593         reference_formats[i].magick,output_filename);
594       reconstruct_image=BlobToImage(image_info,blob,length,exception);
595       blob=(unsigned char *) RelinquishMagickMemory(blob);
596       if (reconstruct_image == (Image *) NULL)
597         {
598           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
599             GetMagickModule());
600           (*fail)++;
601           reference_image=DestroyImage(reference_image);
602           continue;
603         }
604       /*
605         Compare reference to reconstruct image.
606       */
607       fuzz=0.0;
608       if (reference_formats[i].fuzz != 0.0)
609         fuzz=reference_formats[i].fuzz;
610 #if defined(MAGICKCORE_HDRI_SUPPORT)
611       fuzz+=0.003;
612 #endif
613       if (IsRGBColorspace(reference_image->colorspace) == MagickFalse)
614         fuzz+=0.3;
615       fuzz+=MagickEpsilon;
616       difference_image=CompareImages(reference_image,reconstruct_image,
617         MeanSquaredErrorMetric,&distortion,exception);
618       reconstruct_image=DestroyImage(reconstruct_image);
619       reference_image=DestroyImage(reference_image);
620       if (difference_image == (Image *) NULL)
621         {
622           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
623             GetMagickModule());
624           (*fail)++;
625           continue;
626         }
627       difference_image=DestroyImage(difference_image);
628       if ((distortion/QuantumRange) > fuzz)
629         {
630           (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
631             distortion/QuantumRange);
632           (*fail)++;
633           continue;
634         }
635       (void) FormatLocaleFile(stdout,"... pass.\n");
636     }
637   }
638   (void) FormatLocaleFile(stdout,
639     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
640     (double) (test-(*fail)),(double) *fail);
641   return(test);
642 }
643 \f
644 /*
645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646 %                                                                             %
647 %                                                                             %
648 %                                                                             %
649 %   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                       %
650 %                                                                             %
651 %                                                                             %
652 %                                                                             %
653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654 %
655 %  ValidateImageFormatsOnDisk() validates the ImageMagick image formats on disk
656 %  and returns the number of validation tests that passed and failed.
657 %
658 %  The format of the ValidateImageFormatsOnDisk method is:
659 %
660 %      size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
661 %        const char *reference_filename,const char *output_filename,
662 %        size_t *fail,ExceptionInfo *exception)
663 %
664 %  A description of each parameter follows:
665 %
666 %    o image_info: the image info.
667 %
668 %    o reference_filename: the reference image filename.
669 %
670 %    o output_filename: the output image filename.
671 %
672 %    o fail: return the number of validation tests that pass.
673 %
674 %    o exception: return any errors or warnings in this structure.
675 %
676 */
677 static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
678   const char *reference_filename,const char *output_filename,
679   size_t *fail,ExceptionInfo *exception)
680 {
681   char
682     size[MaxTextExtent];
683
684   const MagickInfo
685     *magick_info;
686
687   double
688     distortion,
689     fuzz;
690
691   Image
692     *difference_image,
693     *reference_image,
694     *reconstruct_image;
695
696   MagickBooleanType
697     status;
698
699   register ssize_t
700     i,
701     j;
702
703   size_t
704     test;
705
706   test=0;
707   (void) FormatLocaleFile(stdout,"validate image formats on disk:\n");
708   for (i=0; reference_formats[i].magick != (char *) NULL; i++)
709   {
710     magick_info=GetMagickInfo(reference_formats[i].magick,exception);
711     if ((magick_info == (const MagickInfo *) NULL) ||
712         (magick_info->decoder == (DecodeImageHandler *) NULL) ||
713         (magick_info->encoder == (EncodeImageHandler *) NULL))
714       continue;
715     for (j=0; reference_types[j].type != UndefinedType; j++)
716     {
717       /*
718         Generate reference image.
719       */
720       CatchException(exception);
721       (void) FormatLocaleFile(stdout,"  test %.20g: %s/%s/%s/%.20g-bits",
722         (double) (test++),reference_formats[i].magick,CommandOptionToMnemonic(
723         MagickCompressOptions,reference_formats[i].compression),
724         CommandOptionToMnemonic(MagickTypeOptions,reference_types[j].type),
725         (double) reference_types[j].depth);
726       (void) CopyMagickString(image_info->filename,reference_filename,
727         MaxTextExtent);
728       reference_image=ReadImage(image_info,exception);
729       if (reference_image == (Image *) NULL)
730         {
731           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
732             GetMagickModule());
733           (*fail)++;
734           continue;
735         }
736       /*
737         Write reference image.
738       */
739       (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",
740         (double) reference_image->columns,(double) reference_image->rows);
741       (void) CloneString(&image_info->size,size);
742       image_info->depth=reference_types[j].depth;
743       (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
744         reference_formats[i].magick,output_filename);
745       status=SetImageType(reference_image,reference_types[j].type);
746       InheritException(exception,&reference_image->exception);
747       if (status == MagickFalse)
748         {
749           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
750             GetMagickModule());
751           (*fail)++;
752           reference_image=DestroyImage(reference_image);
753           continue;
754         }
755       status=SetImageDepth(reference_image,reference_types[j].depth);
756       InheritException(exception,&reference_image->exception);
757       if (status == MagickFalse)
758         {
759           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
760             GetMagickModule());
761           (*fail)++;
762           reference_image=DestroyImage(reference_image);
763           continue;
764         }
765       reference_image->compression=reference_formats[i].compression;
766       status=WriteImage(image_info,reference_image);
767       InheritException(exception,&reference_image->exception);
768       reference_image=DestroyImage(reference_image);
769       if (status == MagickFalse)
770         {
771           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
772             GetMagickModule());
773           (*fail)++;
774           continue;
775         }
776       /*
777         Read reference image.
778       */
779       (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
780         reference_formats[i].magick,output_filename);
781       reference_image=ReadImage(image_info,exception);
782       if (reference_image == (Image *) NULL)
783         {
784           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
785             GetMagickModule());
786           (*fail)++;
787           continue;
788         }
789       /*
790         Write reference image.
791       */
792       (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
793         reference_formats[i].magick,output_filename);
794       reference_image->depth=reference_types[j].depth;
795       reference_image->compression=reference_formats[i].compression;
796       status=WriteImage(image_info,reference_image);
797       InheritException(exception,&reference_image->exception);
798       if (status == MagickFalse)
799         {
800           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
801             GetMagickModule());
802           (*fail)++;
803           reference_image=DestroyImage(reference_image);
804           continue;
805         }
806       /*
807         Read reconstruct image.
808       */
809       (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
810         reference_formats[i].magick,output_filename);
811       reconstruct_image=ReadImage(image_info,exception);
812       if (reconstruct_image == (Image *) NULL)
813         {
814           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
815             GetMagickModule());
816           (*fail)++;
817           reference_image=DestroyImage(reference_image);
818           continue;
819         }
820       /*
821         Compare reference to reconstruct image.
822       */
823       fuzz=0.0;
824       if (reference_formats[i].fuzz != 0.0)
825         fuzz=reference_formats[i].fuzz;
826 #if defined(MAGICKCORE_HDRI_SUPPORT)
827       fuzz+=0.003;
828 #endif
829       if (IsRGBColorspace(reference_image->colorspace) == MagickFalse)
830         fuzz+=0.3;
831       fuzz+=MagickEpsilon;
832       difference_image=CompareImages(reference_image,reconstruct_image,
833         MeanSquaredErrorMetric,&distortion,exception);
834       reconstruct_image=DestroyImage(reconstruct_image);
835       reference_image=DestroyImage(reference_image);
836       if (difference_image == (Image *) NULL)
837         {
838           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
839             GetMagickModule());
840           (*fail)++;
841           continue;
842         }
843       difference_image=DestroyImage(difference_image);
844       if ((distortion/QuantumRange) > fuzz)
845         {
846           (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
847             distortion/QuantumRange);
848           (*fail)++;
849           continue;
850         }
851       (void) FormatLocaleFile(stdout,"... pass.\n");
852     }
853   }
854   (void) FormatLocaleFile(stdout,
855     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
856     (double) (test-(*fail)),(double) *fail);
857   return(test);
858 }
859 \f
860 /*
861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
862 %                                                                             %
863 %                                                                             %
864 %                                                                             %
865 %   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                       %
866 %                                                                             %
867 %                                                                             %
868 %                                                                             %
869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
870 %
871 %  ValidateImportExportPixels() validates the pixel import and export methods.
872 %  It returns the number of validation tests that passed and failed.
873 %
874 %  The format of the ValidateImportExportPixels method is:
875 %
876 %      size_t ValidateImportExportPixels(ImageInfo *image_info,
877 %        const char *reference_filename,const char *output_filename,
878 %        size_t *fail,ExceptionInfo *exception)
879 %
880 %  A description of each parameter follows:
881 %
882 %    o image_info: the image info.
883 %
884 %    o reference_filename: the reference image filename.
885 %
886 %    o output_filename: the output image filename.
887 %
888 %    o fail: return the number of validation tests that pass.
889 %
890 %    o exception: return any errors or warnings in this structure.
891 %
892 */
893 static size_t ValidateImportExportPixels(ImageInfo *image_info,
894   const char *reference_filename,const char *output_filename,
895   size_t *fail,ExceptionInfo *exception)
896 {
897   double
898     distortion;
899
900   Image
901     *difference_image,
902     *reference_image,
903     *reconstruct_image;
904
905   MagickBooleanType
906     status;
907
908   register ssize_t
909     i,
910     j;
911
912   size_t
913     length;
914
915   unsigned char
916     *pixels;
917
918   size_t
919     test;
920
921   (void) output_filename;
922   test=0;
923   (void) FormatLocaleFile(stdout,
924     "validate the import and export of image pixels:\n");
925   for (i=0; reference_map[i] != (char *) NULL; i++)
926   {
927     for (j=0; reference_storage[j].type != UndefinedPixel; j++)
928     {
929       /*
930         Generate reference image.
931       */
932       CatchException(exception);
933       (void) FormatLocaleFile(stdout,"  test %.20g: %s/%s",(double) (test++),
934         reference_map[i],CommandOptionToMnemonic(MagickStorageOptions,
935         reference_storage[j].type));
936       (void) CopyMagickString(image_info->filename,reference_filename,
937         MaxTextExtent);
938       reference_image=ReadImage(image_info,exception);
939       if (reference_image == (Image *) NULL)
940         {
941           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
942             GetMagickModule());
943           (*fail)++;
944           continue;
945         }
946       if (LocaleNCompare(reference_map[i],"cmy",3) == 0)
947         (void) TransformImageColorspace(reference_image,CMYKColorspace);
948       length=strlen(reference_map[i])*reference_image->columns*
949         reference_image->rows*reference_storage[j].quantum;
950       pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
951       if (pixels == (unsigned char *) NULL)
952         {
953           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
954             GetMagickModule());
955           (*fail)++;
956           reference_image=DestroyImage(reference_image);
957           continue;
958         }
959       (void) ResetMagickMemory(pixels,0,length*sizeof(*pixels));
960       status=ExportImagePixels(reference_image,0,0,reference_image->columns,
961         reference_image->rows,reference_map[i],reference_storage[j].type,pixels,
962         exception);
963       if (status == MagickFalse)
964         {
965           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
966             GetMagickModule());
967           (*fail)++;
968           pixels=(unsigned char *) RelinquishMagickMemory(pixels);
969           reference_image=DestroyImage(reference_image);
970           continue;
971         }
972       (void) SetImageBackgroundColor(reference_image);
973       status=ImportImagePixels(reference_image,0,0,reference_image->columns,
974         reference_image->rows,reference_map[i],reference_storage[j].type,
975         pixels);
976       InheritException(exception,&reference_image->exception);
977       if (status == MagickFalse)
978         {
979           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
980             GetMagickModule());
981           (*fail)++;
982            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
983           reference_image=DestroyImage(reference_image);
984           continue;
985         }
986       /*
987         Read reconstruct image.
988       */
989       reconstruct_image=AcquireImage(image_info);
990       (void) SetImageExtent(reconstruct_image,reference_image->columns,
991         reference_image->rows);
992       (void) SetImageColorspace(reconstruct_image,reference_image->colorspace);
993       (void) SetImageBackgroundColor(reconstruct_image);
994       status=ImportImagePixels(reconstruct_image,0,0,reconstruct_image->columns,
995         reconstruct_image->rows,reference_map[i],reference_storage[j].type,
996         pixels);
997       InheritException(exception,&reconstruct_image->exception);
998       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
999       if (status == MagickFalse)
1000         {
1001           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1002             GetMagickModule());
1003           (*fail)++;
1004           reference_image=DestroyImage(reference_image);
1005           continue;
1006         }
1007       /*
1008         Compare reference to reconstruct image.
1009       */
1010       difference_image=CompareImages(reference_image,reconstruct_image,
1011         MeanSquaredErrorMetric,&distortion,exception);
1012       reconstruct_image=DestroyImage(reconstruct_image);
1013       reference_image=DestroyImage(reference_image);
1014       if (difference_image == (Image *) NULL)
1015         {
1016           (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1017             GetMagickModule());
1018           (*fail)++;
1019           continue;
1020         }
1021       difference_image=DestroyImage(difference_image);
1022       if ((distortion/QuantumRange) > 0.0)
1023         {
1024           (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
1025             distortion/QuantumRange);
1026           (*fail)++;
1027           continue;
1028         }
1029       (void) FormatLocaleFile(stdout,"... pass.\n");
1030     }
1031   }
1032   (void) FormatLocaleFile(stdout,
1033     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1034     (double) (test-(*fail)),(double) *fail);
1035   return(test);
1036 }
1037 \f
1038 /*
1039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1040 %                                                                             %
1041 %                                                                             %
1042 %                                                                             %
1043 %   V a l i d a t e M o n t a g e C o m m a n d                               %
1044 %                                                                             %
1045 %                                                                             %
1046 %                                                                             %
1047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1048 %
1049 %  ValidateMontageCommand() validates the ImageMagick montage command line
1050 %  program and returns the number of validation tests that passed and failed.
1051 %
1052 %  The format of the ValidateMontageCommand method is:
1053 %
1054 %      size_t ValidateMontageCommand(ImageInfo *image_info,
1055 %        const char *reference_filename,const char *output_filename,
1056 %        size_t *fail,ExceptionInfo *exception)
1057 %
1058 %  A description of each parameter follows:
1059 %
1060 %    o image_info: the image info.
1061 %
1062 %    o reference_filename: the reference image filename.
1063 %
1064 %    o output_filename: the output image filename.
1065 %
1066 %    o fail: return the number of validation tests that pass.
1067 %
1068 %    o exception: return any errors or warnings in this structure.
1069 %
1070 */
1071 static size_t ValidateMontageCommand(ImageInfo *image_info,
1072   const char *reference_filename,const char *output_filename,
1073   size_t *fail,ExceptionInfo *exception)
1074 {
1075   char
1076     **arguments,
1077     command[MaxTextExtent];
1078
1079   int
1080     number_arguments;
1081
1082   MagickBooleanType
1083     status;
1084
1085   register ssize_t
1086     i,
1087     j;
1088
1089   size_t
1090     test;
1091
1092   test=0;
1093   (void) FormatLocaleFile(stdout,"validate montage command line program:\n");
1094   for (i=0; montage_options[i] != (char *) NULL; i++)
1095   {
1096     CatchException(exception);
1097     (void) FormatLocaleFile(stdout,"  test %.20g: %s",(double) (test++),
1098       montage_options[i]);
1099     (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
1100       reference_filename,montage_options[i],reference_filename,
1101       output_filename);
1102     arguments=StringToArgv(command,&number_arguments);
1103     if (arguments == (char **) NULL)
1104       {
1105         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1106             GetMagickModule());
1107         (*fail)++;
1108         continue;
1109       }
1110     status=MontageImageCommand(image_info,number_arguments,arguments,
1111       (char **) NULL,exception);
1112     for (j=0; j < number_arguments; j++)
1113       arguments[j]=DestroyString(arguments[j]);
1114     arguments=(char **) RelinquishMagickMemory(arguments);
1115     if (status != MagickFalse)
1116       {
1117         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1118             GetMagickModule());
1119         (*fail)++;
1120         continue;
1121       }
1122     (void) FormatLocaleFile(stdout,"... pass.\n");
1123   }
1124   (void) FormatLocaleFile(stdout,
1125     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1126     (double) (test-(*fail)),(double) *fail);
1127   return(test);
1128 }
1129 \f
1130 /*
1131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1132 %                                                                             %
1133 %                                                                             %
1134 %                                                                             %
1135 %   V a l i d a t e S t r e a m C o m m a n d                                 %
1136 %                                                                             %
1137 %                                                                             %
1138 %                                                                             %
1139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1140 %
1141 %  ValidateStreamCommand() validates the ImageMagick stream command line
1142 %  program and returns the number of validation tests that passed and failed.
1143 %
1144 %  The format of the ValidateStreamCommand method is:
1145 %
1146 %      size_t ValidateStreamCommand(ImageInfo *image_info,
1147 %        const char *reference_filename,const char *output_filename,
1148 %        size_t *fail,ExceptionInfo *exception)
1149 %
1150 %  A description of each parameter follows:
1151 %
1152 %    o image_info: the image info.
1153 %
1154 %    o reference_filename: the reference image filename.
1155 %
1156 %    o output_filename: the output image filename.
1157 %
1158 %    o fail: return the number of validation tests that pass.
1159 %
1160 %    o exception: return any errors or warnings in this structure.
1161 %
1162 */
1163 static size_t ValidateStreamCommand(ImageInfo *image_info,
1164   const char *reference_filename,const char *output_filename,
1165   size_t *fail,ExceptionInfo *exception)
1166 {
1167   char
1168     **arguments,
1169     command[MaxTextExtent];
1170
1171   int
1172     number_arguments;
1173
1174   MagickBooleanType
1175     status;
1176
1177   register ssize_t
1178     i,
1179     j;
1180
1181   size_t
1182     test;
1183
1184   test=0;
1185   (void) FormatLocaleFile(stdout,"validate stream command line program:\n");
1186   for (i=0; stream_options[i] != (char *) NULL; i++)
1187   {
1188     CatchException(exception);
1189     (void) FormatLocaleFile(stdout,"  test %.20g: %s",(double) (test++),
1190       stream_options[i]);
1191     (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s",
1192       stream_options[i],reference_filename,output_filename);
1193     arguments=StringToArgv(command,&number_arguments);
1194     if (arguments == (char **) NULL)
1195       {
1196         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1197             GetMagickModule());
1198         (*fail)++;
1199         continue;
1200       }
1201     status=StreamImageCommand(image_info,number_arguments,arguments,
1202       (char **) NULL,exception);
1203     for (j=0; j < number_arguments; j++)
1204       arguments[j]=DestroyString(arguments[j]);
1205     arguments=(char **) RelinquishMagickMemory(arguments);
1206     if (status != MagickFalse)
1207       {
1208         (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1209             GetMagickModule());
1210         (*fail)++;
1211         continue;
1212       }
1213     (void) FormatLocaleFile(stdout,"... pass.\n");
1214   }
1215   (void) FormatLocaleFile(stdout,
1216     "  summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1217     (double) (test-(*fail)),(double) *fail);
1218   return(test);
1219 }
1220 \f
1221 /*
1222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1223 %                                                                             %
1224 %                                                                             %
1225 %                                                                             %
1226 %  M a i n                                                                    %
1227 %                                                                             %
1228 %                                                                             %
1229 %                                                                             %
1230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1231 %
1232 %
1233 */
1234
1235 static MagickBooleanType ValidateUsage(void)
1236 {
1237   const char
1238     **p;
1239
1240   static const char
1241     *miscellaneous[]=
1242     {
1243       "-debug events        display copious debugging information",
1244       "-help                print program options",
1245       "-log format          format of debugging information",
1246       "-validate type       validation type",
1247       "-version             print version information",
1248       (char *) NULL
1249     },
1250     *settings[]=
1251     {
1252       "-regard-warnings     pay attention to warning messages",
1253       "-verbose             print detailed information about the image",
1254       (char *) NULL
1255     };
1256
1257   (void) printf("Version: %s\n",GetMagickVersion((size_t *) NULL));
1258   (void) printf("Copyright: %s\n\n",GetMagickCopyright());
1259   (void) printf("Features: %s\n",GetMagickFeatures());
1260   (void) printf("Usage: %s [options ...] reference-file\n",GetClientName());
1261   (void) printf("\nValidate Settings:\n");
1262   for (p=settings; *p != (char *) NULL; p++)
1263     (void) printf("  %s\n",*p);
1264   (void) printf("\nMiscellaneous Options:\n");
1265   for (p=miscellaneous; *p != (char *) NULL; p++)
1266     (void) printf("  %s\n",*p);
1267   return(MagickTrue);
1268 }
1269
1270 int main(int argc,char **argv)
1271 {
1272 #define DestroyValidate() \
1273 { \
1274   image_info=DestroyImageInfo(image_info); \
1275   exception=DestroyExceptionInfo(exception); \
1276 }
1277 #define ThrowValidateException(asperity,tag,option) \
1278 { \
1279   (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
1280     option); \
1281   CatchException(exception); \
1282   DestroyValidate(); \
1283   return(MagickFalse); \
1284 }
1285
1286   char
1287     output_filename[MaxTextExtent],
1288     reference_filename[MaxTextExtent],
1289     *option;
1290
1291   double
1292     elapsed_time,
1293     user_time;
1294
1295   ExceptionInfo
1296     *exception;
1297
1298   Image
1299     *reference_image;
1300
1301   ImageInfo
1302     *image_info;
1303
1304   MagickBooleanType
1305     regard_warnings,
1306     status;
1307
1308   register ssize_t
1309     i;
1310
1311   TimerInfo
1312     *timer;
1313
1314   size_t
1315     fail,
1316     iterations,
1317     tests;
1318
1319   ValidateType
1320     type;
1321
1322   /*
1323     Validate the ImageMagick image processing suite.
1324   */
1325   MagickCoreGenesis(*argv,MagickFalse);
1326   iterations=1;
1327   status=MagickFalse;
1328   type=AllValidate;
1329   regard_warnings=MagickFalse;
1330   (void) regard_warnings;
1331   exception=AcquireExceptionInfo();
1332   image_info=AcquireImageInfo();
1333   (void) CopyMagickString(image_info->filename,ReferenceFilename,MaxTextExtent);
1334   for (i=1; i < (ssize_t) argc; i++)
1335   {
1336     option=argv[i];
1337     if (IsCommandOption(option) == MagickFalse)
1338       {
1339         (void) CopyMagickString(image_info->filename,option,MaxTextExtent);
1340         continue;
1341       }
1342     switch (*(option+1))
1343     {
1344       case 'b':
1345       {
1346         if (LocaleCompare("bench",option+1) == 0)
1347           {
1348             iterations=StringToUnsignedLong(argv[++i]);
1349             break;
1350           }
1351         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1352       }
1353       case 'd':
1354       {
1355         if (LocaleCompare("debug",option+1) == 0)
1356           {
1357             (void) SetLogEventMask(argv[++i]);
1358             break;
1359           }
1360         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1361       }
1362       case 'h':
1363       {
1364         if (LocaleCompare("help",option+1) == 0)
1365           {
1366             (void) ValidateUsage();
1367             return(0);
1368           }
1369         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1370       }
1371       case 'l':
1372       {
1373         if (LocaleCompare("log",option+1) == 0)
1374           {
1375             if (*option != '+')
1376               (void) SetLogFormat(argv[i+1]);
1377             break;
1378           }
1379         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1380       }
1381       case 'r':
1382       {
1383         if (LocaleCompare("regard-warnings",option+1) == 0)
1384           {
1385             regard_warnings=MagickTrue;
1386             break;
1387           }
1388         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1389       }
1390       case 'v':
1391       {
1392         if (LocaleCompare("validate",option+1) == 0)
1393           {
1394             ssize_t
1395               validate;
1396
1397             if (*option == '+')
1398               break;
1399             i++;
1400             if (i == (ssize_t) argc)
1401               ThrowValidateException(OptionError,"MissingArgument",option);
1402             validate=ParseCommandOption(MagickValidateOptions,MagickFalse,
1403               argv[i]);
1404             if (validate < 0)
1405               ThrowValidateException(OptionError,"UnrecognizedValidateType",
1406                 argv[i]);
1407             type=(ValidateType) validate;
1408             break;
1409           }
1410         if ((LocaleCompare("version",option+1) == 0) ||
1411             (LocaleCompare("-version",option+1) == 0))
1412           {
1413             (void) FormatLocaleFile(stdout,"Version: %s\n",
1414               GetMagickVersion((size_t *) NULL));
1415             (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
1416               GetMagickCopyright());
1417             (void) FormatLocaleFile(stdout,"Features: %s\n\n",
1418               GetMagickFeatures());
1419             return(0);
1420           }
1421         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1422       }
1423       default:
1424         ThrowValidateException(OptionError,"UnrecognizedOption",option)
1425     }
1426   }
1427   timer=(TimerInfo *) NULL;
1428   if (iterations > 1)
1429     timer=AcquireTimerInfo();
1430   reference_image=ReadImage(image_info,exception);
1431   tests=0;
1432   fail=0;
1433   if (reference_image == (Image *) NULL)
1434     fail++;
1435   else
1436     {
1437       if (LocaleCompare(image_info->filename,ReferenceFilename) == 0)
1438         (void) CopyMagickString(reference_image->magick,ReferenceImageFormat,
1439           MaxTextExtent);
1440       (void) AcquireUniqueFilename(reference_filename);
1441       (void) AcquireUniqueFilename(output_filename);
1442       (void) CopyMagickString(reference_image->filename,reference_filename,
1443         MaxTextExtent);
1444       status=WriteImage(image_info,reference_image);
1445       InheritException(exception,&reference_image->exception);
1446       reference_image=DestroyImage(reference_image);
1447       if (status == MagickFalse)
1448         fail++;
1449       else
1450         {
1451           (void) FormatLocaleFile(stdout,"Version: %s\n",
1452             GetMagickVersion((size_t *) NULL));
1453           (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
1454             GetMagickCopyright());
1455           (void) FormatLocaleFile(stdout,
1456             "ImageMagick Validation Suite (%s)\n\n",CommandOptionToMnemonic(
1457             MagickValidateOptions,(ssize_t) type));
1458           if ((type & CompareValidate) != 0)
1459             tests+=ValidateCompareCommand(image_info,reference_filename,
1460               output_filename,&fail,exception);
1461           if ((type & CompositeValidate) != 0)
1462             tests+=ValidateCompositeCommand(image_info,reference_filename,
1463               output_filename,&fail,exception);
1464           if ((type & ConvertValidate) != 0)
1465             tests+=ValidateConvertCommand(image_info,reference_filename,
1466               output_filename,&fail,exception);
1467           if ((type & FormatsInMemoryValidate) != 0)
1468             tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
1469               output_filename,&fail,exception);
1470           if ((type & FormatsOnDiskValidate) != 0)
1471             tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
1472               output_filename,&fail,exception);
1473           if ((type & IdentifyValidate) != 0)
1474             tests+=ValidateIdentifyCommand(image_info,reference_filename,
1475               output_filename,&fail,exception);
1476           if ((type & ImportExportValidate) != 0)
1477             tests+=ValidateImportExportPixels(image_info,reference_filename,
1478               output_filename,&fail,exception);
1479           if ((type & MontageValidate) != 0)
1480             tests+=ValidateMontageCommand(image_info,reference_filename,
1481               output_filename,&fail,exception);
1482           if ((type & StreamValidate) != 0)
1483             tests+=ValidateStreamCommand(image_info,reference_filename,
1484               output_filename,&fail,exception);
1485           (void) FormatLocaleFile(stdout,
1486             "validation suite: %.20g tests; %.20g passed; %.20g failed.\n",
1487             (double) tests,(double) (tests-fail),(double) fail);
1488         }
1489       (void) RelinquishUniqueFileResource(output_filename);
1490       (void) RelinquishUniqueFileResource(reference_filename);
1491     }
1492   if (exception->severity != UndefinedException)
1493     CatchException(exception);
1494   if (iterations > 1)
1495     {
1496       elapsed_time=GetElapsedTime(timer);
1497       user_time=GetUserTime(timer);
1498       (void) FormatLocaleFile(stderr,
1499         "Performance: %.20gi %gips %0.3fu %ld:%02ld.%03ld\n",(double)
1500         iterations,1.0*iterations/elapsed_time,user_time,(long)
1501         (elapsed_time/60.0),(long) ceil(fmod(elapsed_time,60.0)),
1502         (long) (1000.0*(elapsed_time-floor(elapsed_time))));
1503       timer=DestroyTimerInfo(timer);
1504     }
1505   DestroyValidate();
1506   MagickCoreTerminus();
1507   return(fail == 0 ? 0 : 1);
1508 }