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