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