blob: 0404f0cb67b649d93b58930a6359c02af707bfd4 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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% %
cristy45ef08f2012-12-07 13:13:34 +000021% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000022% dedicated to making software imaging solutions freely available. %
23% %
24% You may not use this file except in compliance with the License. You may %
25% obtain a copy of the License at %
26% %
27% http://www.imagemagick.org/script/license.php %
28% %
29% Unless required by applicable law or agreed to in writing, software %
30% distributed under the License is distributed on an "AS IS" BASIS, %
31% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
32% see the License for the specific language governing permissions and %
33% limitations under the License. %
34% %
35%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
43#include <stdio.h>
cristy5e8e9812009-12-17 15:13:38 +000044#include <stdlib.h>
cristy3ed852e2009-09-05 21:47:34 +000045#include <string.h>
cristy5e8e9812009-12-17 15:13:38 +000046#include <ctype.h>
cristy3ed852e2009-09-05 21:47:34 +000047#include <math.h>
cristye2605742012-12-12 11:18:34 +000048#include <locale.h>
cristy9883b452011-07-01 23:37:21 +000049#include "MagickWand/MagickWand.h"
cristy510d06a2011-07-06 23:43:54 +000050#include "MagickCore/colorspace-private.h"
glennrp4084cda2012-12-11 14:13:35 +000051#include "MagickCore/resource_.h"
cristy9883b452011-07-01 23:37:21 +000052#include "MagickCore/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000053#include "validate.h"
54
55/*
cristy8d24e062013-05-07 12:48:19 +000056 Define declarations.
57*/
58#define CIEEpsilon (216.0/24389.0)
59#define CIEK (24389.0/27.0)
60#define D65X 0.950456
61#define D65Y 1.0
62#define D65Z 1.088754
63#define ReferenceEpsilon (1.0e-0)
64
65/*
cristy3ed852e2009-09-05 21:47:34 +000066%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67% %
68% %
69% %
cristy80e870e2013-05-07 12:23:02 +000070% V a l i d a t e C o l o r s p a c e C o m m a n d %
71% %
72% %
73% %
74%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75%
76% ValidateCompareCommand() validates the ImageMagick colorspaces and returns
77% the number of validation tests that passed and failed.
78%
79% The format of the ValidateColorspaceCommand method is:
80%
81% size_t ValidateColorspaceCommand(ImageInfo *image_info,
82% const char *reference_filename,const char *output_filename,
83% size_t *fail,ExceptionInfo *exception)
84%
85% A description of each parameter follows:
86%
87% o image_info: the image info.
88%
89% o reference_filename: the reference image filename.
90%
91% o output_filename: the output image filename.
92%
93% o fail: return the number of validation tests that pass.
94%
95% o exception: return any errors or warnings in this structure.
96%
97*/
cristy8d24e062013-05-07 12:48:19 +000098
99static void ConvertHSIToRGB(const double hue,const double saturation,
100 const double intensity,double *red,double *green,double *blue)
101{
102 double
103 h;
104
105 /*
106 Convert HSI to RGB colorspace.
107 */
108 h=360.0*hue;
109 h-=360.0*floor(h/360.0);
110 if (h < 120.0)
111 {
112 *blue=intensity*(1.0-saturation);
113 *red=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
114 (MagickPI/180.0)));
115 *green=3.0*intensity-*red-*blue;
116 }
117 else
118 if (h < 240.0)
119 {
120 h-=120.0;
121 *red=intensity*(1.0-saturation);
122 *green=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
123 (MagickPI/180.0)));
124 *blue=3.0*intensity-*red-*green;
125 }
126 else
127 {
128 h-=240.0;
129 *green=intensity*(1.0-saturation);
130 *blue=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
131 (MagickPI/180.0)));
132 *red=3.0*intensity-*green-*blue;
133 }
134 *red*=QuantumRange;
135 *green*=QuantumRange;
136 *blue*=QuantumRange;
137}
138
139static inline double MagickMin(const double x,const double y)
140{
141 if (x < y)
142 return(x);
143 return(y);
144}
145
146static void ConvertRGBToHSI(const double red,const double green,
147 const double blue,double *hue,double *saturation,double *intensity)
148{
149 double
150 alpha,
151 beta;
152
153 /*
154 Convert RGB to HSI colorspace.
155 */
156 *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0;
157 if (*intensity <= 0.0)
158 {
159 *hue=0.0;
160 *saturation=0.0;
161 return;
162 }
163 *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
164 QuantumScale*blue))/(*intensity);
165 alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
166 beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue);
167 *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
168 if (*hue < 0.0)
169 *hue+=1.0;
170}
171
172MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
173 const double lightness,double *red,double *green,double *blue)
174{
175 double
176 c,
177 h,
178 min,
179 x;
180
181 /*
182 Convert HSL to RGB colorspace.
183 */
184 h=hue*360.0;
185 if (lightness <= 0.5)
186 c=2.0*lightness*saturation;
187 else
188 c=(2.0-2.0*lightness)*saturation;
189 min=lightness-0.5*c;
190 h-=360.0*floor(h/360.0);
191 h/=60.0;
192 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
193 switch ((int) floor(h))
194 {
195 case 0:
196 {
197 *red=QuantumRange*(min+c);
198 *green=QuantumRange*(min+x);
199 *blue=QuantumRange*min;
200 break;
201 }
202 case 1:
203 {
204 *red=QuantumRange*(min+x);
205 *green=QuantumRange*(min+c);
206 *blue=QuantumRange*min;
207 break;
208 }
209 case 2:
210 {
211 *red=QuantumRange*min;
212 *green=QuantumRange*(min+c);
213 *blue=QuantumRange*(min+x);
214 break;
215 }
216 case 3:
217 {
218 *red=QuantumRange*min;
219 *green=QuantumRange*(min+x);
220 *blue=QuantumRange*(min+c);
221 break;
222 }
223 case 4:
224 {
225 *red=QuantumRange*(min+x);
226 *green=QuantumRange*min;
227 *blue=QuantumRange*(min+c);
228 break;
229 }
230 case 5:
231 {
232 *red=QuantumRange*(min+c);
233 *green=QuantumRange*min;
234 *blue=QuantumRange*(min+x);
235 break;
236 }
237 default:
238 {
239 *red=0.0;
240 *green=0.0;
241 *blue=0.0;
242 }
243 }
244}
245
246static inline double MagickMax(const double x,const double y)
247{
248 if (x > y)
249 return(x);
250 return(y);
251}
252
253MagickExport void ConvertRGBToHSL(const double red,const double green,
254 const double blue,double *hue,double *saturation,double *lightness)
255{
256 double
257 c,
258 max,
259 min;
260
261 /*
262 Convert RGB to HSL colorspace.
263 */
264 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
265 QuantumScale*blue));
266 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
267 QuantumScale*blue));
268 c=max-min;
269 *lightness=(max+min)/2.0;
270 if (c <= 0.0)
271 {
272 *hue=0.0;
273 *saturation=0.0;
274 return;
275 }
276 if (max == (QuantumScale*red))
277 {
278 *hue=(QuantumScale*green-QuantumScale*blue)/c;
279 if ((QuantumScale*green) < (QuantumScale*blue))
280 *hue+=6.0;
281 }
282 else
283 if (max == (QuantumScale*green))
284 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
285 else
286 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
287 *hue*=60.0/360.0;
288 if (*lightness <= 0.5)
289 *saturation=c/(2.0*(*lightness));
290 else
291 *saturation=c/(2.0-2.0*(*lightness));
292}
293
294static void ConvertHSVToRGB(const double hue,const double saturation,
295 const double value,double *red,double *green,double *blue)
296{
297 double
298 c,
299 h,
300 min,
301 x;
302
303 /*
304 Convert HSV to RGB colorspace.
305 */
306 h=hue*360.0;
307 c=value*saturation;
308 min=value-c;
309 h-=360.0*floor(h/360.0);
310 h/=60.0;
311 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
312 switch ((int) floor(h))
313 {
314 case 0:
315 {
316 *red=QuantumRange*(min+c);
317 *green=QuantumRange*(min+x);
318 *blue=QuantumRange*min;
319 break;
320 }
321 case 1:
322 {
323 *red=QuantumRange*(min+x);
324 *green=QuantumRange*(min+c);
325 *blue=QuantumRange*min;
326 break;
327 }
328 case 2:
329 {
330 *red=QuantumRange*min;
331 *green=QuantumRange*(min+c);
332 *blue=QuantumRange*(min+x);
333 break;
334 }
335 case 3:
336 {
337 *red=QuantumRange*min;
338 *green=QuantumRange*(min+x);
339 *blue=QuantumRange*(min+c);
340 break;
341 }
342 case 4:
343 {
344 *red=QuantumRange*(min+x);
345 *green=QuantumRange*min;
346 *blue=QuantumRange*(min+c);
347 break;
348 }
349 case 5:
350 {
351 *red=QuantumRange*(min+c);
352 *green=QuantumRange*min;
353 *blue=QuantumRange*(min+x);
354 break;
355 }
356 default:
357 {
358 *red=0.0;
359 *green=0.0;
360 *blue=0.0;
361 }
362 }
363}
364
365static inline void ConvertRGBToXYZ(const double red,const double green,
366 const double blue,double *X,double *Y,double *Z)
367{
368 double
369 b,
370 g,
371 r;
372
373 /*
374 Convert RGB to XYZ colorspace.
375 */
376 r=QuantumScale*DecodePixelGamma(red);
377 g=QuantumScale*DecodePixelGamma(green);
378 b=QuantumScale*DecodePixelGamma(blue);
379 *X=0.41239558896741421610*r+0.35758343076371481710*g+0.18049264738170157350*b;
380 *Y=0.21258623078559555160*r+0.71517030370341084990*g+0.07220049864333622685*b;
381 *Z=0.01929721549174694484*r+0.11918386458084853180*g+0.95049712513157976600*b;
382}
383
384static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
385 double *L,double *a,double *b)
386{
387 double
388 x,
389 y,
390 z;
391
392 if ((X/D65X) > CIEEpsilon)
393 x=pow(X/D65X,1.0/3.0);
394 else
395 x=(CIEK*X/D65X+16.0)/116.0;
396 if ((Y/D65Y) > CIEEpsilon)
397 y=pow(Y/D65Y,1.0/3.0);
398 else
399 y=(CIEK*Y/D65Y+16.0)/116.0;
400 if ((Z/D65Z) > CIEEpsilon)
401 z=pow(Z/D65Z,1.0/3.0);
402 else
403 z=(CIEK*Z/D65Z+16.0)/116.0;
404 *L=((116.0*y)-16.0)/100.0;
405 *a=(500.0*(x-y))/255.0+0.5;
406 *b=(200.0*(y-z))/255.0+0.5;
407}
408
409static void ConvertRGBToLab(const double red,const double green,
410 const double blue,double *L,double *a,double *b)
411{
412 double
413 X,
414 Y,
415 Z;
416
417 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
418 ConvertXYZToLab(X,Y,Z,L,a,b);
419}
420
421static inline void ConvertLabToXYZ(const double L,const double a,const double b,
422 double *X,double *Y,double *Z)
423{
424 double
425 x,
426 y,
427 z;
428
429 y=(L+16.0)/116.0;
430 x=y+a/500.0;
431 z=y-b/200.0;
432 if ((x*x*x) > CIEEpsilon)
433 x=(x*x*x);
434 else
435 x=(116.0*x-16.0)/CIEK;
436 if ((y*y*y) > CIEEpsilon)
437 y=(y*y*y);
438 else
439 y=L/CIEK;
440 if ((z*z*z) > CIEEpsilon)
441 z=(z*z*z);
442 else
443 z=(116.0*z-16.0)/CIEK;
444 *X=D65X*x;
445 *Y=D65Y*y;
446 *Z=D65Z*z;
447}
448
449static inline void ConvertXYZToRGB(const double x,const double y,const double z,
450 double *red,double *green,double *blue)
451{
452 double
453 b,
454 g,
455 r;
456
457 /*
458 Convert XYZ to RGB colorspace.
459 */
460 r=3.2406*x-1.5372*y-0.4986*z;
461 g=(-0.9689*x+1.8758*y+0.0415*z);
462 b=0.0557*x-0.2040*y+1.0570*z;
463 *red=EncodePixelGamma(QuantumRange*r);
464 *green=EncodePixelGamma(QuantumRange*g);
465 *blue=EncodePixelGamma(QuantumRange*b);
466}
467
468static inline void ConvertLabToRGB(const double L,const double a,
469 const double b,double *red,double *green,double *blue)
470{
471 double
472 X,
473 Y,
474 Z;
475
476 ConvertLabToXYZ(L*100.0,255.0*(a-0.5),255.0*(b-0.5),&X,&Y,&Z);
477 ConvertXYZToRGB(X,Y,Z,red,green,blue);
478}
479
480static void ConvertRGBToYPbPr(const double red,const double green,
481 const double blue,double *Y,double *Pb,double *Pr)
482{
483 /*
484 Convert RGB to YPbPr colorspace.
485 */
486 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
487 *Pb=QuantumScale*((-0.1687367)*red-0.331264*green+0.5*blue)+0.5;
488 *Pr=QuantumScale*(0.5*red-0.418688*green-0.081312*blue)+0.5;
489}
490
491static void ConvertRGBToYCbCr(const double red,const double green,
492 const double blue,double *Y,double *Cb,double *Cr)
493{
494 /*
495 Convert RGB to YCbCr colorspace.
496 */
497 ConvertRGBToYPbPr(red,green,blue,Y,Cb,Cr);
498}
499
500static void ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr,
501 double *red,double *green,double *blue)
502{
503 /*
504 Convert YPbPr to RGB colorspace.
505 */
506 *red=QuantumRange*(0.99999999999914679361*Y-1.2188941887145875e-06*(Pb-0.5)+
507 1.4019995886561440468*(Pr-0.5));
508 *green=QuantumRange*(0.99999975910502514331*Y-0.34413567816504303521*(Pb-0.5)-
509 0.71413649331646789076*(Pr-0.5));
510 *blue=QuantumRange*(1.00000124040004623180*Y+1.77200006607230409200*(Pb-0.5)+
511 2.1453384174593273e-06*(Pr-0.5));
512}
513
514static void ConvertYCbCrToRGB(const double Y,const double Cb,
515 const double Cr,double *red,double *green,double *blue)
516{
517 /*
518 Convert YCbCr to RGB colorspace.
519 */
520 ConvertYPbPrToRGB(Y,Cb,Cr,red,green,blue);
521}
522
523static inline void ConvertLCHabToXYZ(const double luma,const double chroma,
524 const double hue,double *X,double *Y,double *Z)
525{
526 ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
527 sin(hue*MagickPI/180.0),X,Y,Z);
528}
529
530static void ConvertLCHabToRGB(const double luma,const double chroma,
531 const double hue,double *red,double *green,double *blue)
532{
533 double
534 X,
535 Y,
536 Z;
537
538 /*
539 Convert LCHab to RGB colorspace.
540 */
541 ConvertLCHabToXYZ(luma*100.0,255.0*(chroma-0.5),255.0*(hue-0.5),&X,&Y,&Z);
542 ConvertXYZToRGB(X,Y,Z,red,green,blue);
543}
544
545static void ConvertRGBToHSV(const double red,const double green,
546 const double blue,double *hue,double *saturation,double *value)
547{
548 double
549 c,
550 max,
551 min;
552
553 /*
554 Convert RGB to HSV colorspace.
555 */
556 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
557 QuantumScale*blue));
558 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
559 QuantumScale*blue));
560 c=max-min;
561 *value=max;
562 if (c <= 0.0)
563 {
564 *hue=0.0;
565 *saturation=0.0;
566 return;
567 }
568 if (max == (QuantumScale*red))
569 {
570 *hue=(QuantumScale*green-QuantumScale*blue)/c;
571 if ((QuantumScale*green) < (QuantumScale*blue))
572 *hue+=6.0;
573 }
574 else
575 if (max == (QuantumScale*green))
576 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
577 else
578 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
579 *hue*=60.0/360.0;
580 *saturation=c/max;
581}
582
583static inline void ConvertXYZToLCHab(const double X,const double Y,
584 const double Z,double *luma,double *chroma,double *hue)
585{
586 double
587 a,
588 b;
589
590 ConvertXYZToLab(X,Y,Z,luma,&a,&b);
591 *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5));
592 *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI;
593 *chroma=(*chroma)/255.0+0.5;
594 *hue=(*hue)/255.0+0.5;
595 if (*hue < 0.0)
596 *hue+=1.0;
597}
598
599static void ConvertRGBToLCHab(const double red,const double green,
600 const double blue,double *luma,double *chroma,double *hue)
601{
602 double
603 X,
604 Y,
605 Z;
606
607 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
608 ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue);
609}
610
611static inline void ConvertLMSToXYZ(const double L,const double M,const double S,
612 double *X,double *Y,double *Z)
613{
614 *X=1.096123820835514*L-0.278869000218287*M+0.182745179382773*S;
615 *Y=0.454369041975359*L+0.473533154307412*M+0.072097803717229*S;
616 *Z=(-0.009627608738429)*L-0.005698031216113*M+1.015325639954543*S;
617}
618
619static inline void ConvertLMSToRGB(const double L,const double M,
620 const double S,double *red,double *green,double *blue)
621{
622 double
623 X,
624 Y,
625 Z;
626
627 ConvertLMSToXYZ(L,M,S,&X,&Y,&Z);
628 ConvertXYZToRGB(X,Y,Z,red,green,blue);
629}
630
631static inline void ConvertXYZToLMS(const double x,const double y,
632 const double z,double *L,double *M,double *S)
633{
634 /*
635 Convert XYZ to LMS colorspace.
636 */
637 *L=0.7328*x+0.4296*y-0.1624*z;
638 *M=(-0.7036*x+1.6975*y+0.0061*z);
639 *S=0.0030*x+0.0136*y+0.9834*z;
640}
641
642static void ConvertRGBToLMS(const double red,const double green,
643 const double blue,double *L,double *M,double *S)
644{
645 double
646 X,
647 Y,
648 Z;
649
650 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
651 ConvertXYZToLMS(X,Y,Z,L,M,S);
652}
653
654static inline double PerceptibleReciprocal(const double x)
655{
656 double
657 sign;
658
659 /*
660 Return 1/x where x is perceptible (not unlimited or infinitesimal).
661 */
662 sign=x < 0.0 ? -1.0 : 1.0;
663 if ((sign*x) >= MagickEpsilon)
664 return(1.0/x);
665 return(sign/MagickEpsilon);
666}
667
668static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
669 double *L,double *u,double *v)
670{
671 double
672 alpha;
673
674 if ((Y/D65Y) > CIEEpsilon)
675 *L=(double) (116.0*pow(Y/D65Y,1.0/3.0)-16.0);
676 else
677 *L=CIEK*(Y/D65Y);
678 alpha=PerceptibleReciprocal(X+15.0*Y+3.0*Z);
679 *u=13.0*(*L)*((4.0*alpha*X)-(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z)));
680 *v=13.0*(*L)*((9.0*alpha*Y)-(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z)));
681 *L/=100.0;
682 *u=(*u+134.0)/354.0;
683 *v=(*v+140.0)/262.0;
684}
685
686static void ConvertRGBToLuv(const double red,const double green,
687 const double blue,double *L,double *u,double *v)
688{
689 double
690 X,
691 Y,
692 Z;
693
694 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
695 ConvertXYZToLuv(X,Y,Z,L,u,v);
696}
697
698static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
699 double *X,double *Y,double *Z)
700{
701 if (L > (CIEK*CIEEpsilon))
702 *Y=(double) pow((L+16.0)/116.0,3.0);
703 else
704 *Y=L/CIEK;
705 *X=((*Y*((39.0*L/(v+13.0*L*(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z))))-5.0))+
706 5.0*(*Y))/((((52.0f*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/
707 3.0)-(-1.0/3.0));
708 *Z=(*X*(((52.0f*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/3.0))-
709 5.0*(*Y);
710}
711
712static inline void ConvertLuvToRGB(const double L,const double u,
713 const double v,double *red,double *green,double *blue)
714{
715 double
716 X,
717 Y,
718 Z;
719
720 ConvertLuvToXYZ(100.0*L,354.0*u-134.0,262.0*v-140.0,&X,&Y,&Z);
721 ConvertXYZToRGB(X,Y,Z,red,green,blue);
722}
723
724static void ConvertRGBToYDbDr(const double red,const double green,
725 const double blue,double *Y,double *Db,double *Dr)
726{
727 /*
728 Convert RGB to YDbDr colorspace.
729 */
730 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
731 *Db=QuantumScale*(-0.450*red-0.883*green+1.333*blue)+0.5;
732 *Dr=QuantumScale*(-1.333*red+1.116*green+0.217*blue)+0.5;
733}
734
735static void ConvertYDbDrToRGB(const double Y,const double Db,const double Dr,
736 double *red,double *green,double *blue)
737{
738 /*
739 Convert YDbDr to RGB colorspace.
740 */
741 *red=QuantumRange*(Y+9.2303716147657e-05*(Db-0.5)-0.52591263066186533*
742 (Dr-0.5));
743 *green=QuantumRange*(Y-0.12913289889050927*(Db-0.5)+0.26789932820759876*
744 (Dr-0.5));
745 *blue=QuantumRange*(Y+0.66467905997895482*(Db-0.5)-7.9202543533108e-05*
746 (Dr-0.5));
747}
748
749static void ConvertRGBToYIQ(const double red,const double green,
750 const double blue,double *Y,double *I,double *Q)
751{
752 /*
753 Convert RGB to YIQ colorspace.
754 */
755 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
756 *I=QuantumScale*(0.595716*red-0.274453*green-0.321263*blue)+0.5;
757 *Q=QuantumScale*(0.211456*red-0.522591*green+0.311135*blue)+0.5;
758}
759
760static void ConvertYIQToRGB(const double Y,const double I,const double Q,
761 double *red,double *green,double *blue)
762{
763 /*
764 Convert YIQ to RGB colorspace.
765 */
766 *red=QuantumRange*(Y+0.9562957197589482261*(I-0.5)+0.6210244164652610754*
767 (Q-0.5));
768 *green=QuantumRange*(Y-0.2721220993185104464*(I-0.5)-0.6473805968256950427*
769 (Q-0.5));
770 *blue=QuantumRange*(Y-1.1069890167364901945*(I-0.5)+1.7046149983646481374*
771 (Q-0.5));
772}
773
774static void ConvertRGBToYUV(const double red,const double green,
775 const double blue,double *Y,double *U,double *V)
776{
777 /*
778 Convert RGB to YUV colorspace.
779 */
780 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
781 *U=QuantumScale*((-0.147)*red-0.289*green+0.436*blue)+0.5;
782 *V=QuantumScale*(0.615*red-0.515*green-0.100*blue)+0.5;
783}
784
785static void ConvertYUVToRGB(const double Y,const double U,const double V,
786 double *red,double *green,double *blue)
787{
788 /*
789 Convert YUV to RGB colorspace.
790 */
791 *red=QuantumRange*(Y-3.945707070708279e-05*(U-0.5)+1.1398279671717170825*
792 (V-0.5));
793 *green=QuantumRange*(Y-0.3946101641414141437*(U-0.5)-0.5805003156565656797*
794 (V-0.5));
795 *blue=QuantumRange*(Y+2.0319996843434342537*(U-0.5)-4.813762626262513e-04*
796 (V-0.5));
797}
798
799static MagickBooleanType ValidateHSIToRGB()
800{
801 double
802 r,
803 g,
804 b;
805
806 (void) FormatLocaleFile(stdout," HSIToRGB: ");
807 ConvertHSIToRGB(111.244375/360.0,0.295985,0.658734,&r,&g,&b);
808 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
809 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
810 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
811 return(MagickFalse);
812 return(MagickTrue);
813}
814
815static MagickBooleanType ValidateRGBToHSI()
816{
817 double
818 h,
819 i,
820 s;
821
822 (void) FormatLocaleFile(stdout," RGBToHSI: ");
823 ConvertRGBToHSI(0.545877*QuantumRange,0.966567*QuantumRange,
824 0.463759*QuantumRange,&h,&s,&i);
825 if ((fabs(h-111.244374/360.0) >= ReferenceEpsilon) ||
826 (fabs(s-0.295985) >= ReferenceEpsilon) ||
827 (fabs(i-0.658734) >= ReferenceEpsilon))
828 return(MagickFalse);
829 return(MagickTrue);
830}
831
832static MagickBooleanType ValidateHSLToRGB()
833{
834 double
835 r,
836 g,
837 b;
838
839 (void) FormatLocaleFile(stdout," HSLToRGB: ");
840 ConvertHSLToRGB(110.200859/360.0,0.882623,0.715163,&r,&g,&b);
841 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
842 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
843 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
844 return(MagickFalse);
845 return(MagickTrue);
846}
847
848static MagickBooleanType ValidateRGBToHSL()
849{
850 double
851 h,
852 l,
853 s;
854
855 (void) FormatLocaleFile(stdout," RGBToHSL: ");
856 ConvertRGBToHSL(0.545877*QuantumRange,0.966567*QuantumRange,
857 0.463759*QuantumRange,&h,&s,&l);
858 if ((fabs(h-110.200859/360.0) >= ReferenceEpsilon) ||
859 (fabs(s-0.882623) >= ReferenceEpsilon) ||
860 (fabs(l-0.715163) >= ReferenceEpsilon))
861 return(MagickFalse);
862 return(MagickTrue);
863}
864
865static MagickBooleanType ValidateHSVToRGB()
866{
867 double
868 r,
869 g,
870 b;
871
872 (void) FormatLocaleFile(stdout," HSVToRGB: ");
873 ConvertHSVToRGB(110.200859/360.0,0.520200,0.966567,&r,&g,&b);
874 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
875 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
876 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
877 return(MagickFalse);
878 return(MagickTrue);
879}
880
881static MagickBooleanType ValidateRGBToHSV()
882{
883 double
884 h,
885 s,
886 v;
887
888 (void) FormatLocaleFile(stdout," RGBToHSV: ");
889 ConvertRGBToHSV(0.545877*QuantumRange,0.966567*QuantumRange,
890 0.463759*QuantumRange,&h,&s,&v);
891 if ((fabs(h-110.200859/360.0) >= ReferenceEpsilon) ||
892 (fabs(s-0.520200) >= ReferenceEpsilon) ||
893 (fabs(v-0.966567) >= ReferenceEpsilon))
894 return(MagickFalse);
895 return(MagickTrue);
896}
897
898static MagickBooleanType ValidateRGBToJPEGYCbCr()
899{
900 double
901 Cb,
902 Cr,
903 Y;
904
905 (void) FormatLocaleFile(stdout," RGBToJPEGYCbCr: ");
906 ConvertRGBToYCbCr(0.545877*QuantumRange,0.966567*QuantumRange,
907 0.463759*QuantumRange,&Y,&Cb,&Cr);
908 if ((fabs(Y-0.783460) >= ReferenceEpsilon) ||
909 (fabs(Cb-0.319581) >= ReferenceEpsilon) ||
910 (fabs(Cr-0.330539) >= ReferenceEpsilon))
911 return(MagickFalse);
912 return(MagickTrue);
913}
914
915static MagickBooleanType ValidateJPEGYCbCrToRGB()
916{
917 double
918 r,
919 g,
920 b;
921
922 (void) FormatLocaleFile(stdout," JPEGYCbCrToRGB: ");
923 ConvertYCbCrToRGB(0.783460,0.319581,0.330539,&r,&g,&b);
924 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
925 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
926 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
927 return(MagickFalse);
928 return(MagickTrue);
929}
930
931static MagickBooleanType ValidateLabToRGB()
932{
933 double
934 r,
935 g,
936 b;
937
938 (void) FormatLocaleFile(stdout," LabToRGB: ");
939 ConvertLabToRGB(88.456154/100.0,-54.671483/255+0.5,51.662818/255.0+0.5,
940 &r,&g,&b);
941 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
942 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
943 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
944 return(MagickFalse);
945 return(MagickTrue);
946}
947
948static MagickBooleanType ValidateRGBToLab()
949{
950 double
951 a,
952 b,
953 L;
954
955 (void) FormatLocaleFile(stdout," RGBToLab: ");
956 ConvertRGBToLab(0.545877*QuantumRange,0.966567*QuantumRange,
957 0.463759*QuantumRange,&L,&a,&b);
958 if ((fabs(L-(88.456154/100.0)) >= ReferenceEpsilon) ||
959 (fabs(a-(-54.671483/255.0+0.5)) >= ReferenceEpsilon) ||
960 (fabs(b-(51.662818/255.0+0.5)) >= ReferenceEpsilon))
961 return(MagickFalse);
962 return(MagickTrue);
963}
964
965static MagickBooleanType ValidateLchToRGB()
966{
967 double
968 b,
969 g,
970 r;
971
972 (void) FormatLocaleFile(stdout," LchToRGB: ");
973 ConvertLCHabToRGB(88.456154/100.0,75.219797/255.0+0.5,136.620717/255.0+0.5,
974 &r,&g,&b);
975 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
976 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
977 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
978 return(MagickFalse);
979 return(MagickTrue);
980}
981
982static MagickBooleanType ValidateRGBToLch()
983{
984 double
985 c,
986 h,
987 L;
988
989 (void) FormatLocaleFile(stdout," RGBToLch: ");
990 ConvertRGBToLCHab(0.545877*QuantumRange,0.966567*QuantumRange,
991 0.463759*QuantumRange,&L,&c,&h);
992 if ((fabs(L-88.456154/100.0) >= ReferenceEpsilon) ||
993 (fabs(c-(75.219797/255.0+0.5)) >= ReferenceEpsilon) ||
994 (fabs(h-(136.620717/255.0+0.5)) >= ReferenceEpsilon))
995 return(MagickFalse);
996 return(MagickTrue);
997}
998
999static MagickBooleanType ValidateRGBToLMS()
1000{
1001 double
1002 L,
1003 M,
1004 S;
1005
1006 (void) FormatLocaleFile(stdout," RGBToLMS: ");
1007 ConvertRGBToLMS(0.545877*QuantumRange,0.966567*QuantumRange,
1008 0.463759*QuantumRange,&L,&M,&S);
1009 if ((fabs(L-0.611749) >= ReferenceEpsilon) ||
1010 (fabs(M-0.910088) >= ReferenceEpsilon) ||
1011 (fabs(S-0.294880) >= ReferenceEpsilon))
1012 return(MagickFalse);
1013 return(MagickTrue);
1014}
1015
1016static MagickBooleanType ValidateLMSToRGB()
1017{
1018 double
1019 r,
1020 g,
1021 b;
1022
1023 (void) FormatLocaleFile(stdout," LMSToRGB: ");
1024 ConvertLMSToRGB(0.611749,0.910088,0.294880,&r,&g,&b);
1025 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1026 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1027 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1028 return(MagickFalse);
1029 return(MagickTrue);
1030}
1031
1032static MagickBooleanType ValidateRGBToLuv()
1033{
1034 double
1035 l,
1036 u,
1037 v;
1038
1039 (void) FormatLocaleFile(stdout," RGBToLuv: ");
1040 ConvertRGBToLuv(0.545877*QuantumRange,0.966567*QuantumRange,
1041 0.463759*QuantumRange,&l,&u,&v);
1042 if ((fabs(l-88.456154/262.0) >= ReferenceEpsilon) ||
1043 (fabs(u-(-51.330414+134.0)/354.0) >= ReferenceEpsilon) ||
1044 (fabs(v-(76.405526+140.0)/262.0) >= ReferenceEpsilon))
1045 return(MagickFalse);
1046 return(MagickTrue);
1047}
1048
1049static MagickBooleanType ValidateLuvToRGB()
1050{
1051 double
1052 r,
1053 g,
1054 b;
1055
1056 (void) FormatLocaleFile(stdout," LuvToRGB: ");
1057 ConvertLuvToRGB(88.456154/100.0,(-51.330414+134.0)/354.0,
1058 (76.405526+140.0)/262.0,&r,&g,&b);
1059 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1060 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1061 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1062 return(MagickFalse);
1063 return(MagickTrue);
1064}
1065
1066static MagickBooleanType ValidateRGBToXYZ()
1067{
1068 double
1069 x,
1070 y,
1071 z;
1072
1073 (void) FormatLocaleFile(stdout," RGBToXYZ: ");
1074 ConvertRGBToXYZ(0.545877*QuantumRange,0.966567*QuantumRange,
1075 0.463759*QuantumRange,&x,&y,&z);
1076 if ((fabs(x-0.470646) >= ReferenceEpsilon) ||
1077 (fabs(y-0.730178) >= ReferenceEpsilon) ||
1078 (fabs(z-0.288324) >= ReferenceEpsilon))
1079 return(MagickFalse);
1080 return(MagickTrue);
1081}
1082
1083static MagickBooleanType ValidateXYZToRGB()
1084{
1085 double
1086 r,
1087 g,
1088 b;
1089
1090 (void) FormatLocaleFile(stdout," XYZToRGB: ");
1091 ConvertXYZToRGB(0.470646,0.730178,0.288324,&r,&g,&b);
1092 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1093 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1094 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1095 return(MagickFalse);
1096 return(MagickTrue);
1097}
1098
1099static MagickBooleanType ValidateYDbDrToRGB()
1100{
1101 double
1102 r,
1103 g,
1104 b;
1105
1106 (void) FormatLocaleFile(stdout," YDbDrToRGB: ");
1107 ConvertYDbDrToRGB(0.783460,-0.480932+0.5,0.451670+0.5,&r,&g,&b);
1108 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1109 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1110 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1111 return(MagickFalse);
1112 return(MagickTrue);
1113}
1114
1115static MagickBooleanType ValidateRGBToYDbDr()
1116{
1117 double
1118 Db,
1119 Dr,
1120 Y;
1121
1122 (void) FormatLocaleFile(stdout," RGBToYDbDr: ");
1123 ConvertRGBToYDbDr(0.545877*QuantumRange,0.966567*QuantumRange,
1124 0.463759*QuantumRange,&Y,&Db,&Dr);
1125 if ((fabs(Y-0.783460) >= ReferenceEpsilon) ||
1126 (fabs(Db-(-0.480932)) >= ReferenceEpsilon) ||
1127 (fabs(Dr-0.451670) >= ReferenceEpsilon))
1128 return(MagickFalse);
1129 return(MagickTrue);
1130}
1131
1132static MagickBooleanType ValidateRGBToYIQ()
1133{
1134 double
1135 i,
1136 q,
1137 y;
1138
1139 (void) FormatLocaleFile(stdout," RGBToYIQ: ");
1140 ConvertRGBToYIQ(0.545877*QuantumRange,0.966567*QuantumRange,
1141 0.463759*QuantumRange,&y,&i,&q);
1142 if ((fabs(y-0.783460) >= ReferenceEpsilon) ||
1143 (fabs(i-(-0.089078)) >= ReferenceEpsilon) ||
1144 (fabs(q-(-0.245399)) >= ReferenceEpsilon))
1145 return(MagickFalse);
1146 return(MagickTrue);
1147}
1148
1149static MagickBooleanType ValidateYIQToRGB()
1150{
1151 double
1152 r,
1153 g,
1154 b;
1155
1156 (void) FormatLocaleFile(stdout," YIQToRGB: ");
1157 ConvertYIQToRGB(0.783460,-0.089078+0.5,-0.245399+0.5,&r,&g,&b);
1158 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1159 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1160 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1161 return(MagickFalse);
1162 return(MagickTrue);
1163}
1164
1165static MagickBooleanType ValidateRGBToYPbPr()
1166{
1167 double
1168 cb,
1169 cr,
1170 y;
1171
1172 (void) FormatLocaleFile(stdout," RGBToYPbPr: ");
1173 ConvertRGBToYPbPr(0.545877*QuantumRange,0.966567*QuantumRange,
1174 0.463759*QuantumRange,&y,&cb,&cr);
1175 if ((fabs(y-0.783460) >= ReferenceEpsilon) ||
1176 (fabs(cb-(-0.180419)) >= ReferenceEpsilon) ||
1177 (fabs(cr-(-0.169461)) >= ReferenceEpsilon))
1178 return(MagickFalse);
1179 return(MagickTrue);
1180}
1181
1182static MagickBooleanType ValidateYPbPrToRGB()
1183{
1184 double
1185 r,
1186 g,
1187 b;
1188
1189 (void) FormatLocaleFile(stdout," YPbPrToRGB: ");
1190 ConvertYPbPrToRGB(0.783460,-0.180419+0.5,-0.169461+0.5,&r,&g,&b);
1191 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1192 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1193 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1194 return(MagickFalse);
1195 return(MagickTrue);
1196}
1197
1198static MagickBooleanType ValidateRGBToYUV()
1199{
1200 double
1201 U,
1202 V,
1203 Y;
1204
1205 (void) FormatLocaleFile(stdout," RGBToYUV: ");
1206 ConvertRGBToYUV(0.545877*QuantumRange,0.966567*QuantumRange,
1207 0.463759*QuantumRange,&Y,&U,&V);
1208 if ((fabs(Y-0.783460) >= ReferenceEpsilon) ||
1209 (fabs(U-(-0.157383)) >= ReferenceEpsilon) ||
1210 (fabs(V-(-0.208443)) >= ReferenceEpsilon))
1211 return(MagickFalse);
1212 return(MagickTrue);
1213}
1214
1215static MagickBooleanType ValidateYUVToRGB()
1216{
1217 double
1218 r,
1219 g,
1220 b;
1221
1222 (void) FormatLocaleFile(stdout," YUVToRGB: ");
1223 ConvertYUVToRGB(0.783460,-0.157383+0.5,-0.208443+0.5,&r,&g,&b);
1224 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1225 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1226 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1227 return(MagickFalse);
1228 return(MagickTrue);
1229}
1230
cristy80e870e2013-05-07 12:23:02 +00001231static size_t ValidateColorspaceCommand(ImageInfo *image_info,
1232 const char *reference_filename,const char *output_filename,size_t *fail,
1233 ExceptionInfo *exception)
1234{
1235 MagickBooleanType
1236 status;
1237
cristy80e870e2013-05-07 12:23:02 +00001238 size_t
1239 test;
1240
cristy8d24e062013-05-07 12:48:19 +00001241 /*
1242 Reference: https://code.google.com/p/chroma:
1243
1244 Illuminant = D65
1245 Observer = 2° (1931)
1246
1247 XYZ 0.470645, 0.730177, 0.288323
1248 sRGB 0.545877, 0.966567, 0.463759
1249 CAT02 LMS 0.611749, 0.910088, 0.294880
1250 Y'DbDr 0.783460, -0.480932, 0.451670
1251 Y'IQ 0.783460, -0.089078, -0.245399
1252 Y'PbPr 0.783460, -0.180419, -0.169461
1253 Y'UV 0.783460, -0.157383, -0.208443
1254 JPEG-Y'CbCr 0.783460, 0.319581, 0.330539
1255 L*u*v* 88.456154, -51.330414, 76.405526
1256 L*a*b* 88.456154, -54.671483, 51.662818
1257 L*C*H* 88.456154, 75.219797, 136.620717
1258 HSV 110.200859, 0.520200, 0.966567
1259 HSL 110.200859, 0.882623, 0.715163
1260 HSI 111.244375, 0.295985, 0.658734
1261 Y'CbCr 187.577791, 87.586330, 90.040886
1262
1263 */
cristy80e870e2013-05-07 12:23:02 +00001264 (void) FormatLocaleFile(stdout,"validate colorspaces:\n");
cristy8d24e062013-05-07 12:48:19 +00001265 for (test=0; test < 26; test++)
1266 {
1267 CatchException(exception);
1268 (void) FormatLocaleFile(stdout," test %.20g: ",(double) test);
1269 switch (test)
cristy80e870e2013-05-07 12:23:02 +00001270 {
cristy8d24e062013-05-07 12:48:19 +00001271 case 0: status=ValidateHSIToRGB(); break;
1272 case 1: status=ValidateRGBToHSI(); break;
1273 case 2: status=ValidateHSLToRGB(); break;
1274 case 3: status=ValidateRGBToHSL(); break;
1275 case 4: status=ValidateHSVToRGB(); break;
1276 case 5: status=ValidateRGBToHSV(); break;
1277 case 6: status=ValidateJPEGYCbCrToRGB(); break;
1278 case 7: status=ValidateRGBToJPEGYCbCr(); break;
1279 case 8: status=ValidateLabToRGB(); break;
1280 case 9: status=ValidateRGBToLab(); break;
1281 case 10: status=ValidateLchToRGB(); break;
1282 case 11: status=ValidateRGBToLch(); break;
1283 case 12: status=ValidateLMSToRGB(); break;
1284 case 13: status=ValidateRGBToLMS(); break;
1285 case 14: status=ValidateLuvToRGB(); break;
1286 case 15: status=ValidateRGBToLuv(); break;
1287 case 16: status=ValidateXYZToRGB(); break;
1288 case 17: status=ValidateRGBToXYZ(); break;
1289 case 18: status=ValidateYDbDrToRGB(); break;
1290 case 19: status=ValidateRGBToYDbDr(); break;
1291 case 20: status=ValidateYIQToRGB(); break;
1292 case 21: status=ValidateRGBToYIQ(); break;
1293 case 22: status=ValidateYPbPrToRGB(); break;
1294 case 23: status=ValidateRGBToYPbPr(); break;
1295 case 24: status=ValidateYUVToRGB(); break;
1296 case 25: status=ValidateRGBToYUV(); break;
1297 default: status=MagickFalse;
cristy80e870e2013-05-07 12:23:02 +00001298 }
cristy8d24e062013-05-07 12:48:19 +00001299 if (status != MagickFalse)
1300 {
1301 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1302 GetMagickModule());
1303 (*fail)++;
1304 continue;
1305 }
1306 (void) FormatLocaleFile(stdout,"... pass.\n");
1307 }
cristy80e870e2013-05-07 12:23:02 +00001308 (void) FormatLocaleFile(stdout,
1309 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1310 (double) (test-(*fail)),(double) *fail);
1311 return(test);
1312}
1313
1314/*
1315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1316% %
1317% %
1318% %
cristy3ed852e2009-09-05 21:47:34 +00001319% V a l i d a t e C o m p a r e C o m m a n d %
1320% %
1321% %
1322% %
1323%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1324%
1325% ValidateCompareCommand() validates the ImageMagick compare command line
1326% program and returns the number of validation tests that passed and failed.
1327%
1328% The format of the ValidateCompareCommand method is:
1329%
cristybb503372010-05-27 20:51:26 +00001330% size_t ValidateCompareCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001331% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001332% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001333%
1334% A description of each parameter follows:
1335%
1336% o image_info: the image info.
1337%
1338% o reference_filename: the reference image filename.
1339%
1340% o output_filename: the output image filename.
1341%
1342% o fail: return the number of validation tests that pass.
1343%
1344% o exception: return any errors or warnings in this structure.
1345%
1346*/
cristybb503372010-05-27 20:51:26 +00001347static size_t ValidateCompareCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001348 const char *reference_filename,const char *output_filename,size_t *fail,
1349 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001350{
1351 char
1352 **arguments,
1353 command[MaxTextExtent];
1354
1355 int
1356 number_arguments;
1357
1358 MagickBooleanType
1359 status;
1360
cristybb503372010-05-27 20:51:26 +00001361 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001362 i,
1363 j;
1364
cristybb503372010-05-27 20:51:26 +00001365 size_t
cristy3ed852e2009-09-05 21:47:34 +00001366 test;
1367
1368 test=0;
cristyb51dff52011-05-19 16:55:47 +00001369 (void) FormatLocaleFile(stdout,"validate compare command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00001370 for (i=0; compare_options[i] != (char *) NULL; i++)
1371 {
1372 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00001373 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
cristy6aa47ad2010-05-28 19:32:32 +00001374 compare_options[i]);
cristyb51dff52011-05-19 16:55:47 +00001375 (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
cristy3ed852e2009-09-05 21:47:34 +00001376 compare_options[i],reference_filename,reference_filename,output_filename);
1377 arguments=StringToArgv(command,&number_arguments);
1378 if (arguments == (char **) NULL)
1379 {
cristy1e604812011-05-19 18:07:50 +00001380 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1381 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001382 (*fail)++;
1383 continue;
1384 }
cristy8a9106f2011-07-05 14:39:26 +00001385 status=CompareImagesCommand(image_info,number_arguments,arguments,
cristy3ed852e2009-09-05 21:47:34 +00001386 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00001387 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00001388 arguments[j]=DestroyString(arguments[j]);
1389 arguments=(char **) RelinquishMagickMemory(arguments);
1390 if (status != MagickFalse)
1391 {
cristy1e604812011-05-19 18:07:50 +00001392 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1393 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001394 (*fail)++;
1395 continue;
1396 }
cristyb51dff52011-05-19 16:55:47 +00001397 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00001398 }
cristyb51dff52011-05-19 16:55:47 +00001399 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00001400 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1401 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00001402 return(test);
1403}
1404
1405/*
1406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1407% %
1408% %
1409% %
1410% V a l i d a t e C o m p o s i t e C o m m a n d %
1411% %
1412% %
1413% %
1414%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1415%
1416% ValidateCompositeCommand() validates the ImageMagick composite command line
1417% program and returns the number of validation tests that passed and failed.
1418%
1419% The format of the ValidateCompositeCommand method is:
1420%
cristybb503372010-05-27 20:51:26 +00001421% size_t ValidateCompositeCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001422% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001423% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001424%
1425% A description of each parameter follows:
1426%
1427% o image_info: the image info.
1428%
1429% o reference_filename: the reference image filename.
1430%
1431% o output_filename: the output image filename.
1432%
1433% o fail: return the number of validation tests that pass.
1434%
1435% o exception: return any errors or warnings in this structure.
1436%
1437*/
cristybb503372010-05-27 20:51:26 +00001438static size_t ValidateCompositeCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001439 const char *reference_filename,const char *output_filename,size_t *fail,
1440 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001441{
1442 char
1443 **arguments,
1444 command[MaxTextExtent];
1445
1446 int
1447 number_arguments;
1448
1449 MagickBooleanType
1450 status;
1451
cristybb503372010-05-27 20:51:26 +00001452 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001453 i,
1454 j;
1455
cristybb503372010-05-27 20:51:26 +00001456 size_t
cristy3ed852e2009-09-05 21:47:34 +00001457 test;
1458
1459 test=0;
cristyb51dff52011-05-19 16:55:47 +00001460 (void) FormatLocaleFile(stdout,"validate composite command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00001461 for (i=0; composite_options[i] != (char *) NULL; i++)
1462 {
1463 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00001464 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
cristy6aa47ad2010-05-28 19:32:32 +00001465 composite_options[i]);
cristyb51dff52011-05-19 16:55:47 +00001466 (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
cristy3ed852e2009-09-05 21:47:34 +00001467 reference_filename,composite_options[i],reference_filename,
1468 output_filename);
1469 arguments=StringToArgv(command,&number_arguments);
1470 if (arguments == (char **) NULL)
1471 {
cristy1e604812011-05-19 18:07:50 +00001472 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1473 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001474 (*fail)++;
1475 continue;
1476 }
1477 status=CompositeImageCommand(image_info,number_arguments,arguments,
1478 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00001479 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00001480 arguments[j]=DestroyString(arguments[j]);
1481 arguments=(char **) RelinquishMagickMemory(arguments);
1482 if (status != MagickFalse)
1483 {
cristy1e604812011-05-19 18:07:50 +00001484 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1485 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001486 (*fail)++;
1487 continue;
1488 }
cristyb51dff52011-05-19 16:55:47 +00001489 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00001490 }
cristyb51dff52011-05-19 16:55:47 +00001491 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00001492 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1493 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00001494 return(test);
1495}
1496
1497/*
1498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1499% %
1500% %
1501% %
1502% V a l i d a t e C o n v e r t C o m m a n d %
1503% %
1504% %
1505% %
1506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1507%
1508% ValidateConvertCommand() validates the ImageMagick convert command line
1509% program and returns the number of validation tests that passed and failed.
1510%
1511% The format of the ValidateConvertCommand method is:
1512%
cristybb503372010-05-27 20:51:26 +00001513% size_t ValidateConvertCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001514% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001515% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001516%
1517% A description of each parameter follows:
1518%
1519% o image_info: the image info.
1520%
1521% o reference_filename: the reference image filename.
1522%
1523% o output_filename: the output image filename.
1524%
1525% o fail: return the number of validation tests that pass.
1526%
1527% o exception: return any errors or warnings in this structure.
1528%
1529*/
cristybb503372010-05-27 20:51:26 +00001530static size_t ValidateConvertCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001531 const char *reference_filename,const char *output_filename,size_t *fail,
1532 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001533{
1534 char
1535 **arguments,
1536 command[MaxTextExtent];
1537
1538 int
1539 number_arguments;
1540
1541 MagickBooleanType
1542 status;
1543
cristybb503372010-05-27 20:51:26 +00001544 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001545 i,
1546 j;
1547
cristybb503372010-05-27 20:51:26 +00001548 size_t
cristy3ed852e2009-09-05 21:47:34 +00001549 test;
1550
1551 test=0;
cristyb51dff52011-05-19 16:55:47 +00001552 (void) FormatLocaleFile(stdout,"validate convert command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00001553 for (i=0; convert_options[i] != (char *) NULL; i++)
1554 {
1555 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00001556 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) test++,
cristy6aa47ad2010-05-28 19:32:32 +00001557 convert_options[i]);
cristyb51dff52011-05-19 16:55:47 +00001558 (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
cristy3ed852e2009-09-05 21:47:34 +00001559 reference_filename,convert_options[i],reference_filename,output_filename);
1560 arguments=StringToArgv(command,&number_arguments);
1561 if (arguments == (char **) NULL)
1562 {
cristy1e604812011-05-19 18:07:50 +00001563 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1564 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001565 (*fail)++;
1566 continue;
1567 }
1568 status=ConvertImageCommand(image_info,number_arguments,arguments,
1569 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00001570 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00001571 arguments[j]=DestroyString(arguments[j]);
1572 arguments=(char **) RelinquishMagickMemory(arguments);
1573 if (status != MagickFalse)
1574 {
cristy1e604812011-05-19 18:07:50 +00001575 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1576 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001577 (*fail)++;
1578 continue;
1579 }
cristyb51dff52011-05-19 16:55:47 +00001580 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00001581 }
cristyb51dff52011-05-19 16:55:47 +00001582 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00001583 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1584 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00001585 return(test);
1586}
1587
1588/*
1589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1590% %
1591% %
1592% %
1593% V a l i d a t e I d e n t i f y C o m m a n d %
1594% %
1595% %
1596% %
1597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1598%
1599% ValidateIdentifyCommand() validates the ImageMagick identify command line
1600% program and returns the number of validation tests that passed and failed.
1601%
1602% The format of the ValidateIdentifyCommand method is:
1603%
cristybb503372010-05-27 20:51:26 +00001604% size_t ValidateIdentifyCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001605% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001606% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001607%
1608% A description of each parameter follows:
1609%
1610% o image_info: the image info.
1611%
1612% o reference_filename: the reference image filename.
1613%
1614% o output_filename: the output image filename.
1615%
1616% o fail: return the number of validation tests that pass.
1617%
1618% o exception: return any errors or warnings in this structure.
1619%
1620*/
cristybb503372010-05-27 20:51:26 +00001621static size_t ValidateIdentifyCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001622 const char *reference_filename,const char *output_filename,size_t *fail,
1623 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001624{
1625 char
1626 **arguments,
1627 command[MaxTextExtent];
1628
1629 int
1630 number_arguments;
1631
1632 MagickBooleanType
1633 status;
1634
cristybb503372010-05-27 20:51:26 +00001635 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001636 i,
1637 j;
1638
cristybb503372010-05-27 20:51:26 +00001639 size_t
cristy3ed852e2009-09-05 21:47:34 +00001640 test;
1641
1642 (void) output_filename;
1643 test=0;
cristyb51dff52011-05-19 16:55:47 +00001644 (void) FormatLocaleFile(stdout,"validate identify command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00001645 for (i=0; identify_options[i] != (char *) NULL; i++)
1646 {
1647 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00001648 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) test++,
cristy6aa47ad2010-05-28 19:32:32 +00001649 identify_options[i]);
cristyb51dff52011-05-19 16:55:47 +00001650 (void) FormatLocaleString(command,MaxTextExtent,"%s %s",
cristy3ed852e2009-09-05 21:47:34 +00001651 identify_options[i],reference_filename);
1652 arguments=StringToArgv(command,&number_arguments);
1653 if (arguments == (char **) NULL)
1654 {
cristy1e604812011-05-19 18:07:50 +00001655 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1656 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001657 (*fail)++;
1658 continue;
1659 }
1660 status=IdentifyImageCommand(image_info,number_arguments,arguments,
1661 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00001662 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00001663 arguments[j]=DestroyString(arguments[j]);
1664 arguments=(char **) RelinquishMagickMemory(arguments);
1665 if (status != MagickFalse)
1666 {
cristy1e604812011-05-19 18:07:50 +00001667 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1668 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001669 (*fail)++;
1670 continue;
1671 }
cristyb51dff52011-05-19 16:55:47 +00001672 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00001673 }
cristyb51dff52011-05-19 16:55:47 +00001674 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00001675 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1676 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00001677 return(test);
1678}
1679
1680/*
1681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1682% %
1683% %
1684% %
1685% 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 %
1686% %
1687% %
1688% %
1689%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1690%
1691% ValidateImageFormatsInMemory() validates the ImageMagick image formats in
1692% memory and returns the number of validation tests that passed and failed.
1693%
1694% The format of the ValidateImageFormatsInMemory method is:
1695%
cristybb503372010-05-27 20:51:26 +00001696% size_t ValidateImageFormatsInMemory(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001697% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001698% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001699%
1700% A description of each parameter follows:
1701%
1702% o image_info: the image info.
1703%
1704% o reference_filename: the reference image filename.
1705%
1706% o output_filename: the output image filename.
1707%
1708% o fail: return the number of validation tests that pass.
1709%
1710% o exception: return any errors or warnings in this structure.
1711%
1712*/
glennrp4084cda2012-12-11 14:13:35 +00001713
cristy725833f2012-12-13 17:40:53 +00001714/*
1715 Enable this to count remaining $TMPDIR/magick-* files. Note that the count
1716 includes any files left over from other runs.
1717*/
1718#undef MagickCountTempFiles
glennrp4084cda2012-12-11 14:13:35 +00001719
cristybb503372010-05-27 20:51:26 +00001720static size_t ValidateImageFormatsInMemory(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001721 const char *reference_filename,const char *output_filename,size_t *fail,
1722 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001723{
1724 char
glennrp4084cda2012-12-11 14:13:35 +00001725#ifdef MagickCountTempFiles
glennrp4084cda2012-12-11 14:13:35 +00001726 path[MaxTextExtent],
cristy77b33ba2013-03-28 13:23:13 +00001727 SystemCommand[MaxTextExtent],
glennrp4084cda2012-12-11 14:13:35 +00001728#endif
cristy3ed852e2009-09-05 21:47:34 +00001729 size[MaxTextExtent];
1730
1731 const MagickInfo
1732 *magick_info;
1733
1734 double
1735 distortion,
1736 fuzz;
1737
1738 Image
1739 *difference_image,
cristy2c404222012-06-10 15:36:30 +00001740 *ping_image,
cristy6b9ae3f2012-06-10 15:39:34 +00001741 *reconstruct_image,
cristy100b8d92012-01-08 00:32:49 +00001742 *reference_image;
cristy3ed852e2009-09-05 21:47:34 +00001743
1744 MagickBooleanType
1745 status;
1746
cristybb503372010-05-27 20:51:26 +00001747 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001748 i,
1749 j;
1750
1751 size_t
cristy100b8d92012-01-08 00:32:49 +00001752 length,
1753 test;
cristy3ed852e2009-09-05 21:47:34 +00001754
1755 unsigned char
1756 *blob;
1757
cristy3ed852e2009-09-05 21:47:34 +00001758 test=0;
cristyb51dff52011-05-19 16:55:47 +00001759 (void) FormatLocaleFile(stdout,"validate image formats in memory:\n");
glennrp4084cda2012-12-11 14:13:35 +00001760
1761#ifdef MagickCountTempFiles
1762 (void)GetPathTemplate(path);
glennrp33fb8032013-01-07 18:43:03 +00001763 /* Remove file template except for the leading "/path/to/magick-" */
glennrp4084cda2012-12-11 14:13:35 +00001764 path[strlen(path)-17]='\0';
1765 (void) FormatLocaleFile(stdout," tmp path is '%s*'\n",path);
1766#endif
1767
cristy3ed852e2009-09-05 21:47:34 +00001768 for (i=0; reference_formats[i].magick != (char *) NULL; i++)
1769 {
1770 magick_info=GetMagickInfo(reference_formats[i].magick,exception);
1771 if ((magick_info == (const MagickInfo *) NULL) ||
1772 (magick_info->decoder == (DecodeImageHandler *) NULL) ||
1773 (magick_info->encoder == (EncodeImageHandler *) NULL))
1774 continue;
cristy5f1c1ff2010-12-23 21:38:06 +00001775 for (j=0; reference_types[j].type != UndefinedType; j++)
cristy3ed852e2009-09-05 21:47:34 +00001776 {
1777 /*
1778 Generate reference image.
1779 */
1780 CatchException(exception);
cristy1e604812011-05-19 18:07:50 +00001781 (void) FormatLocaleFile(stdout," test %.20g: %s/%s/%s/%.20g-bits",
1782 (double) (test++),reference_formats[i].magick,CommandOptionToMnemonic(
cristy7998e5f2009-10-08 02:45:33 +00001783 MagickCompressOptions,reference_formats[i].compression),
cristy042ee782011-04-22 18:48:30 +00001784 CommandOptionToMnemonic(MagickTypeOptions,reference_types[j].type),
cristy75a26232010-06-03 17:15:02 +00001785 (double) reference_types[j].depth);
cristy3ed852e2009-09-05 21:47:34 +00001786 (void) CopyMagickString(image_info->filename,reference_filename,
1787 MaxTextExtent);
1788 reference_image=ReadImage(image_info,exception);
1789 if (reference_image == (Image *) NULL)
1790 {
cristy1e604812011-05-19 18:07:50 +00001791 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1792 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001793 (*fail)++;
1794 continue;
1795 }
1796 /*
1797 Write reference image.
1798 */
cristyb51dff52011-05-19 16:55:47 +00001799 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",
cristy75a26232010-06-03 17:15:02 +00001800 (double) reference_image->columns,(double) reference_image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001801 (void) CloneString(&image_info->size,size);
1802 image_info->depth=reference_types[j].depth;
cristyb51dff52011-05-19 16:55:47 +00001803 (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001804 reference_formats[i].magick,output_filename);
cristy018f07f2011-09-04 21:15:19 +00001805 status=SetImageType(reference_image,reference_types[j].type,exception);
cristy3ed852e2009-09-05 21:47:34 +00001806 if (status == MagickFalse)
1807 {
cristy1e604812011-05-19 18:07:50 +00001808 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1809 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001810 (*fail)++;
1811 reference_image=DestroyImage(reference_image);
1812 continue;
1813 }
cristy8a11cb12011-10-19 23:53:34 +00001814 status=SetImageDepth(reference_image,reference_types[j].depth,exception);
cristy3ed852e2009-09-05 21:47:34 +00001815 if (status == MagickFalse)
1816 {
cristy1e604812011-05-19 18:07:50 +00001817 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1818 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001819 (*fail)++;
1820 reference_image=DestroyImage(reference_image);
1821 continue;
1822 }
cristy7998e5f2009-10-08 02:45:33 +00001823 reference_image->compression=reference_formats[i].compression;
cristy6f9e0d32011-08-28 16:32:09 +00001824 status=WriteImage(image_info,reference_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001825 reference_image=DestroyImage(reference_image);
1826 if (status == MagickFalse)
1827 {
cristy1e604812011-05-19 18:07:50 +00001828 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1829 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001830 (*fail)++;
1831 continue;
1832 }
1833 /*
cristy2c404222012-06-10 15:36:30 +00001834 Ping reference image.
cristy3ed852e2009-09-05 21:47:34 +00001835 */
cristyb51dff52011-05-19 16:55:47 +00001836 (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001837 reference_formats[i].magick,output_filename);
cristy2c404222012-06-10 15:36:30 +00001838 ping_image=PingImage(image_info,exception);
1839 if (ping_image == (Image *) NULL)
1840 {
1841 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1842 GetMagickModule());
1843 (*fail)++;
1844 continue;
1845 }
1846 ping_image=DestroyImage(ping_image);
1847 /*
1848 Read reference image.
1849 */
cristy3ed852e2009-09-05 21:47:34 +00001850 reference_image=ReadImage(image_info,exception);
1851 if (reference_image == (Image *) NULL)
1852 {
cristy1e604812011-05-19 18:07:50 +00001853 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1854 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001855 (*fail)++;
1856 continue;
1857 }
1858 /*
1859 Write reference image.
1860 */
cristyb51dff52011-05-19 16:55:47 +00001861 (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001862 reference_formats[i].magick,output_filename);
1863 (void) CopyMagickString(image_info->magick,reference_formats[i].magick,
1864 MaxTextExtent);
1865 reference_image->depth=reference_types[j].depth;
cristy7998e5f2009-10-08 02:45:33 +00001866 reference_image->compression=reference_formats[i].compression;
cristy3ed852e2009-09-05 21:47:34 +00001867 length=8192;
1868 blob=ImageToBlob(image_info,reference_image,&length,exception);
1869 if (blob == (unsigned char *) NULL)
1870 {
cristy1e604812011-05-19 18:07:50 +00001871 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1872 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001873 (*fail)++;
1874 reference_image=DestroyImage(reference_image);
1875 continue;
1876 }
1877 /*
cristy2c404222012-06-10 15:36:30 +00001878 Ping reference blob.
1879 */
1880 ping_image=PingBlob(image_info,blob,length,exception);
1881 if (ping_image == (Image *) NULL)
1882 {
1883 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1884 GetMagickModule());
1885 (*fail)++;
1886 blob=(unsigned char *) RelinquishMagickMemory(blob);
1887 continue;
1888 }
1889 ping_image=DestroyImage(ping_image);
1890 /*
cristy3ed852e2009-09-05 21:47:34 +00001891 Read reconstruct image.
1892 */
cristyb51dff52011-05-19 16:55:47 +00001893 (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001894 reference_formats[i].magick,output_filename);
1895 reconstruct_image=BlobToImage(image_info,blob,length,exception);
1896 blob=(unsigned char *) RelinquishMagickMemory(blob);
1897 if (reconstruct_image == (Image *) NULL)
1898 {
cristy1e604812011-05-19 18:07:50 +00001899 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1900 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001901 (*fail)++;
1902 reference_image=DestroyImage(reference_image);
1903 continue;
1904 }
1905 /*
1906 Compare reference to reconstruct image.
1907 */
cristy93540ab2013-03-30 19:59:41 +00001908 fuzz=0.003; /* grayscale */
cristy3ed852e2009-09-05 21:47:34 +00001909 if (reference_formats[i].fuzz != 0.0)
1910 fuzz=reference_formats[i].fuzz;
cristy8a9106f2011-07-05 14:39:26 +00001911 difference_image=CompareImages(reference_image,reconstruct_image,
cristy864c6a82012-06-19 16:45:22 +00001912 RootMeanSquaredErrorMetric,&distortion,exception);
cristy3ed852e2009-09-05 21:47:34 +00001913 reconstruct_image=DestroyImage(reconstruct_image);
1914 reference_image=DestroyImage(reference_image);
1915 if (difference_image == (Image *) NULL)
1916 {
cristy1e604812011-05-19 18:07:50 +00001917 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1918 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001919 (*fail)++;
1920 continue;
1921 }
1922 difference_image=DestroyImage(difference_image);
cristy14154222012-06-15 23:21:49 +00001923 if ((QuantumScale*distortion) > fuzz)
cristy3ed852e2009-09-05 21:47:34 +00001924 {
cristyb51dff52011-05-19 16:55:47 +00001925 (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
cristy14154222012-06-15 23:21:49 +00001926 QuantumScale*distortion);
cristy3ed852e2009-09-05 21:47:34 +00001927 (*fail)++;
1928 continue;
1929 }
glennrp4084cda2012-12-11 14:13:35 +00001930#ifdef MagickCountTempFiles
1931 (void) FormatLocaleFile(stdout,"... pass, ");
1932 (void) fflush(stdout);
1933 SystemCommand[0]='\0';
cristy77b33ba2013-03-28 13:23:13 +00001934 (void) strncat(SystemCommand,"echo `ls ",9);
1935 (void) strncat(SystemCommand,path,MaxTextExtent-31);
1936 (void) strncat(SystemCommand,"* | wc -w` tmp files.",20);
1937 (void) system(SystemCommand);
glennrp4084cda2012-12-11 14:13:35 +00001938 (void) fflush(stdout);
1939#else
1940 (void) FormatLocaleFile(stdout,"... pass\n");
1941#endif
cristy3ed852e2009-09-05 21:47:34 +00001942 }
1943 }
cristyb51dff52011-05-19 16:55:47 +00001944 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00001945 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1946 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00001947 return(test);
1948}
1949
1950/*
1951%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1952% %
1953% %
1954% %
1955% 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 %
1956% %
1957% %
1958% %
1959%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1960%
1961% ValidateImageFormatsOnDisk() validates the ImageMagick image formats on disk
1962% and returns the number of validation tests that passed and failed.
1963%
1964% The format of the ValidateImageFormatsOnDisk method is:
1965%
cristybb503372010-05-27 20:51:26 +00001966% size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001967% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001968% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001969%
1970% A description of each parameter follows:
1971%
1972% o image_info: the image info.
1973%
1974% o reference_filename: the reference image filename.
1975%
1976% o output_filename: the output image filename.
1977%
1978% o fail: return the number of validation tests that pass.
1979%
1980% o exception: return any errors or warnings in this structure.
1981%
1982*/
cristybb503372010-05-27 20:51:26 +00001983static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001984 const char *reference_filename,const char *output_filename,size_t *fail,
1985 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001986{
1987 char
1988 size[MaxTextExtent];
1989
1990 const MagickInfo
1991 *magick_info;
1992
1993 double
1994 distortion,
1995 fuzz;
1996
1997 Image
1998 *difference_image,
1999 *reference_image,
2000 *reconstruct_image;
2001
2002 MagickBooleanType
2003 status;
2004
cristybb503372010-05-27 20:51:26 +00002005 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002006 i,
2007 j;
2008
cristybb503372010-05-27 20:51:26 +00002009 size_t
cristy3ed852e2009-09-05 21:47:34 +00002010 test;
2011
2012 test=0;
cristyb51dff52011-05-19 16:55:47 +00002013 (void) FormatLocaleFile(stdout,"validate image formats on disk:\n");
cristy3ed852e2009-09-05 21:47:34 +00002014 for (i=0; reference_formats[i].magick != (char *) NULL; i++)
2015 {
2016 magick_info=GetMagickInfo(reference_formats[i].magick,exception);
2017 if ((magick_info == (const MagickInfo *) NULL) ||
2018 (magick_info->decoder == (DecodeImageHandler *) NULL) ||
2019 (magick_info->encoder == (EncodeImageHandler *) NULL))
2020 continue;
cristy5f1c1ff2010-12-23 21:38:06 +00002021 for (j=0; reference_types[j].type != UndefinedType; j++)
cristy3ed852e2009-09-05 21:47:34 +00002022 {
2023 /*
2024 Generate reference image.
2025 */
2026 CatchException(exception);
cristy1e604812011-05-19 18:07:50 +00002027 (void) FormatLocaleFile(stdout," test %.20g: %s/%s/%s/%.20g-bits",
2028 (double) (test++),reference_formats[i].magick,CommandOptionToMnemonic(
cristy7998e5f2009-10-08 02:45:33 +00002029 MagickCompressOptions,reference_formats[i].compression),
cristy042ee782011-04-22 18:48:30 +00002030 CommandOptionToMnemonic(MagickTypeOptions,reference_types[j].type),
cristy75a26232010-06-03 17:15:02 +00002031 (double) reference_types[j].depth);
cristy3ed852e2009-09-05 21:47:34 +00002032 (void) CopyMagickString(image_info->filename,reference_filename,
2033 MaxTextExtent);
2034 reference_image=ReadImage(image_info,exception);
2035 if (reference_image == (Image *) NULL)
2036 {
cristy1e604812011-05-19 18:07:50 +00002037 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2038 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002039 (*fail)++;
2040 continue;
2041 }
2042 /*
2043 Write reference image.
2044 */
cristyb51dff52011-05-19 16:55:47 +00002045 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",
cristy75a26232010-06-03 17:15:02 +00002046 (double) reference_image->columns,(double) reference_image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002047 (void) CloneString(&image_info->size,size);
2048 image_info->depth=reference_types[j].depth;
cristyb51dff52011-05-19 16:55:47 +00002049 (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00002050 reference_formats[i].magick,output_filename);
cristy018f07f2011-09-04 21:15:19 +00002051 status=SetImageType(reference_image,reference_types[j].type,exception);
cristy3ed852e2009-09-05 21:47:34 +00002052 if (status == MagickFalse)
2053 {
cristy1e604812011-05-19 18:07:50 +00002054 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2055 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002056 (*fail)++;
2057 reference_image=DestroyImage(reference_image);
2058 continue;
2059 }
cristy8a11cb12011-10-19 23:53:34 +00002060 status=SetImageDepth(reference_image,reference_types[j].depth,exception);
cristy3ed852e2009-09-05 21:47:34 +00002061 if (status == MagickFalse)
2062 {
cristy1e604812011-05-19 18:07:50 +00002063 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2064 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002065 (*fail)++;
2066 reference_image=DestroyImage(reference_image);
2067 continue;
2068 }
cristy7998e5f2009-10-08 02:45:33 +00002069 reference_image->compression=reference_formats[i].compression;
cristy6f9e0d32011-08-28 16:32:09 +00002070 status=WriteImage(image_info,reference_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002071 reference_image=DestroyImage(reference_image);
2072 if (status == MagickFalse)
2073 {
cristy1e604812011-05-19 18:07:50 +00002074 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2075 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002076 (*fail)++;
2077 continue;
2078 }
2079 /*
2080 Read reference image.
2081 */
cristyb51dff52011-05-19 16:55:47 +00002082 (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00002083 reference_formats[i].magick,output_filename);
2084 reference_image=ReadImage(image_info,exception);
2085 if (reference_image == (Image *) NULL)
2086 {
cristy1e604812011-05-19 18:07:50 +00002087 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2088 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002089 (*fail)++;
2090 continue;
2091 }
2092 /*
2093 Write reference image.
2094 */
cristyb51dff52011-05-19 16:55:47 +00002095 (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00002096 reference_formats[i].magick,output_filename);
2097 reference_image->depth=reference_types[j].depth;
cristy7998e5f2009-10-08 02:45:33 +00002098 reference_image->compression=reference_formats[i].compression;
cristy6f9e0d32011-08-28 16:32:09 +00002099 status=WriteImage(image_info,reference_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002100 if (status == MagickFalse)
2101 {
cristy1e604812011-05-19 18:07:50 +00002102 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2103 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002104 (*fail)++;
2105 reference_image=DestroyImage(reference_image);
2106 continue;
2107 }
2108 /*
2109 Read reconstruct image.
2110 */
cristyb51dff52011-05-19 16:55:47 +00002111 (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00002112 reference_formats[i].magick,output_filename);
2113 reconstruct_image=ReadImage(image_info,exception);
2114 if (reconstruct_image == (Image *) NULL)
2115 {
cristy1e604812011-05-19 18:07:50 +00002116 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2117 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002118 (*fail)++;
2119 reference_image=DestroyImage(reference_image);
2120 continue;
2121 }
2122 /*
2123 Compare reference to reconstruct image.
2124 */
cristy93540ab2013-03-30 19:59:41 +00002125 fuzz=0.003; /* grayscale */
cristy3ed852e2009-09-05 21:47:34 +00002126 if (reference_formats[i].fuzz != 0.0)
2127 fuzz=reference_formats[i].fuzz;
cristy8a9106f2011-07-05 14:39:26 +00002128 difference_image=CompareImages(reference_image,reconstruct_image,
cristy864c6a82012-06-19 16:45:22 +00002129 RootMeanSquaredErrorMetric,&distortion,exception);
cristy3ed852e2009-09-05 21:47:34 +00002130 reconstruct_image=DestroyImage(reconstruct_image);
2131 reference_image=DestroyImage(reference_image);
2132 if (difference_image == (Image *) NULL)
2133 {
cristy1e604812011-05-19 18:07:50 +00002134 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2135 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002136 (*fail)++;
2137 continue;
2138 }
2139 difference_image=DestroyImage(difference_image);
cristy14154222012-06-15 23:21:49 +00002140 if ((QuantumScale*distortion) > fuzz)
cristy3ed852e2009-09-05 21:47:34 +00002141 {
cristyb51dff52011-05-19 16:55:47 +00002142 (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
cristy14154222012-06-15 23:21:49 +00002143 QuantumScale*distortion);
cristy3ed852e2009-09-05 21:47:34 +00002144 (*fail)++;
2145 continue;
2146 }
cristyb51dff52011-05-19 16:55:47 +00002147 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00002148 }
2149 }
cristyb51dff52011-05-19 16:55:47 +00002150 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00002151 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2152 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00002153 return(test);
2154}
2155
2156/*
2157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2158% %
2159% %
2160% %
2161% 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 %
2162% %
2163% %
2164% %
2165%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2166%
2167% ValidateImportExportPixels() validates the pixel import and export methods.
2168% It returns the number of validation tests that passed and failed.
2169%
2170% The format of the ValidateImportExportPixels method is:
2171%
cristybb503372010-05-27 20:51:26 +00002172% size_t ValidateImportExportPixels(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00002173% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00002174% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002175%
2176% A description of each parameter follows:
2177%
2178% o image_info: the image info.
2179%
2180% o reference_filename: the reference image filename.
2181%
2182% o output_filename: the output image filename.
2183%
2184% o fail: return the number of validation tests that pass.
2185%
2186% o exception: return any errors or warnings in this structure.
2187%
2188*/
cristybb503372010-05-27 20:51:26 +00002189static size_t ValidateImportExportPixels(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00002190 const char *reference_filename,const char *output_filename,size_t *fail,
2191 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002192{
2193 double
2194 distortion;
2195
2196 Image
2197 *difference_image,
2198 *reference_image,
2199 *reconstruct_image;
2200
2201 MagickBooleanType
2202 status;
2203
cristybb503372010-05-27 20:51:26 +00002204 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002205 i,
2206 j;
2207
2208 size_t
2209 length;
2210
2211 unsigned char
2212 *pixels;
2213
cristybb503372010-05-27 20:51:26 +00002214 size_t
cristy3ed852e2009-09-05 21:47:34 +00002215 test;
2216
2217 (void) output_filename;
2218 test=0;
cristy1e604812011-05-19 18:07:50 +00002219 (void) FormatLocaleFile(stdout,
2220 "validate the import and export of image pixels:\n");
cristy3ed852e2009-09-05 21:47:34 +00002221 for (i=0; reference_map[i] != (char *) NULL; i++)
2222 {
2223 for (j=0; reference_storage[j].type != UndefinedPixel; j++)
2224 {
2225 /*
2226 Generate reference image.
2227 */
2228 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00002229 (void) FormatLocaleFile(stdout," test %.20g: %s/%s",(double) (test++),
cristy042ee782011-04-22 18:48:30 +00002230 reference_map[i],CommandOptionToMnemonic(MagickStorageOptions,
cristy3ed852e2009-09-05 21:47:34 +00002231 reference_storage[j].type));
2232 (void) CopyMagickString(image_info->filename,reference_filename,
2233 MaxTextExtent);
2234 reference_image=ReadImage(image_info,exception);
2235 if (reference_image == (Image *) NULL)
2236 {
cristy1e604812011-05-19 18:07:50 +00002237 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2238 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002239 (*fail)++;
2240 continue;
2241 }
2242 if (LocaleNCompare(reference_map[i],"cmy",3) == 0)
cristy2c404222012-06-10 15:36:30 +00002243 (void) SetImageColorspace(reference_image,CMYKColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +00002244 length=strlen(reference_map[i])*reference_image->columns*
2245 reference_image->rows*reference_storage[j].quantum;
2246 pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
2247 if (pixels == (unsigned char *) NULL)
2248 {
cristy1e604812011-05-19 18:07:50 +00002249 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2250 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002251 (*fail)++;
2252 reference_image=DestroyImage(reference_image);
2253 continue;
2254 }
2255 (void) ResetMagickMemory(pixels,0,length*sizeof(*pixels));
2256 status=ExportImagePixels(reference_image,0,0,reference_image->columns,
2257 reference_image->rows,reference_map[i],reference_storage[j].type,pixels,
2258 exception);
2259 if (status == MagickFalse)
2260 {
cristy1e604812011-05-19 18:07:50 +00002261 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2262 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002263 (*fail)++;
2264 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2265 reference_image=DestroyImage(reference_image);
2266 continue;
2267 }
cristyd55c9352011-10-20 15:29:22 +00002268 (void) SetImageBackgroundColor(reference_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002269 status=ImportImagePixels(reference_image,0,0,reference_image->columns,
2270 reference_image->rows,reference_map[i],reference_storage[j].type,
cristy018f07f2011-09-04 21:15:19 +00002271 pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002272 if (status == MagickFalse)
2273 {
cristy1e604812011-05-19 18:07:50 +00002274 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2275 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002276 (*fail)++;
2277 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2278 reference_image=DestroyImage(reference_image);
2279 continue;
2280 }
2281 /*
2282 Read reconstruct image.
2283 */
cristy9950d572011-10-01 18:22:35 +00002284 reconstruct_image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00002285 (void) SetImageExtent(reconstruct_image,reference_image->columns,
cristy655a8d12011-08-05 19:24:28 +00002286 reference_image->rows,exception);
2287 (void) SetImageColorspace(reconstruct_image,reference_image->colorspace,
2288 exception);
cristyd55c9352011-10-20 15:29:22 +00002289 (void) SetImageBackgroundColor(reconstruct_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002290 status=ImportImagePixels(reconstruct_image,0,0,reconstruct_image->columns,
2291 reconstruct_image->rows,reference_map[i],reference_storage[j].type,
cristy018f07f2011-09-04 21:15:19 +00002292 pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002293 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2294 if (status == MagickFalse)
2295 {
cristy1e604812011-05-19 18:07:50 +00002296 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2297 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002298 (*fail)++;
2299 reference_image=DestroyImage(reference_image);
2300 continue;
2301 }
2302 /*
2303 Compare reference to reconstruct image.
2304 */
cristy8a9106f2011-07-05 14:39:26 +00002305 difference_image=CompareImages(reference_image,reconstruct_image,
cristy864c6a82012-06-19 16:45:22 +00002306 RootMeanSquaredErrorMetric,&distortion,exception);
cristy3ed852e2009-09-05 21:47:34 +00002307 reconstruct_image=DestroyImage(reconstruct_image);
2308 reference_image=DestroyImage(reference_image);
2309 if (difference_image == (Image *) NULL)
2310 {
cristy1e604812011-05-19 18:07:50 +00002311 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2312 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002313 (*fail)++;
2314 continue;
2315 }
2316 difference_image=DestroyImage(difference_image);
cristy14154222012-06-15 23:21:49 +00002317 if ((QuantumScale*distortion) > 0.0)
cristy3ed852e2009-09-05 21:47:34 +00002318 {
cristyb51dff52011-05-19 16:55:47 +00002319 (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
cristy14154222012-06-15 23:21:49 +00002320 QuantumScale*distortion);
cristy3ed852e2009-09-05 21:47:34 +00002321 (*fail)++;
2322 continue;
2323 }
cristyb51dff52011-05-19 16:55:47 +00002324 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00002325 }
2326 }
cristyb51dff52011-05-19 16:55:47 +00002327 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00002328 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2329 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00002330 return(test);
2331}
2332
2333/*
2334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2335% %
2336% %
2337% %
2338% V a l i d a t e M o n t a g e C o m m a n d %
2339% %
2340% %
2341% %
2342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2343%
2344% ValidateMontageCommand() validates the ImageMagick montage command line
2345% program and returns the number of validation tests that passed and failed.
2346%
2347% The format of the ValidateMontageCommand method is:
2348%
cristybb503372010-05-27 20:51:26 +00002349% size_t ValidateMontageCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00002350% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00002351% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002352%
2353% A description of each parameter follows:
2354%
2355% o image_info: the image info.
2356%
2357% o reference_filename: the reference image filename.
2358%
2359% o output_filename: the output image filename.
2360%
2361% o fail: return the number of validation tests that pass.
2362%
2363% o exception: return any errors or warnings in this structure.
2364%
2365*/
cristybb503372010-05-27 20:51:26 +00002366static size_t ValidateMontageCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00002367 const char *reference_filename,const char *output_filename,size_t *fail,
2368 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002369{
2370 char
2371 **arguments,
2372 command[MaxTextExtent];
2373
2374 int
2375 number_arguments;
2376
2377 MagickBooleanType
2378 status;
2379
cristybb503372010-05-27 20:51:26 +00002380 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002381 i,
2382 j;
2383
cristybb503372010-05-27 20:51:26 +00002384 size_t
cristy3ed852e2009-09-05 21:47:34 +00002385 test;
2386
2387 test=0;
cristyb51dff52011-05-19 16:55:47 +00002388 (void) FormatLocaleFile(stdout,"validate montage command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00002389 for (i=0; montage_options[i] != (char *) NULL; i++)
2390 {
2391 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00002392 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
cristy6aa47ad2010-05-28 19:32:32 +00002393 montage_options[i]);
cristyb51dff52011-05-19 16:55:47 +00002394 (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
cristy3ed852e2009-09-05 21:47:34 +00002395 reference_filename,montage_options[i],reference_filename,
2396 output_filename);
2397 arguments=StringToArgv(command,&number_arguments);
2398 if (arguments == (char **) NULL)
2399 {
cristy1e604812011-05-19 18:07:50 +00002400 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2401 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002402 (*fail)++;
2403 continue;
2404 }
2405 status=MontageImageCommand(image_info,number_arguments,arguments,
2406 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00002407 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00002408 arguments[j]=DestroyString(arguments[j]);
2409 arguments=(char **) RelinquishMagickMemory(arguments);
2410 if (status != MagickFalse)
2411 {
cristy1e604812011-05-19 18:07:50 +00002412 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2413 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002414 (*fail)++;
2415 continue;
2416 }
cristyb51dff52011-05-19 16:55:47 +00002417 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00002418 }
cristyb51dff52011-05-19 16:55:47 +00002419 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00002420 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2421 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00002422 return(test);
2423}
2424
2425/*
2426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2427% %
2428% %
2429% %
2430% V a l i d a t e S t r e a m C o m m a n d %
2431% %
2432% %
2433% %
2434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2435%
2436% ValidateStreamCommand() validates the ImageMagick stream command line
2437% program and returns the number of validation tests that passed and failed.
2438%
2439% The format of the ValidateStreamCommand method is:
2440%
cristybb503372010-05-27 20:51:26 +00002441% size_t ValidateStreamCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00002442% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00002443% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002444%
2445% A description of each parameter follows:
2446%
2447% o image_info: the image info.
2448%
2449% o reference_filename: the reference image filename.
2450%
2451% o output_filename: the output image filename.
2452%
2453% o fail: return the number of validation tests that pass.
2454%
2455% o exception: return any errors or warnings in this structure.
2456%
2457*/
cristybb503372010-05-27 20:51:26 +00002458static size_t ValidateStreamCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00002459 const char *reference_filename,const char *output_filename,size_t *fail,
2460 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002461{
2462 char
2463 **arguments,
2464 command[MaxTextExtent];
2465
2466 int
2467 number_arguments;
2468
2469 MagickBooleanType
2470 status;
2471
cristybb503372010-05-27 20:51:26 +00002472 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002473 i,
2474 j;
2475
cristybb503372010-05-27 20:51:26 +00002476 size_t
cristy3ed852e2009-09-05 21:47:34 +00002477 test;
2478
2479 test=0;
cristyb51dff52011-05-19 16:55:47 +00002480 (void) FormatLocaleFile(stdout,"validate stream command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00002481 for (i=0; stream_options[i] != (char *) NULL; i++)
2482 {
2483 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00002484 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
cristy6aa47ad2010-05-28 19:32:32 +00002485 stream_options[i]);
cristyb51dff52011-05-19 16:55:47 +00002486 (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s",
cristy3ed852e2009-09-05 21:47:34 +00002487 stream_options[i],reference_filename,output_filename);
2488 arguments=StringToArgv(command,&number_arguments);
2489 if (arguments == (char **) NULL)
2490 {
cristy1e604812011-05-19 18:07:50 +00002491 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2492 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002493 (*fail)++;
2494 continue;
2495 }
2496 status=StreamImageCommand(image_info,number_arguments,arguments,
2497 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00002498 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00002499 arguments[j]=DestroyString(arguments[j]);
2500 arguments=(char **) RelinquishMagickMemory(arguments);
2501 if (status != MagickFalse)
2502 {
cristy1e604812011-05-19 18:07:50 +00002503 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2504 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002505 (*fail)++;
2506 continue;
2507 }
cristyb51dff52011-05-19 16:55:47 +00002508 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00002509 }
cristyb51dff52011-05-19 16:55:47 +00002510 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00002511 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2512 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00002513 return(test);
2514}
2515
2516/*
2517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2518% %
2519% %
2520% %
2521% M a i n %
2522% %
2523% %
2524% %
2525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2526%
2527%
2528*/
2529
2530static MagickBooleanType ValidateUsage(void)
2531{
2532 const char
2533 **p;
2534
2535 static const char
2536 *miscellaneous[]=
2537 {
2538 "-debug events display copious debugging information",
2539 "-help print program options",
2540 "-log format format of debugging information",
2541 "-validate type validation type",
2542 "-version print version information",
2543 (char *) NULL
2544 },
2545 *settings[]=
2546 {
2547 "-regard-warnings pay attention to warning messages",
2548 "-verbose print detailed information about the image",
2549 (char *) NULL
2550 };
2551
cristybb503372010-05-27 20:51:26 +00002552 (void) printf("Version: %s\n",GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00002553 (void) printf("Copyright: %s\n\n",GetMagickCopyright());
cristyb28d6472009-10-17 20:13:35 +00002554 (void) printf("Features: %s\n",GetMagickFeatures());
cristy3ed852e2009-09-05 21:47:34 +00002555 (void) printf("Usage: %s [options ...] reference-file\n",GetClientName());
2556 (void) printf("\nValidate Settings:\n");
2557 for (p=settings; *p != (char *) NULL; p++)
2558 (void) printf(" %s\n",*p);
2559 (void) printf("\nMiscellaneous Options:\n");
2560 for (p=miscellaneous; *p != (char *) NULL; p++)
2561 (void) printf(" %s\n",*p);
2562 return(MagickTrue);
2563}
2564
2565int main(int argc,char **argv)
2566{
2567#define DestroyValidate() \
2568{ \
cristy3ed852e2009-09-05 21:47:34 +00002569 image_info=DestroyImageInfo(image_info); \
2570 exception=DestroyExceptionInfo(exception); \
2571}
2572#define ThrowValidateException(asperity,tag,option) \
2573{ \
2574 (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
2575 option); \
2576 CatchException(exception); \
2577 DestroyValidate(); \
2578 return(MagickFalse); \
2579}
2580
2581 char
2582 output_filename[MaxTextExtent],
2583 reference_filename[MaxTextExtent],
2584 *option;
2585
2586 double
2587 elapsed_time,
2588 user_time;
2589
2590 ExceptionInfo
2591 *exception;
2592
2593 Image
2594 *reference_image;
2595
2596 ImageInfo
2597 *image_info;
2598
2599 MagickBooleanType
2600 regard_warnings,
2601 status;
2602
cristy9cafe592012-11-17 21:17:59 +00002603 MagickSizeType
2604 memory_resource,
2605 map_resource;
2606
cristybb503372010-05-27 20:51:26 +00002607 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002608 i;
2609
2610 TimerInfo
2611 *timer;
2612
cristybb503372010-05-27 20:51:26 +00002613 size_t
cristy3ed852e2009-09-05 21:47:34 +00002614 fail,
2615 iterations,
2616 tests;
2617
2618 ValidateType
2619 type;
2620
2621 /*
2622 Validate the ImageMagick image processing suite.
2623 */
cristyb4d552c2012-12-13 15:42:17 +00002624 MagickCoreGenesis(*argv,MagickTrue);
cristyef2fdc62012-12-12 11:16:48 +00002625 (void) setlocale(LC_ALL,"");
2626 (void) setlocale(LC_NUMERIC,"C");
cristy3ed852e2009-09-05 21:47:34 +00002627 iterations=1;
2628 status=MagickFalse;
2629 type=AllValidate;
2630 regard_warnings=MagickFalse;
cristyd8862902011-02-20 21:12:27 +00002631 (void) regard_warnings;
cristy3ed852e2009-09-05 21:47:34 +00002632 exception=AcquireExceptionInfo();
2633 image_info=AcquireImageInfo();
2634 (void) CopyMagickString(image_info->filename,ReferenceFilename,MaxTextExtent);
cristybb503372010-05-27 20:51:26 +00002635 for (i=1; i < (ssize_t) argc; i++)
cristy3ed852e2009-09-05 21:47:34 +00002636 {
2637 option=argv[i];
cristy042ee782011-04-22 18:48:30 +00002638 if (IsCommandOption(option) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002639 {
2640 (void) CopyMagickString(image_info->filename,option,MaxTextExtent);
2641 continue;
2642 }
2643 switch (*(option+1))
2644 {
2645 case 'b':
2646 {
2647 if (LocaleCompare("bench",option+1) == 0)
2648 {
cristye27293e2009-12-18 02:53:20 +00002649 iterations=StringToUnsignedLong(argv[++i]);
cristy3ed852e2009-09-05 21:47:34 +00002650 break;
2651 }
2652 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2653 }
2654 case 'd':
2655 {
2656 if (LocaleCompare("debug",option+1) == 0)
2657 {
2658 (void) SetLogEventMask(argv[++i]);
2659 break;
2660 }
2661 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2662 }
2663 case 'h':
2664 {
2665 if (LocaleCompare("help",option+1) == 0)
2666 {
2667 (void) ValidateUsage();
2668 return(0);
2669 }
2670 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2671 }
2672 case 'l':
2673 {
2674 if (LocaleCompare("log",option+1) == 0)
2675 {
2676 if (*option != '+')
2677 (void) SetLogFormat(argv[i+1]);
2678 break;
2679 }
2680 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2681 }
2682 case 'r':
2683 {
2684 if (LocaleCompare("regard-warnings",option+1) == 0)
2685 {
2686 regard_warnings=MagickTrue;
2687 break;
2688 }
2689 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2690 }
2691 case 'v':
2692 {
2693 if (LocaleCompare("validate",option+1) == 0)
2694 {
cristybb503372010-05-27 20:51:26 +00002695 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002696 validate;
2697
2698 if (*option == '+')
2699 break;
2700 i++;
cristybb503372010-05-27 20:51:26 +00002701 if (i == (ssize_t) argc)
cristy3ed852e2009-09-05 21:47:34 +00002702 ThrowValidateException(OptionError,"MissingArgument",option);
cristy042ee782011-04-22 18:48:30 +00002703 validate=ParseCommandOption(MagickValidateOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +00002704 argv[i]);
2705 if (validate < 0)
2706 ThrowValidateException(OptionError,"UnrecognizedValidateType",
2707 argv[i]);
2708 type=(ValidateType) validate;
2709 break;
2710 }
2711 if ((LocaleCompare("version",option+1) == 0) ||
2712 (LocaleCompare("-version",option+1) == 0))
2713 {
cristyb51dff52011-05-19 16:55:47 +00002714 (void) FormatLocaleFile(stdout,"Version: %s\n",
cristybb503372010-05-27 20:51:26 +00002715 GetMagickVersion((size_t *) NULL));
cristy1e604812011-05-19 18:07:50 +00002716 (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
2717 GetMagickCopyright());
2718 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
2719 GetMagickFeatures());
cristy3ed852e2009-09-05 21:47:34 +00002720 return(0);
2721 }
2722 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2723 }
2724 default:
2725 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2726 }
2727 }
cristy205e21f2009-09-28 19:01:46 +00002728 timer=(TimerInfo *) NULL;
cristy8b76e552009-09-28 18:20:20 +00002729 if (iterations > 1)
2730 timer=AcquireTimerInfo();
cristy3ed852e2009-09-05 21:47:34 +00002731 reference_image=ReadImage(image_info,exception);
2732 tests=0;
2733 fail=0;
2734 if (reference_image == (Image *) NULL)
2735 fail++;
2736 else
2737 {
2738 if (LocaleCompare(image_info->filename,ReferenceFilename) == 0)
2739 (void) CopyMagickString(reference_image->magick,ReferenceImageFormat,
2740 MaxTextExtent);
2741 (void) AcquireUniqueFilename(reference_filename);
2742 (void) AcquireUniqueFilename(output_filename);
2743 (void) CopyMagickString(reference_image->filename,reference_filename,
2744 MaxTextExtent);
cristy6f9e0d32011-08-28 16:32:09 +00002745 status=WriteImage(image_info,reference_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002746 reference_image=DestroyImage(reference_image);
2747 if (status == MagickFalse)
2748 fail++;
2749 else
2750 {
cristyb51dff52011-05-19 16:55:47 +00002751 (void) FormatLocaleFile(stdout,"Version: %s\n",
cristybb503372010-05-27 20:51:26 +00002752 GetMagickVersion((size_t *) NULL));
cristyb51dff52011-05-19 16:55:47 +00002753 (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002754 GetMagickCopyright());
cristy1e604812011-05-19 18:07:50 +00002755 (void) FormatLocaleFile(stdout,
2756 "ImageMagick Validation Suite (%s)\n\n",CommandOptionToMnemonic(
2757 MagickValidateOptions,(ssize_t) type));
cristy80e870e2013-05-07 12:23:02 +00002758 if ((type & ColorspaceValidate) != 0)
2759 tests+=ValidateColorspaceCommand(image_info,reference_filename,
2760 output_filename,&fail,exception);
cristy3ed852e2009-09-05 21:47:34 +00002761 if ((type & CompareValidate) != 0)
2762 tests+=ValidateCompareCommand(image_info,reference_filename,
2763 output_filename,&fail,exception);
2764 if ((type & CompositeValidate) != 0)
2765 tests+=ValidateCompositeCommand(image_info,reference_filename,
2766 output_filename,&fail,exception);
2767 if ((type & ConvertValidate) != 0)
2768 tests+=ValidateConvertCommand(image_info,reference_filename,
2769 output_filename,&fail,exception);
2770 if ((type & FormatsInMemoryValidate) != 0)
cristyf044a4d2012-11-17 21:10:20 +00002771 {
2772 (void) FormatLocaleFile(stdout,"[pixel-cache: memory] ");
2773 tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
2774 output_filename,&fail,exception);
2775 (void) FormatLocaleFile(stdout,"[pixel-cache: memory-mapped] ");
cristy9cafe592012-11-17 21:17:59 +00002776 memory_resource=SetMagickResourceLimit(MemoryResource,0);
cristyf044a4d2012-11-17 21:10:20 +00002777 tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
2778 output_filename,&fail,exception);
2779 (void) FormatLocaleFile(stdout,"[pixel-cache: disk] ");
cristy9cafe592012-11-17 21:17:59 +00002780 map_resource=SetMagickResourceLimit(MapResource,0);
cristyf044a4d2012-11-17 21:10:20 +00002781 tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
2782 output_filename,&fail,exception);
cristy9cafe592012-11-17 21:17:59 +00002783 (void) SetMagickResourceLimit(MemoryResource,memory_resource);
2784 (void) SetMagickResourceLimit(MapResource,map_resource);
cristyf044a4d2012-11-17 21:10:20 +00002785 }
cristy3ed852e2009-09-05 21:47:34 +00002786 if ((type & FormatsOnDiskValidate) != 0)
cristybda201a2012-11-08 16:44:00 +00002787 {
cristy34c290f2012-11-09 00:44:12 +00002788 (void) FormatLocaleFile(stdout,"[pixel-cache: memory] ");
cristybda201a2012-11-08 16:44:00 +00002789 tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
2790 output_filename,&fail,exception);
cristy34c290f2012-11-09 00:44:12 +00002791 (void) FormatLocaleFile(stdout,"[pixel-cache: memory-mapped] ");
cristy9cafe592012-11-17 21:17:59 +00002792 memory_resource=SetMagickResourceLimit(MemoryResource,0);
cristybda201a2012-11-08 16:44:00 +00002793 tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
2794 output_filename,&fail,exception);
cristy34c290f2012-11-09 00:44:12 +00002795 (void) FormatLocaleFile(stdout,"[pixel-cache: disk] ");
cristy9cafe592012-11-17 21:17:59 +00002796 map_resource=SetMagickResourceLimit(MapResource,0);
cristybda201a2012-11-08 16:44:00 +00002797 tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
2798 output_filename,&fail,exception);
cristy9cafe592012-11-17 21:17:59 +00002799 (void) SetMagickResourceLimit(MemoryResource,memory_resource);
2800 (void) SetMagickResourceLimit(MapResource,map_resource);
cristybda201a2012-11-08 16:44:00 +00002801 }
cristy3ed852e2009-09-05 21:47:34 +00002802 if ((type & IdentifyValidate) != 0)
2803 tests+=ValidateIdentifyCommand(image_info,reference_filename,
2804 output_filename,&fail,exception);
2805 if ((type & ImportExportValidate) != 0)
2806 tests+=ValidateImportExportPixels(image_info,reference_filename,
2807 output_filename,&fail,exception);
2808 if ((type & MontageValidate) != 0)
2809 tests+=ValidateMontageCommand(image_info,reference_filename,
2810 output_filename,&fail,exception);
2811 if ((type & StreamValidate) != 0)
2812 tests+=ValidateStreamCommand(image_info,reference_filename,
2813 output_filename,&fail,exception);
cristyb51dff52011-05-19 16:55:47 +00002814 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00002815 "validation suite: %.20g tests; %.20g passed; %.20g failed.\n",
2816 (double) tests,(double) (tests-fail),(double) fail);
cristy3ed852e2009-09-05 21:47:34 +00002817 }
2818 (void) RelinquishUniqueFileResource(output_filename);
2819 (void) RelinquishUniqueFileResource(reference_filename);
2820 }
2821 if (exception->severity != UndefinedException)
2822 CatchException(exception);
2823 if (iterations > 1)
2824 {
2825 elapsed_time=GetElapsedTime(timer);
2826 user_time=GetUserTime(timer);
cristyb51dff52011-05-19 16:55:47 +00002827 (void) FormatLocaleFile(stderr,
cristy75a26232010-06-03 17:15:02 +00002828 "Performance: %.20gi %gips %0.3fu %ld:%02ld.%03ld\n",(double)
cristy6aa47ad2010-05-28 19:32:32 +00002829 iterations,1.0*iterations/elapsed_time,user_time,(long)
2830 (elapsed_time/60.0),(long) ceil(fmod(elapsed_time,60.0)),
2831 (long) (1000.0*(elapsed_time-floor(elapsed_time))));
cristy8b76e552009-09-28 18:20:20 +00002832 timer=DestroyTimerInfo(timer);
cristy3ed852e2009-09-05 21:47:34 +00002833 }
2834 DestroyValidate();
2835 MagickCoreTerminus();
2836 return(fail == 0 ? 0 : 1);
2837}