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