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