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