blob: b753bfe1b33c60de76c533bf3c033715bdc0ab11 [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 %
cristyde984cd2013-12-01 14:49:27 +000017% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000018% March 2001 %
19% %
20% %
cristyfe676ee2013-11-18 13:03:38 +000021% Copyright 1999-2014 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
cristya7230ee2013-07-25 11:51:29 +000063#define ReferenceEpsilon (QuantumRange*1.0e-2)
cristy8d24e062013-05-07 12:48:19 +000064
65/*
cristy3ed852e2009-09-05 21:47:34 +000066%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67% %
68% %
69% %
cristy572e0972013-05-07 12:51:28 +000070% V a l i d a t e C o l o r s p a c e s %
cristy80e870e2013-05-07 12:23:02 +000071% %
72% %
73% %
74%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75%
cristy572e0972013-05-07 12:51:28 +000076% ValidateColorspaces() validates the ImageMagick colorspaces and returns the
77% number of validation tests that passed and failed.
cristy80e870e2013-05-07 12:23:02 +000078%
cristy572e0972013-05-07 12:51:28 +000079% The format of the ValidateColorspaces method is:
cristy80e870e2013-05-07 12:23:02 +000080%
cristy572e0972013-05-07 12:51:28 +000081% size_t ValidateColorspaces(ImageInfo *image_info,size_t *fail,
82% ExceptionInfo *exception)
cristy80e870e2013-05-07 12:23:02 +000083%
84% A description of each parameter follows:
85%
86% o image_info: the image info.
87%
cristy80e870e2013-05-07 12:23:02 +000088% o fail: return the number of validation tests that pass.
89%
90% o exception: return any errors or warnings in this structure.
91%
92*/
cristy8d24e062013-05-07 12:48:19 +000093
94static void ConvertHSIToRGB(const double hue,const double saturation,
95 const double intensity,double *red,double *green,double *blue)
96{
97 double
98 h;
99
cristy8d24e062013-05-07 12:48:19 +0000100 h=360.0*hue;
101 h-=360.0*floor(h/360.0);
102 if (h < 120.0)
103 {
104 *blue=intensity*(1.0-saturation);
105 *red=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
106 (MagickPI/180.0)));
107 *green=3.0*intensity-*red-*blue;
108 }
109 else
110 if (h < 240.0)
111 {
112 h-=120.0;
113 *red=intensity*(1.0-saturation);
114 *green=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
115 (MagickPI/180.0)));
116 *blue=3.0*intensity-*red-*green;
117 }
118 else
119 {
120 h-=240.0;
121 *green=intensity*(1.0-saturation);
122 *blue=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
123 (MagickPI/180.0)));
124 *red=3.0*intensity-*green-*blue;
125 }
126 *red*=QuantumRange;
127 *green*=QuantumRange;
128 *blue*=QuantumRange;
129}
130
131static inline double MagickMin(const double x,const double y)
132{
133 if (x < y)
134 return(x);
135 return(y);
136}
137
138static void ConvertRGBToHSI(const double red,const double green,
139 const double blue,double *hue,double *saturation,double *intensity)
140{
141 double
142 alpha,
143 beta;
144
cristy8d24e062013-05-07 12:48:19 +0000145 *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0;
146 if (*intensity <= 0.0)
147 {
148 *hue=0.0;
149 *saturation=0.0;
150 return;
151 }
152 *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
153 QuantumScale*blue))/(*intensity);
154 alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
155 beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue);
156 *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
157 if (*hue < 0.0)
158 *hue+=1.0;
159}
160
161MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
162 const double lightness,double *red,double *green,double *blue)
163{
164 double
165 c,
166 h,
167 min,
168 x;
169
cristy8d24e062013-05-07 12:48:19 +0000170 h=hue*360.0;
171 if (lightness <= 0.5)
172 c=2.0*lightness*saturation;
173 else
174 c=(2.0-2.0*lightness)*saturation;
175 min=lightness-0.5*c;
176 h-=360.0*floor(h/360.0);
177 h/=60.0;
178 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
179 switch ((int) floor(h))
180 {
181 case 0:
182 {
183 *red=QuantumRange*(min+c);
184 *green=QuantumRange*(min+x);
185 *blue=QuantumRange*min;
186 break;
187 }
188 case 1:
189 {
190 *red=QuantumRange*(min+x);
191 *green=QuantumRange*(min+c);
192 *blue=QuantumRange*min;
193 break;
194 }
195 case 2:
196 {
197 *red=QuantumRange*min;
198 *green=QuantumRange*(min+c);
199 *blue=QuantumRange*(min+x);
200 break;
201 }
202 case 3:
203 {
204 *red=QuantumRange*min;
205 *green=QuantumRange*(min+x);
206 *blue=QuantumRange*(min+c);
207 break;
208 }
209 case 4:
210 {
211 *red=QuantumRange*(min+x);
212 *green=QuantumRange*min;
213 *blue=QuantumRange*(min+c);
214 break;
215 }
216 case 5:
217 {
218 *red=QuantumRange*(min+c);
219 *green=QuantumRange*min;
220 *blue=QuantumRange*(min+x);
221 break;
222 }
223 default:
224 {
225 *red=0.0;
226 *green=0.0;
227 *blue=0.0;
228 }
229 }
230}
231
232static inline double MagickMax(const double x,const double y)
233{
234 if (x > y)
235 return(x);
236 return(y);
237}
238
239MagickExport void ConvertRGBToHSL(const double red,const double green,
240 const double blue,double *hue,double *saturation,double *lightness)
241{
242 double
243 c,
244 max,
245 min;
246
cristy8d24e062013-05-07 12:48:19 +0000247 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
248 QuantumScale*blue));
249 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
250 QuantumScale*blue));
251 c=max-min;
252 *lightness=(max+min)/2.0;
253 if (c <= 0.0)
254 {
255 *hue=0.0;
256 *saturation=0.0;
257 return;
258 }
259 if (max == (QuantumScale*red))
260 {
261 *hue=(QuantumScale*green-QuantumScale*blue)/c;
262 if ((QuantumScale*green) < (QuantumScale*blue))
263 *hue+=6.0;
264 }
265 else
266 if (max == (QuantumScale*green))
267 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
268 else
269 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
270 *hue*=60.0/360.0;
271 if (*lightness <= 0.5)
272 *saturation=c/(2.0*(*lightness));
273 else
274 *saturation=c/(2.0-2.0*(*lightness));
275}
276
277static void ConvertHSVToRGB(const double hue,const double saturation,
278 const double value,double *red,double *green,double *blue)
279{
280 double
281 c,
282 h,
283 min,
284 x;
285
cristy8d24e062013-05-07 12:48:19 +0000286 h=hue*360.0;
287 c=value*saturation;
288 min=value-c;
289 h-=360.0*floor(h/360.0);
290 h/=60.0;
291 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
292 switch ((int) floor(h))
293 {
294 case 0:
295 {
296 *red=QuantumRange*(min+c);
297 *green=QuantumRange*(min+x);
298 *blue=QuantumRange*min;
299 break;
300 }
301 case 1:
302 {
303 *red=QuantumRange*(min+x);
304 *green=QuantumRange*(min+c);
305 *blue=QuantumRange*min;
306 break;
307 }
308 case 2:
309 {
310 *red=QuantumRange*min;
311 *green=QuantumRange*(min+c);
312 *blue=QuantumRange*(min+x);
313 break;
314 }
315 case 3:
316 {
317 *red=QuantumRange*min;
318 *green=QuantumRange*(min+x);
319 *blue=QuantumRange*(min+c);
320 break;
321 }
322 case 4:
323 {
324 *red=QuantumRange*(min+x);
325 *green=QuantumRange*min;
326 *blue=QuantumRange*(min+c);
327 break;
328 }
329 case 5:
330 {
331 *red=QuantumRange*(min+c);
332 *green=QuantumRange*min;
333 *blue=QuantumRange*(min+x);
334 break;
335 }
336 default:
337 {
338 *red=0.0;
339 *green=0.0;
340 *blue=0.0;
341 }
342 }
343}
344
345static inline void ConvertRGBToXYZ(const double red,const double green,
346 const double blue,double *X,double *Y,double *Z)
347{
348 double
349 b,
350 g,
351 r;
352
cristy8d24e062013-05-07 12:48:19 +0000353 r=QuantumScale*DecodePixelGamma(red);
354 g=QuantumScale*DecodePixelGamma(green);
355 b=QuantumScale*DecodePixelGamma(blue);
356 *X=0.41239558896741421610*r+0.35758343076371481710*g+0.18049264738170157350*b;
357 *Y=0.21258623078559555160*r+0.71517030370341084990*g+0.07220049864333622685*b;
358 *Z=0.01929721549174694484*r+0.11918386458084853180*g+0.95049712513157976600*b;
359}
360
361static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
362 double *L,double *a,double *b)
363{
364 double
365 x,
366 y,
367 z;
368
369 if ((X/D65X) > CIEEpsilon)
370 x=pow(X/D65X,1.0/3.0);
371 else
372 x=(CIEK*X/D65X+16.0)/116.0;
373 if ((Y/D65Y) > CIEEpsilon)
374 y=pow(Y/D65Y,1.0/3.0);
375 else
376 y=(CIEK*Y/D65Y+16.0)/116.0;
377 if ((Z/D65Z) > CIEEpsilon)
378 z=pow(Z/D65Z,1.0/3.0);
379 else
380 z=(CIEK*Z/D65Z+16.0)/116.0;
381 *L=((116.0*y)-16.0)/100.0;
382 *a=(500.0*(x-y))/255.0+0.5;
383 *b=(200.0*(y-z))/255.0+0.5;
384}
385
386static void ConvertRGBToLab(const double red,const double green,
387 const double blue,double *L,double *a,double *b)
388{
389 double
390 X,
391 Y,
392 Z;
393
394 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
395 ConvertXYZToLab(X,Y,Z,L,a,b);
396}
397
398static inline void ConvertLabToXYZ(const double L,const double a,const double b,
399 double *X,double *Y,double *Z)
400{
401 double
402 x,
403 y,
404 z;
405
406 y=(L+16.0)/116.0;
407 x=y+a/500.0;
408 z=y-b/200.0;
409 if ((x*x*x) > CIEEpsilon)
410 x=(x*x*x);
411 else
412 x=(116.0*x-16.0)/CIEK;
413 if ((y*y*y) > CIEEpsilon)
414 y=(y*y*y);
415 else
416 y=L/CIEK;
417 if ((z*z*z) > CIEEpsilon)
418 z=(z*z*z);
419 else
420 z=(116.0*z-16.0)/CIEK;
421 *X=D65X*x;
422 *Y=D65Y*y;
423 *Z=D65Z*z;
424}
425
426static inline void ConvertXYZToRGB(const double x,const double y,const double z,
427 double *red,double *green,double *blue)
428{
429 double
430 b,
431 g,
432 r;
433
cristy8d24e062013-05-07 12:48:19 +0000434 r=3.2406*x-1.5372*y-0.4986*z;
435 g=(-0.9689*x+1.8758*y+0.0415*z);
436 b=0.0557*x-0.2040*y+1.0570*z;
437 *red=EncodePixelGamma(QuantumRange*r);
438 *green=EncodePixelGamma(QuantumRange*g);
439 *blue=EncodePixelGamma(QuantumRange*b);
440}
441
442static inline void ConvertLabToRGB(const double L,const double a,
443 const double b,double *red,double *green,double *blue)
444{
445 double
446 X,
447 Y,
448 Z;
449
450 ConvertLabToXYZ(L*100.0,255.0*(a-0.5),255.0*(b-0.5),&X,&Y,&Z);
451 ConvertXYZToRGB(X,Y,Z,red,green,blue);
452}
453
454static void ConvertRGBToYPbPr(const double red,const double green,
455 const double blue,double *Y,double *Pb,double *Pr)
456{
cristy8d24e062013-05-07 12:48:19 +0000457 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
458 *Pb=QuantumScale*((-0.1687367)*red-0.331264*green+0.5*blue)+0.5;
459 *Pr=QuantumScale*(0.5*red-0.418688*green-0.081312*blue)+0.5;
460}
461
462static void ConvertRGBToYCbCr(const double red,const double green,
463 const double blue,double *Y,double *Cb,double *Cr)
464{
cristy8d24e062013-05-07 12:48:19 +0000465 ConvertRGBToYPbPr(red,green,blue,Y,Cb,Cr);
466}
467
468static void ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr,
469 double *red,double *green,double *blue)
470{
cristy8d24e062013-05-07 12:48:19 +0000471 *red=QuantumRange*(0.99999999999914679361*Y-1.2188941887145875e-06*(Pb-0.5)+
472 1.4019995886561440468*(Pr-0.5));
473 *green=QuantumRange*(0.99999975910502514331*Y-0.34413567816504303521*(Pb-0.5)-
474 0.71413649331646789076*(Pr-0.5));
475 *blue=QuantumRange*(1.00000124040004623180*Y+1.77200006607230409200*(Pb-0.5)+
476 2.1453384174593273e-06*(Pr-0.5));
477}
478
479static void ConvertYCbCrToRGB(const double Y,const double Cb,
480 const double Cr,double *red,double *green,double *blue)
481{
cristy8d24e062013-05-07 12:48:19 +0000482 ConvertYPbPrToRGB(Y,Cb,Cr,red,green,blue);
483}
484
485static inline void ConvertLCHabToXYZ(const double luma,const double chroma,
486 const double hue,double *X,double *Y,double *Z)
487{
488 ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
489 sin(hue*MagickPI/180.0),X,Y,Z);
490}
491
492static void ConvertLCHabToRGB(const double luma,const double chroma,
493 const double hue,double *red,double *green,double *blue)
494{
495 double
496 X,
497 Y,
498 Z;
499
cristy6d897c72013-06-19 19:20:40 +0000500 ConvertLCHabToXYZ(luma*100.0,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z);
cristy8d24e062013-05-07 12:48:19 +0000501 ConvertXYZToRGB(X,Y,Z,red,green,blue);
502}
503
504static void ConvertRGBToHSV(const double red,const double green,
505 const double blue,double *hue,double *saturation,double *value)
506{
507 double
508 c,
509 max,
510 min;
511
cristy8d24e062013-05-07 12:48:19 +0000512 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
513 QuantumScale*blue));
514 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
515 QuantumScale*blue));
516 c=max-min;
517 *value=max;
518 if (c <= 0.0)
519 {
520 *hue=0.0;
521 *saturation=0.0;
522 return;
523 }
524 if (max == (QuantumScale*red))
525 {
526 *hue=(QuantumScale*green-QuantumScale*blue)/c;
527 if ((QuantumScale*green) < (QuantumScale*blue))
528 *hue+=6.0;
529 }
530 else
531 if (max == (QuantumScale*green))
532 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
533 else
534 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
535 *hue*=60.0/360.0;
536 *saturation=c/max;
537}
538
539static inline void ConvertXYZToLCHab(const double X,const double Y,
540 const double Z,double *luma,double *chroma,double *hue)
541{
542 double
543 a,
544 b;
545
546 ConvertXYZToLab(X,Y,Z,luma,&a,&b);
cristy846740b2013-06-19 18:19:55 +0000547 *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5))/255.0+0.5;
cristy6d897c72013-06-19 19:20:40 +0000548 *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI/360.0;
cristy8d24e062013-05-07 12:48:19 +0000549 if (*hue < 0.0)
550 *hue+=1.0;
551}
552
553static void ConvertRGBToLCHab(const double red,const double green,
554 const double blue,double *luma,double *chroma,double *hue)
555{
556 double
557 X,
558 Y,
559 Z;
560
561 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
562 ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue);
563}
564
565static inline void ConvertLMSToXYZ(const double L,const double M,const double S,
566 double *X,double *Y,double *Z)
567{
568 *X=1.096123820835514*L-0.278869000218287*M+0.182745179382773*S;
569 *Y=0.454369041975359*L+0.473533154307412*M+0.072097803717229*S;
570 *Z=(-0.009627608738429)*L-0.005698031216113*M+1.015325639954543*S;
571}
572
573static inline void ConvertLMSToRGB(const double L,const double M,
574 const double S,double *red,double *green,double *blue)
575{
576 double
577 X,
578 Y,
579 Z;
580
581 ConvertLMSToXYZ(L,M,S,&X,&Y,&Z);
582 ConvertXYZToRGB(X,Y,Z,red,green,blue);
583}
584
585static inline void ConvertXYZToLMS(const double x,const double y,
586 const double z,double *L,double *M,double *S)
587{
cristy8d24e062013-05-07 12:48:19 +0000588 *L=0.7328*x+0.4296*y-0.1624*z;
589 *M=(-0.7036*x+1.6975*y+0.0061*z);
590 *S=0.0030*x+0.0136*y+0.9834*z;
591}
592
593static void ConvertRGBToLMS(const double red,const double green,
594 const double blue,double *L,double *M,double *S)
595{
596 double
597 X,
598 Y,
599 Z;
600
601 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
602 ConvertXYZToLMS(X,Y,Z,L,M,S);
603}
604
605static inline double PerceptibleReciprocal(const double x)
606{
607 double
608 sign;
609
610 /*
611 Return 1/x where x is perceptible (not unlimited or infinitesimal).
612 */
613 sign=x < 0.0 ? -1.0 : 1.0;
614 if ((sign*x) >= MagickEpsilon)
615 return(1.0/x);
616 return(sign/MagickEpsilon);
617}
618
619static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
620 double *L,double *u,double *v)
621{
622 double
623 alpha;
624
625 if ((Y/D65Y) > CIEEpsilon)
626 *L=(double) (116.0*pow(Y/D65Y,1.0/3.0)-16.0);
627 else
628 *L=CIEK*(Y/D65Y);
629 alpha=PerceptibleReciprocal(X+15.0*Y+3.0*Z);
630 *u=13.0*(*L)*((4.0*alpha*X)-(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z)));
631 *v=13.0*(*L)*((9.0*alpha*Y)-(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z)));
632 *L/=100.0;
633 *u=(*u+134.0)/354.0;
634 *v=(*v+140.0)/262.0;
635}
636
637static void ConvertRGBToLuv(const double red,const double green,
638 const double blue,double *L,double *u,double *v)
639{
640 double
641 X,
642 Y,
643 Z;
644
645 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
646 ConvertXYZToLuv(X,Y,Z,L,u,v);
647}
648
649static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
650 double *X,double *Y,double *Z)
651{
652 if (L > (CIEK*CIEEpsilon))
653 *Y=(double) pow((L+16.0)/116.0,3.0);
654 else
655 *Y=L/CIEK;
656 *X=((*Y*((39.0*L/(v+13.0*L*(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z))))-5.0))+
657 5.0*(*Y))/((((52.0f*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/
658 3.0)-(-1.0/3.0));
659 *Z=(*X*(((52.0f*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/3.0))-
660 5.0*(*Y);
661}
662
663static inline void ConvertLuvToRGB(const double L,const double u,
664 const double v,double *red,double *green,double *blue)
665{
666 double
667 X,
668 Y,
669 Z;
670
671 ConvertLuvToXYZ(100.0*L,354.0*u-134.0,262.0*v-140.0,&X,&Y,&Z);
672 ConvertXYZToRGB(X,Y,Z,red,green,blue);
673}
674
675static void ConvertRGBToYDbDr(const double red,const double green,
676 const double blue,double *Y,double *Db,double *Dr)
677{
cristy8d24e062013-05-07 12:48:19 +0000678 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
679 *Db=QuantumScale*(-0.450*red-0.883*green+1.333*blue)+0.5;
680 *Dr=QuantumScale*(-1.333*red+1.116*green+0.217*blue)+0.5;
681}
682
683static void ConvertYDbDrToRGB(const double Y,const double Db,const double Dr,
684 double *red,double *green,double *blue)
685{
cristy8d24e062013-05-07 12:48:19 +0000686 *red=QuantumRange*(Y+9.2303716147657e-05*(Db-0.5)-0.52591263066186533*
687 (Dr-0.5));
688 *green=QuantumRange*(Y-0.12913289889050927*(Db-0.5)+0.26789932820759876*
689 (Dr-0.5));
690 *blue=QuantumRange*(Y+0.66467905997895482*(Db-0.5)-7.9202543533108e-05*
691 (Dr-0.5));
692}
693
694static void ConvertRGBToYIQ(const double red,const double green,
695 const double blue,double *Y,double *I,double *Q)
696{
cristy8d24e062013-05-07 12:48:19 +0000697 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
698 *I=QuantumScale*(0.595716*red-0.274453*green-0.321263*blue)+0.5;
699 *Q=QuantumScale*(0.211456*red-0.522591*green+0.311135*blue)+0.5;
700}
701
702static void ConvertYIQToRGB(const double Y,const double I,const double Q,
703 double *red,double *green,double *blue)
704{
cristy8d24e062013-05-07 12:48:19 +0000705 *red=QuantumRange*(Y+0.9562957197589482261*(I-0.5)+0.6210244164652610754*
706 (Q-0.5));
707 *green=QuantumRange*(Y-0.2721220993185104464*(I-0.5)-0.6473805968256950427*
708 (Q-0.5));
709 *blue=QuantumRange*(Y-1.1069890167364901945*(I-0.5)+1.7046149983646481374*
710 (Q-0.5));
711}
712
713static void ConvertRGBToYUV(const double red,const double green,
714 const double blue,double *Y,double *U,double *V)
715{
cristy8d24e062013-05-07 12:48:19 +0000716 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
717 *U=QuantumScale*((-0.147)*red-0.289*green+0.436*blue)+0.5;
718 *V=QuantumScale*(0.615*red-0.515*green-0.100*blue)+0.5;
719}
720
721static void ConvertYUVToRGB(const double Y,const double U,const double V,
722 double *red,double *green,double *blue)
723{
cristy8d24e062013-05-07 12:48:19 +0000724 *red=QuantumRange*(Y-3.945707070708279e-05*(U-0.5)+1.1398279671717170825*
725 (V-0.5));
726 *green=QuantumRange*(Y-0.3946101641414141437*(U-0.5)-0.5805003156565656797*
727 (V-0.5));
728 *blue=QuantumRange*(Y+2.0319996843434342537*(U-0.5)-4.813762626262513e-04*
729 (V-0.5));
730}
731
732static MagickBooleanType ValidateHSIToRGB()
733{
734 double
735 r,
736 g,
737 b;
738
cristyb8588ab2013-05-07 13:17:38 +0000739 (void) FormatLocaleFile(stdout," HSIToRGB");
cristy8d24e062013-05-07 12:48:19 +0000740 ConvertHSIToRGB(111.244375/360.0,0.295985,0.658734,&r,&g,&b);
741 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
742 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
743 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
744 return(MagickFalse);
745 return(MagickTrue);
746}
747
748static MagickBooleanType ValidateRGBToHSI()
749{
750 double
751 h,
752 i,
753 s;
754
cristyb8588ab2013-05-07 13:17:38 +0000755 (void) FormatLocaleFile(stdout," RGBToHSI");
cristy8d24e062013-05-07 12:48:19 +0000756 ConvertRGBToHSI(0.545877*QuantumRange,0.966567*QuantumRange,
757 0.463759*QuantumRange,&h,&s,&i);
758 if ((fabs(h-111.244374/360.0) >= ReferenceEpsilon) ||
759 (fabs(s-0.295985) >= ReferenceEpsilon) ||
760 (fabs(i-0.658734) >= ReferenceEpsilon))
761 return(MagickFalse);
762 return(MagickTrue);
763}
764
765static MagickBooleanType ValidateHSLToRGB()
766{
767 double
768 r,
769 g,
770 b;
771
cristyb8588ab2013-05-07 13:17:38 +0000772 (void) FormatLocaleFile(stdout," HSLToRGB");
cristy8d24e062013-05-07 12:48:19 +0000773 ConvertHSLToRGB(110.200859/360.0,0.882623,0.715163,&r,&g,&b);
774 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
775 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
776 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
777 return(MagickFalse);
778 return(MagickTrue);
779}
780
781static MagickBooleanType ValidateRGBToHSL()
782{
783 double
784 h,
785 l,
786 s;
787
cristyb8588ab2013-05-07 13:17:38 +0000788 (void) FormatLocaleFile(stdout," RGBToHSL");
cristy8d24e062013-05-07 12:48:19 +0000789 ConvertRGBToHSL(0.545877*QuantumRange,0.966567*QuantumRange,
790 0.463759*QuantumRange,&h,&s,&l);
791 if ((fabs(h-110.200859/360.0) >= ReferenceEpsilon) ||
792 (fabs(s-0.882623) >= ReferenceEpsilon) ||
793 (fabs(l-0.715163) >= ReferenceEpsilon))
794 return(MagickFalse);
795 return(MagickTrue);
796}
797
798static MagickBooleanType ValidateHSVToRGB()
799{
800 double
801 r,
802 g,
803 b;
804
cristyb8588ab2013-05-07 13:17:38 +0000805 (void) FormatLocaleFile(stdout," HSVToRGB");
cristy8d24e062013-05-07 12:48:19 +0000806 ConvertHSVToRGB(110.200859/360.0,0.520200,0.966567,&r,&g,&b);
807 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
808 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
809 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
810 return(MagickFalse);
811 return(MagickTrue);
812}
813
814static MagickBooleanType ValidateRGBToHSV()
815{
816 double
817 h,
818 s,
819 v;
820
cristyb8588ab2013-05-07 13:17:38 +0000821 (void) FormatLocaleFile(stdout," RGBToHSV");
cristy8d24e062013-05-07 12:48:19 +0000822 ConvertRGBToHSV(0.545877*QuantumRange,0.966567*QuantumRange,
823 0.463759*QuantumRange,&h,&s,&v);
824 if ((fabs(h-110.200859/360.0) >= ReferenceEpsilon) ||
825 (fabs(s-0.520200) >= ReferenceEpsilon) ||
826 (fabs(v-0.966567) >= ReferenceEpsilon))
827 return(MagickFalse);
828 return(MagickTrue);
829}
830
831static MagickBooleanType ValidateRGBToJPEGYCbCr()
832{
833 double
834 Cb,
835 Cr,
836 Y;
837
cristyb8588ab2013-05-07 13:17:38 +0000838 (void) FormatLocaleFile(stdout," RGBToJPEGYCbCr");
cristy8d24e062013-05-07 12:48:19 +0000839 ConvertRGBToYCbCr(0.545877*QuantumRange,0.966567*QuantumRange,
840 0.463759*QuantumRange,&Y,&Cb,&Cr);
841 if ((fabs(Y-0.783460) >= ReferenceEpsilon) ||
842 (fabs(Cb-0.319581) >= ReferenceEpsilon) ||
843 (fabs(Cr-0.330539) >= ReferenceEpsilon))
844 return(MagickFalse);
845 return(MagickTrue);
846}
847
848static MagickBooleanType ValidateJPEGYCbCrToRGB()
849{
850 double
851 r,
852 g,
853 b;
854
cristyb8588ab2013-05-07 13:17:38 +0000855 (void) FormatLocaleFile(stdout," JPEGYCbCrToRGB");
cristy8d24e062013-05-07 12:48:19 +0000856 ConvertYCbCrToRGB(0.783460,0.319581,0.330539,&r,&g,&b);
857 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
858 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
859 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
860 return(MagickFalse);
861 return(MagickTrue);
862}
863
864static MagickBooleanType ValidateLabToRGB()
865{
866 double
867 r,
868 g,
869 b;
870
cristyb8588ab2013-05-07 13:17:38 +0000871 (void) FormatLocaleFile(stdout," LabToRGB");
cristy8d24e062013-05-07 12:48:19 +0000872 ConvertLabToRGB(88.456154/100.0,-54.671483/255+0.5,51.662818/255.0+0.5,
873 &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 ValidateRGBToLab()
882{
883 double
884 a,
885 b,
886 L;
887
cristyb8588ab2013-05-07 13:17:38 +0000888 (void) FormatLocaleFile(stdout," RGBToLab");
cristy8d24e062013-05-07 12:48:19 +0000889 ConvertRGBToLab(0.545877*QuantumRange,0.966567*QuantumRange,
890 0.463759*QuantumRange,&L,&a,&b);
891 if ((fabs(L-(88.456154/100.0)) >= ReferenceEpsilon) ||
892 (fabs(a-(-54.671483/255.0+0.5)) >= ReferenceEpsilon) ||
893 (fabs(b-(51.662818/255.0+0.5)) >= ReferenceEpsilon))
894 return(MagickFalse);
895 return(MagickTrue);
896}
897
898static MagickBooleanType ValidateLchToRGB()
899{
900 double
901 b,
902 g,
903 r;
904
cristyb8588ab2013-05-07 13:17:38 +0000905 (void) FormatLocaleFile(stdout," LchToRGB");
cristya44ed132013-06-19 23:56:32 +0000906 ConvertLCHabToRGB(88.456154/100.0,75.219797/255.0+0.5,136.620717/360.0,
cristy8d24e062013-05-07 12:48:19 +0000907 &r,&g,&b);
908 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
909 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
910 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
911 return(MagickFalse);
912 return(MagickTrue);
913}
914
915static MagickBooleanType ValidateRGBToLch()
916{
917 double
918 c,
919 h,
920 L;
921
cristyb8588ab2013-05-07 13:17:38 +0000922 (void) FormatLocaleFile(stdout," RGBToLch");
cristy8d24e062013-05-07 12:48:19 +0000923 ConvertRGBToLCHab(0.545877*QuantumRange,0.966567*QuantumRange,
924 0.463759*QuantumRange,&L,&c,&h);
925 if ((fabs(L-88.456154/100.0) >= ReferenceEpsilon) ||
926 (fabs(c-(75.219797/255.0+0.5)) >= ReferenceEpsilon) ||
927 (fabs(h-(136.620717/255.0+0.5)) >= ReferenceEpsilon))
928 return(MagickFalse);
929 return(MagickTrue);
930}
931
932static MagickBooleanType ValidateRGBToLMS()
933{
934 double
935 L,
936 M,
937 S;
938
cristyb8588ab2013-05-07 13:17:38 +0000939 (void) FormatLocaleFile(stdout," RGBToLMS");
cristy8d24e062013-05-07 12:48:19 +0000940 ConvertRGBToLMS(0.545877*QuantumRange,0.966567*QuantumRange,
941 0.463759*QuantumRange,&L,&M,&S);
942 if ((fabs(L-0.611749) >= ReferenceEpsilon) ||
943 (fabs(M-0.910088) >= ReferenceEpsilon) ||
944 (fabs(S-0.294880) >= ReferenceEpsilon))
945 return(MagickFalse);
946 return(MagickTrue);
947}
948
949static MagickBooleanType ValidateLMSToRGB()
950{
951 double
952 r,
953 g,
954 b;
955
cristyb8588ab2013-05-07 13:17:38 +0000956 (void) FormatLocaleFile(stdout," LMSToRGB");
cristy8d24e062013-05-07 12:48:19 +0000957 ConvertLMSToRGB(0.611749,0.910088,0.294880,&r,&g,&b);
958 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
959 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
960 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
961 return(MagickFalse);
962 return(MagickTrue);
963}
964
965static MagickBooleanType ValidateRGBToLuv()
966{
967 double
968 l,
969 u,
970 v;
971
cristyb8588ab2013-05-07 13:17:38 +0000972 (void) FormatLocaleFile(stdout," RGBToLuv");
cristy8d24e062013-05-07 12:48:19 +0000973 ConvertRGBToLuv(0.545877*QuantumRange,0.966567*QuantumRange,
974 0.463759*QuantumRange,&l,&u,&v);
975 if ((fabs(l-88.456154/262.0) >= ReferenceEpsilon) ||
976 (fabs(u-(-51.330414+134.0)/354.0) >= ReferenceEpsilon) ||
977 (fabs(v-(76.405526+140.0)/262.0) >= ReferenceEpsilon))
978 return(MagickFalse);
979 return(MagickTrue);
980}
981
982static MagickBooleanType ValidateLuvToRGB()
983{
984 double
985 r,
986 g,
987 b;
988
cristyb8588ab2013-05-07 13:17:38 +0000989 (void) FormatLocaleFile(stdout," LuvToRGB");
cristy8d24e062013-05-07 12:48:19 +0000990 ConvertLuvToRGB(88.456154/100.0,(-51.330414+134.0)/354.0,
991 (76.405526+140.0)/262.0,&r,&g,&b);
992 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
993 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
994 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
995 return(MagickFalse);
996 return(MagickTrue);
997}
998
999static MagickBooleanType ValidateRGBToXYZ()
1000{
1001 double
1002 x,
1003 y,
1004 z;
1005
cristyb8588ab2013-05-07 13:17:38 +00001006 (void) FormatLocaleFile(stdout," RGBToXYZ");
cristy8d24e062013-05-07 12:48:19 +00001007 ConvertRGBToXYZ(0.545877*QuantumRange,0.966567*QuantumRange,
1008 0.463759*QuantumRange,&x,&y,&z);
1009 if ((fabs(x-0.470646) >= ReferenceEpsilon) ||
1010 (fabs(y-0.730178) >= ReferenceEpsilon) ||
1011 (fabs(z-0.288324) >= ReferenceEpsilon))
1012 return(MagickFalse);
1013 return(MagickTrue);
1014}
1015
1016static MagickBooleanType ValidateXYZToRGB()
1017{
1018 double
1019 r,
1020 g,
1021 b;
1022
cristyb8588ab2013-05-07 13:17:38 +00001023 (void) FormatLocaleFile(stdout," XYZToRGB");
cristy8d24e062013-05-07 12:48:19 +00001024 ConvertXYZToRGB(0.470646,0.730178,0.288324,&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 ValidateYDbDrToRGB()
1033{
1034 double
1035 r,
1036 g,
1037 b;
1038
cristyb8588ab2013-05-07 13:17:38 +00001039 (void) FormatLocaleFile(stdout," YDbDrToRGB");
cristy8d24e062013-05-07 12:48:19 +00001040 ConvertYDbDrToRGB(0.783460,-0.480932+0.5,0.451670+0.5,&r,&g,&b);
1041 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1042 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1043 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1044 return(MagickFalse);
1045 return(MagickTrue);
1046}
1047
1048static MagickBooleanType ValidateRGBToYDbDr()
1049{
1050 double
1051 Db,
1052 Dr,
1053 Y;
1054
cristyb8588ab2013-05-07 13:17:38 +00001055 (void) FormatLocaleFile(stdout," RGBToYDbDr");
cristy8d24e062013-05-07 12:48:19 +00001056 ConvertRGBToYDbDr(0.545877*QuantumRange,0.966567*QuantumRange,
1057 0.463759*QuantumRange,&Y,&Db,&Dr);
1058 if ((fabs(Y-0.783460) >= ReferenceEpsilon) ||
1059 (fabs(Db-(-0.480932)) >= ReferenceEpsilon) ||
1060 (fabs(Dr-0.451670) >= ReferenceEpsilon))
1061 return(MagickFalse);
1062 return(MagickTrue);
1063}
1064
1065static MagickBooleanType ValidateRGBToYIQ()
1066{
1067 double
1068 i,
1069 q,
1070 y;
1071
cristyb8588ab2013-05-07 13:17:38 +00001072 (void) FormatLocaleFile(stdout," RGBToYIQ");
cristy8d24e062013-05-07 12:48:19 +00001073 ConvertRGBToYIQ(0.545877*QuantumRange,0.966567*QuantumRange,
1074 0.463759*QuantumRange,&y,&i,&q);
1075 if ((fabs(y-0.783460) >= ReferenceEpsilon) ||
1076 (fabs(i-(-0.089078)) >= ReferenceEpsilon) ||
1077 (fabs(q-(-0.245399)) >= ReferenceEpsilon))
1078 return(MagickFalse);
1079 return(MagickTrue);
1080}
1081
1082static MagickBooleanType ValidateYIQToRGB()
1083{
1084 double
1085 r,
1086 g,
1087 b;
1088
cristyb8588ab2013-05-07 13:17:38 +00001089 (void) FormatLocaleFile(stdout," YIQToRGB");
cristy8d24e062013-05-07 12:48:19 +00001090 ConvertYIQToRGB(0.783460,-0.089078+0.5,-0.245399+0.5,&r,&g,&b);
1091 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1092 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1093 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1094 return(MagickFalse);
1095 return(MagickTrue);
1096}
1097
1098static MagickBooleanType ValidateRGBToYPbPr()
1099{
1100 double
cristy4ae2e762013-05-07 13:19:24 +00001101 Pb,
1102 Pr,
cristy8d24e062013-05-07 12:48:19 +00001103 y;
1104
cristyb8588ab2013-05-07 13:17:38 +00001105 (void) FormatLocaleFile(stdout," RGBToYPbPr");
cristy8d24e062013-05-07 12:48:19 +00001106 ConvertRGBToYPbPr(0.545877*QuantumRange,0.966567*QuantumRange,
cristy4ae2e762013-05-07 13:19:24 +00001107 0.463759*QuantumRange,&y,&Pb,&Pr);
cristy8d24e062013-05-07 12:48:19 +00001108 if ((fabs(y-0.783460) >= ReferenceEpsilon) ||
cristy4ae2e762013-05-07 13:19:24 +00001109 (fabs(Pb-(-0.180419)) >= ReferenceEpsilon) ||
1110 (fabs(Pr-(-0.169461)) >= ReferenceEpsilon))
cristy8d24e062013-05-07 12:48:19 +00001111 return(MagickFalse);
1112 return(MagickTrue);
1113}
1114
1115static MagickBooleanType ValidateYPbPrToRGB()
1116{
1117 double
1118 r,
1119 g,
1120 b;
1121
cristyb8588ab2013-05-07 13:17:38 +00001122 (void) FormatLocaleFile(stdout," YPbPrToRGB");
cristy8d24e062013-05-07 12:48:19 +00001123 ConvertYPbPrToRGB(0.783460,-0.180419+0.5,-0.169461+0.5,&r,&g,&b);
1124 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1125 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1126 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1127 return(MagickFalse);
1128 return(MagickTrue);
1129}
1130
1131static MagickBooleanType ValidateRGBToYUV()
1132{
1133 double
1134 U,
1135 V,
1136 Y;
1137
cristyb8588ab2013-05-07 13:17:38 +00001138 (void) FormatLocaleFile(stdout," RGBToYUV");
cristy8d24e062013-05-07 12:48:19 +00001139 ConvertRGBToYUV(0.545877*QuantumRange,0.966567*QuantumRange,
1140 0.463759*QuantumRange,&Y,&U,&V);
1141 if ((fabs(Y-0.783460) >= ReferenceEpsilon) ||
1142 (fabs(U-(-0.157383)) >= ReferenceEpsilon) ||
1143 (fabs(V-(-0.208443)) >= ReferenceEpsilon))
1144 return(MagickFalse);
1145 return(MagickTrue);
1146}
1147
1148static MagickBooleanType ValidateYUVToRGB()
1149{
1150 double
1151 r,
1152 g,
1153 b;
1154
cristyb8588ab2013-05-07 13:17:38 +00001155 (void) FormatLocaleFile(stdout," YUVToRGB");
cristy8d24e062013-05-07 12:48:19 +00001156 ConvertYUVToRGB(0.783460,-0.157383+0.5,-0.208443+0.5,&r,&g,&b);
1157 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1158 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1159 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1160 return(MagickFalse);
1161 return(MagickTrue);
1162}
1163
cristy572e0972013-05-07 12:51:28 +00001164static size_t ValidateColorspaces(ImageInfo *image_info,size_t *fail,
cristy80e870e2013-05-07 12:23:02 +00001165 ExceptionInfo *exception)
1166{
1167 MagickBooleanType
1168 status;
1169
cristy80e870e2013-05-07 12:23:02 +00001170 size_t
1171 test;
1172
cristy8d24e062013-05-07 12:48:19 +00001173 /*
cristy92e5cea2013-05-08 12:24:12 +00001174 Reference: https://code.google.com/p/chroma.
cristy8d24e062013-05-07 12:48:19 +00001175
1176 Illuminant = D65
1177 Observer = 2° (1931)
1178
1179 XYZ 0.470645, 0.730177, 0.288323
1180 sRGB 0.545877, 0.966567, 0.463759
1181 CAT02 LMS 0.611749, 0.910088, 0.294880
1182 Y'DbDr 0.783460, -0.480932, 0.451670
1183 Y'IQ 0.783460, -0.089078, -0.245399
1184 Y'PbPr 0.783460, -0.180419, -0.169461
1185 Y'UV 0.783460, -0.157383, -0.208443
1186 JPEG-Y'CbCr 0.783460, 0.319581, 0.330539
1187 L*u*v* 88.456154, -51.330414, 76.405526
1188 L*a*b* 88.456154, -54.671483, 51.662818
1189 L*C*H* 88.456154, 75.219797, 136.620717
1190 HSV 110.200859, 0.520200, 0.966567
1191 HSL 110.200859, 0.882623, 0.715163
1192 HSI 111.244375, 0.295985, 0.658734
1193 Y'CbCr 187.577791, 87.586330, 90.040886
cristy8d24e062013-05-07 12:48:19 +00001194 */
cristy80e870e2013-05-07 12:23:02 +00001195 (void) FormatLocaleFile(stdout,"validate colorspaces:\n");
cristy8d24e062013-05-07 12:48:19 +00001196 for (test=0; test < 26; test++)
1197 {
1198 CatchException(exception);
1199 (void) FormatLocaleFile(stdout," test %.20g: ",(double) test);
1200 switch (test)
cristy80e870e2013-05-07 12:23:02 +00001201 {
cristy8d24e062013-05-07 12:48:19 +00001202 case 0: status=ValidateHSIToRGB(); break;
1203 case 1: status=ValidateRGBToHSI(); break;
1204 case 2: status=ValidateHSLToRGB(); break;
1205 case 3: status=ValidateRGBToHSL(); break;
1206 case 4: status=ValidateHSVToRGB(); break;
1207 case 5: status=ValidateRGBToHSV(); break;
1208 case 6: status=ValidateJPEGYCbCrToRGB(); break;
1209 case 7: status=ValidateRGBToJPEGYCbCr(); break;
1210 case 8: status=ValidateLabToRGB(); break;
1211 case 9: status=ValidateRGBToLab(); break;
1212 case 10: status=ValidateLchToRGB(); break;
1213 case 11: status=ValidateRGBToLch(); break;
1214 case 12: status=ValidateLMSToRGB(); break;
1215 case 13: status=ValidateRGBToLMS(); break;
1216 case 14: status=ValidateLuvToRGB(); break;
1217 case 15: status=ValidateRGBToLuv(); break;
1218 case 16: status=ValidateXYZToRGB(); break;
1219 case 17: status=ValidateRGBToXYZ(); break;
1220 case 18: status=ValidateYDbDrToRGB(); break;
1221 case 19: status=ValidateRGBToYDbDr(); break;
1222 case 20: status=ValidateYIQToRGB(); break;
1223 case 21: status=ValidateRGBToYIQ(); break;
1224 case 22: status=ValidateYPbPrToRGB(); break;
1225 case 23: status=ValidateRGBToYPbPr(); break;
1226 case 24: status=ValidateYUVToRGB(); break;
1227 case 25: status=ValidateRGBToYUV(); break;
1228 default: status=MagickFalse;
cristy80e870e2013-05-07 12:23:02 +00001229 }
cristyb8588ab2013-05-07 13:17:38 +00001230 if (status == MagickFalse)
cristy8d24e062013-05-07 12:48:19 +00001231 {
1232 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1233 GetMagickModule());
1234 (*fail)++;
1235 continue;
1236 }
1237 (void) FormatLocaleFile(stdout,"... pass.\n");
1238 }
cristy80e870e2013-05-07 12:23:02 +00001239 (void) FormatLocaleFile(stdout,
1240 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1241 (double) (test-(*fail)),(double) *fail);
1242 return(test);
1243}
1244
1245/*
1246%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1247% %
1248% %
1249% %
cristy3ed852e2009-09-05 21:47:34 +00001250% V a l i d a t e C o m p a r e C o m m a n d %
1251% %
1252% %
1253% %
1254%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1255%
1256% ValidateCompareCommand() validates the ImageMagick compare command line
1257% program and returns the number of validation tests that passed and failed.
1258%
1259% The format of the ValidateCompareCommand method is:
1260%
cristybb503372010-05-27 20:51:26 +00001261% size_t ValidateCompareCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001262% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001263% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001264%
1265% A description of each parameter follows:
1266%
1267% o image_info: the image info.
1268%
1269% o reference_filename: the reference image filename.
1270%
1271% o output_filename: the output image filename.
1272%
1273% o fail: return the number of validation tests that pass.
1274%
1275% o exception: return any errors or warnings in this structure.
1276%
1277*/
cristybb503372010-05-27 20:51:26 +00001278static size_t ValidateCompareCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001279 const char *reference_filename,const char *output_filename,size_t *fail,
1280 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001281{
1282 char
1283 **arguments,
1284 command[MaxTextExtent];
1285
1286 int
1287 number_arguments;
1288
1289 MagickBooleanType
1290 status;
1291
cristybb503372010-05-27 20:51:26 +00001292 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001293 i,
1294 j;
1295
cristybb503372010-05-27 20:51:26 +00001296 size_t
cristy3ed852e2009-09-05 21:47:34 +00001297 test;
1298
1299 test=0;
cristyb51dff52011-05-19 16:55:47 +00001300 (void) FormatLocaleFile(stdout,"validate compare command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00001301 for (i=0; compare_options[i] != (char *) NULL; i++)
1302 {
1303 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00001304 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
cristy6aa47ad2010-05-28 19:32:32 +00001305 compare_options[i]);
cristyb51dff52011-05-19 16:55:47 +00001306 (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
cristy3ed852e2009-09-05 21:47:34 +00001307 compare_options[i],reference_filename,reference_filename,output_filename);
1308 arguments=StringToArgv(command,&number_arguments);
1309 if (arguments == (char **) NULL)
1310 {
cristy1e604812011-05-19 18:07:50 +00001311 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1312 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001313 (*fail)++;
1314 continue;
1315 }
cristy8a9106f2011-07-05 14:39:26 +00001316 status=CompareImagesCommand(image_info,number_arguments,arguments,
cristy3ed852e2009-09-05 21:47:34 +00001317 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00001318 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00001319 arguments[j]=DestroyString(arguments[j]);
1320 arguments=(char **) RelinquishMagickMemory(arguments);
1321 if (status != MagickFalse)
1322 {
cristy1e604812011-05-19 18:07:50 +00001323 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1324 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001325 (*fail)++;
1326 continue;
1327 }
cristyb51dff52011-05-19 16:55:47 +00001328 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00001329 }
cristyb51dff52011-05-19 16:55:47 +00001330 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00001331 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1332 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00001333 return(test);
1334}
1335
1336/*
1337%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1338% %
1339% %
1340% %
1341% V a l i d a t e C o m p o s i t e C o m m a n d %
1342% %
1343% %
1344% %
1345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1346%
1347% ValidateCompositeCommand() validates the ImageMagick composite command line
1348% program and returns the number of validation tests that passed and failed.
1349%
1350% The format of the ValidateCompositeCommand method is:
1351%
cristybb503372010-05-27 20:51:26 +00001352% size_t ValidateCompositeCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001353% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001354% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001355%
1356% A description of each parameter follows:
1357%
1358% o image_info: the image info.
1359%
1360% o reference_filename: the reference image filename.
1361%
1362% o output_filename: the output image filename.
1363%
1364% o fail: return the number of validation tests that pass.
1365%
1366% o exception: return any errors or warnings in this structure.
1367%
1368*/
cristybb503372010-05-27 20:51:26 +00001369static size_t ValidateCompositeCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001370 const char *reference_filename,const char *output_filename,size_t *fail,
1371 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001372{
1373 char
1374 **arguments,
1375 command[MaxTextExtent];
1376
1377 int
1378 number_arguments;
1379
1380 MagickBooleanType
1381 status;
1382
cristybb503372010-05-27 20:51:26 +00001383 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001384 i,
1385 j;
1386
cristybb503372010-05-27 20:51:26 +00001387 size_t
cristy3ed852e2009-09-05 21:47:34 +00001388 test;
1389
1390 test=0;
cristyb51dff52011-05-19 16:55:47 +00001391 (void) FormatLocaleFile(stdout,"validate composite command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00001392 for (i=0; composite_options[i] != (char *) NULL; i++)
1393 {
1394 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00001395 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
cristy6aa47ad2010-05-28 19:32:32 +00001396 composite_options[i]);
cristyb51dff52011-05-19 16:55:47 +00001397 (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
cristy3ed852e2009-09-05 21:47:34 +00001398 reference_filename,composite_options[i],reference_filename,
1399 output_filename);
1400 arguments=StringToArgv(command,&number_arguments);
1401 if (arguments == (char **) NULL)
1402 {
cristy1e604812011-05-19 18:07:50 +00001403 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1404 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001405 (*fail)++;
1406 continue;
1407 }
1408 status=CompositeImageCommand(image_info,number_arguments,arguments,
1409 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00001410 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00001411 arguments[j]=DestroyString(arguments[j]);
1412 arguments=(char **) RelinquishMagickMemory(arguments);
1413 if (status != MagickFalse)
1414 {
cristy1e604812011-05-19 18:07:50 +00001415 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1416 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001417 (*fail)++;
1418 continue;
1419 }
cristyb51dff52011-05-19 16:55:47 +00001420 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00001421 }
cristyb51dff52011-05-19 16:55:47 +00001422 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00001423 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1424 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00001425 return(test);
1426}
1427
1428/*
1429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1430% %
1431% %
1432% %
1433% V a l i d a t e C o n v e r t C o m m a n d %
1434% %
1435% %
1436% %
1437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1438%
1439% ValidateConvertCommand() validates the ImageMagick convert command line
1440% program and returns the number of validation tests that passed and failed.
1441%
1442% The format of the ValidateConvertCommand method is:
1443%
cristybb503372010-05-27 20:51:26 +00001444% size_t ValidateConvertCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001445% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001446% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001447%
1448% A description of each parameter follows:
1449%
1450% o image_info: the image info.
1451%
1452% o reference_filename: the reference image filename.
1453%
1454% o output_filename: the output image filename.
1455%
1456% o fail: return the number of validation tests that pass.
1457%
1458% o exception: return any errors or warnings in this structure.
1459%
1460*/
cristybb503372010-05-27 20:51:26 +00001461static size_t ValidateConvertCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001462 const char *reference_filename,const char *output_filename,size_t *fail,
1463 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001464{
1465 char
1466 **arguments,
1467 command[MaxTextExtent];
1468
1469 int
1470 number_arguments;
1471
1472 MagickBooleanType
1473 status;
1474
cristybb503372010-05-27 20:51:26 +00001475 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001476 i,
1477 j;
1478
cristybb503372010-05-27 20:51:26 +00001479 size_t
cristy3ed852e2009-09-05 21:47:34 +00001480 test;
1481
1482 test=0;
cristyb51dff52011-05-19 16:55:47 +00001483 (void) FormatLocaleFile(stdout,"validate convert command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00001484 for (i=0; convert_options[i] != (char *) NULL; i++)
1485 {
1486 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00001487 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) test++,
cristy6aa47ad2010-05-28 19:32:32 +00001488 convert_options[i]);
cristyb51dff52011-05-19 16:55:47 +00001489 (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
cristy3ed852e2009-09-05 21:47:34 +00001490 reference_filename,convert_options[i],reference_filename,output_filename);
1491 arguments=StringToArgv(command,&number_arguments);
1492 if (arguments == (char **) NULL)
1493 {
cristy1e604812011-05-19 18:07:50 +00001494 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1495 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001496 (*fail)++;
1497 continue;
1498 }
1499 status=ConvertImageCommand(image_info,number_arguments,arguments,
1500 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00001501 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00001502 arguments[j]=DestroyString(arguments[j]);
1503 arguments=(char **) RelinquishMagickMemory(arguments);
1504 if (status != MagickFalse)
1505 {
cristy1e604812011-05-19 18:07:50 +00001506 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1507 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001508 (*fail)++;
1509 continue;
1510 }
cristyb51dff52011-05-19 16:55:47 +00001511 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00001512 }
cristyb51dff52011-05-19 16:55:47 +00001513 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00001514 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1515 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00001516 return(test);
1517}
1518
1519/*
1520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1521% %
1522% %
1523% %
1524% V a l i d a t e I d e n t i f y C o m m a n d %
1525% %
1526% %
1527% %
1528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1529%
1530% ValidateIdentifyCommand() validates the ImageMagick identify command line
1531% program and returns the number of validation tests that passed and failed.
1532%
1533% The format of the ValidateIdentifyCommand method is:
1534%
cristybb503372010-05-27 20:51:26 +00001535% size_t ValidateIdentifyCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001536% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001537% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001538%
1539% A description of each parameter follows:
1540%
1541% o image_info: the image info.
1542%
1543% o reference_filename: the reference image filename.
1544%
1545% o output_filename: the output image filename.
1546%
1547% o fail: return the number of validation tests that pass.
1548%
1549% o exception: return any errors or warnings in this structure.
1550%
1551*/
cristybb503372010-05-27 20:51:26 +00001552static size_t ValidateIdentifyCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001553 const char *reference_filename,const char *output_filename,size_t *fail,
1554 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001555{
1556 char
1557 **arguments,
1558 command[MaxTextExtent];
1559
1560 int
1561 number_arguments;
1562
1563 MagickBooleanType
1564 status;
1565
cristybb503372010-05-27 20:51:26 +00001566 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001567 i,
1568 j;
1569
cristybb503372010-05-27 20:51:26 +00001570 size_t
cristy3ed852e2009-09-05 21:47:34 +00001571 test;
1572
1573 (void) output_filename;
1574 test=0;
cristyb51dff52011-05-19 16:55:47 +00001575 (void) FormatLocaleFile(stdout,"validate identify command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00001576 for (i=0; identify_options[i] != (char *) NULL; i++)
1577 {
1578 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00001579 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) test++,
cristy6aa47ad2010-05-28 19:32:32 +00001580 identify_options[i]);
cristyb51dff52011-05-19 16:55:47 +00001581 (void) FormatLocaleString(command,MaxTextExtent,"%s %s",
cristy3ed852e2009-09-05 21:47:34 +00001582 identify_options[i],reference_filename);
1583 arguments=StringToArgv(command,&number_arguments);
1584 if (arguments == (char **) NULL)
1585 {
cristy1e604812011-05-19 18:07:50 +00001586 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1587 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001588 (*fail)++;
1589 continue;
1590 }
1591 status=IdentifyImageCommand(image_info,number_arguments,arguments,
1592 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00001593 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00001594 arguments[j]=DestroyString(arguments[j]);
1595 arguments=(char **) RelinquishMagickMemory(arguments);
1596 if (status != MagickFalse)
1597 {
cristy1e604812011-05-19 18:07:50 +00001598 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1599 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001600 (*fail)++;
1601 continue;
1602 }
cristyb51dff52011-05-19 16:55:47 +00001603 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00001604 }
cristyb51dff52011-05-19 16:55:47 +00001605 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00001606 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1607 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00001608 return(test);
1609}
1610
1611/*
1612%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1613% %
1614% %
1615% %
1616% 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 %
1617% %
1618% %
1619% %
1620%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1621%
1622% ValidateImageFormatsInMemory() validates the ImageMagick image formats in
1623% memory and returns the number of validation tests that passed and failed.
1624%
1625% The format of the ValidateImageFormatsInMemory method is:
1626%
cristybb503372010-05-27 20:51:26 +00001627% size_t ValidateImageFormatsInMemory(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001628% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001629% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001630%
1631% A description of each parameter follows:
1632%
1633% o image_info: the image info.
1634%
1635% o reference_filename: the reference image filename.
1636%
1637% o output_filename: the output image filename.
1638%
1639% o fail: return the number of validation tests that pass.
1640%
1641% o exception: return any errors or warnings in this structure.
1642%
1643*/
glennrp4084cda2012-12-11 14:13:35 +00001644
cristy725833f2012-12-13 17:40:53 +00001645/*
1646 Enable this to count remaining $TMPDIR/magick-* files. Note that the count
1647 includes any files left over from other runs.
1648*/
1649#undef MagickCountTempFiles
glennrp4084cda2012-12-11 14:13:35 +00001650
cristybb503372010-05-27 20:51:26 +00001651static size_t ValidateImageFormatsInMemory(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001652 const char *reference_filename,const char *output_filename,size_t *fail,
1653 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001654{
1655 char
glennrp4084cda2012-12-11 14:13:35 +00001656#ifdef MagickCountTempFiles
glennrp4084cda2012-12-11 14:13:35 +00001657 path[MaxTextExtent],
cristy77b33ba2013-03-28 13:23:13 +00001658 SystemCommand[MaxTextExtent],
glennrp4084cda2012-12-11 14:13:35 +00001659#endif
cristy3ed852e2009-09-05 21:47:34 +00001660 size[MaxTextExtent];
1661
1662 const MagickInfo
1663 *magick_info;
1664
1665 double
1666 distortion,
1667 fuzz;
1668
1669 Image
1670 *difference_image,
cristy2c404222012-06-10 15:36:30 +00001671 *ping_image,
cristy6b9ae3f2012-06-10 15:39:34 +00001672 *reconstruct_image,
cristy100b8d92012-01-08 00:32:49 +00001673 *reference_image;
cristy3ed852e2009-09-05 21:47:34 +00001674
1675 MagickBooleanType
1676 status;
1677
cristybb503372010-05-27 20:51:26 +00001678 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001679 i,
1680 j;
1681
1682 size_t
cristy100b8d92012-01-08 00:32:49 +00001683 length,
1684 test;
cristy3ed852e2009-09-05 21:47:34 +00001685
1686 unsigned char
1687 *blob;
1688
cristy3ed852e2009-09-05 21:47:34 +00001689 test=0;
cristyb51dff52011-05-19 16:55:47 +00001690 (void) FormatLocaleFile(stdout,"validate image formats in memory:\n");
glennrp4084cda2012-12-11 14:13:35 +00001691
1692#ifdef MagickCountTempFiles
1693 (void)GetPathTemplate(path);
glennrp33fb8032013-01-07 18:43:03 +00001694 /* Remove file template except for the leading "/path/to/magick-" */
glennrp4084cda2012-12-11 14:13:35 +00001695 path[strlen(path)-17]='\0';
1696 (void) FormatLocaleFile(stdout," tmp path is '%s*'\n",path);
1697#endif
1698
cristy3ed852e2009-09-05 21:47:34 +00001699 for (i=0; reference_formats[i].magick != (char *) NULL; i++)
1700 {
1701 magick_info=GetMagickInfo(reference_formats[i].magick,exception);
1702 if ((magick_info == (const MagickInfo *) NULL) ||
1703 (magick_info->decoder == (DecodeImageHandler *) NULL) ||
1704 (magick_info->encoder == (EncodeImageHandler *) NULL))
1705 continue;
cristy5f1c1ff2010-12-23 21:38:06 +00001706 for (j=0; reference_types[j].type != UndefinedType; j++)
cristy3ed852e2009-09-05 21:47:34 +00001707 {
1708 /*
1709 Generate reference image.
1710 */
1711 CatchException(exception);
cristy1e604812011-05-19 18:07:50 +00001712 (void) FormatLocaleFile(stdout," test %.20g: %s/%s/%s/%.20g-bits",
1713 (double) (test++),reference_formats[i].magick,CommandOptionToMnemonic(
cristy7998e5f2009-10-08 02:45:33 +00001714 MagickCompressOptions,reference_formats[i].compression),
cristy042ee782011-04-22 18:48:30 +00001715 CommandOptionToMnemonic(MagickTypeOptions,reference_types[j].type),
cristy75a26232010-06-03 17:15:02 +00001716 (double) reference_types[j].depth);
cristy3ed852e2009-09-05 21:47:34 +00001717 (void) CopyMagickString(image_info->filename,reference_filename,
1718 MaxTextExtent);
1719 reference_image=ReadImage(image_info,exception);
1720 if (reference_image == (Image *) NULL)
1721 {
cristy1e604812011-05-19 18:07:50 +00001722 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1723 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001724 (*fail)++;
1725 continue;
1726 }
1727 /*
1728 Write reference image.
1729 */
cristyb51dff52011-05-19 16:55:47 +00001730 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",
cristy75a26232010-06-03 17:15:02 +00001731 (double) reference_image->columns,(double) reference_image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001732 (void) CloneString(&image_info->size,size);
1733 image_info->depth=reference_types[j].depth;
cristyb51dff52011-05-19 16:55:47 +00001734 (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001735 reference_formats[i].magick,output_filename);
cristy018f07f2011-09-04 21:15:19 +00001736 status=SetImageType(reference_image,reference_types[j].type,exception);
cristy3ed852e2009-09-05 21:47:34 +00001737 if (status == MagickFalse)
1738 {
cristy1e604812011-05-19 18:07:50 +00001739 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1740 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001741 (*fail)++;
1742 reference_image=DestroyImage(reference_image);
1743 continue;
1744 }
cristy8a11cb12011-10-19 23:53:34 +00001745 status=SetImageDepth(reference_image,reference_types[j].depth,exception);
cristy3ed852e2009-09-05 21:47:34 +00001746 if (status == MagickFalse)
1747 {
cristy1e604812011-05-19 18:07:50 +00001748 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1749 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001750 (*fail)++;
1751 reference_image=DestroyImage(reference_image);
1752 continue;
1753 }
cristy7998e5f2009-10-08 02:45:33 +00001754 reference_image->compression=reference_formats[i].compression;
cristy6f9e0d32011-08-28 16:32:09 +00001755 status=WriteImage(image_info,reference_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001756 reference_image=DestroyImage(reference_image);
1757 if (status == MagickFalse)
1758 {
cristy1e604812011-05-19 18:07:50 +00001759 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1760 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001761 (*fail)++;
1762 continue;
1763 }
1764 /*
cristy2c404222012-06-10 15:36:30 +00001765 Ping reference image.
cristy3ed852e2009-09-05 21:47:34 +00001766 */
cristyb51dff52011-05-19 16:55:47 +00001767 (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001768 reference_formats[i].magick,output_filename);
cristy2c404222012-06-10 15:36:30 +00001769 ping_image=PingImage(image_info,exception);
1770 if (ping_image == (Image *) NULL)
1771 {
1772 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1773 GetMagickModule());
1774 (*fail)++;
1775 continue;
1776 }
1777 ping_image=DestroyImage(ping_image);
1778 /*
1779 Read reference image.
1780 */
cristy3ed852e2009-09-05 21:47:34 +00001781 reference_image=ReadImage(image_info,exception);
1782 if (reference_image == (Image *) NULL)
1783 {
cristy1e604812011-05-19 18:07:50 +00001784 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1785 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001786 (*fail)++;
1787 continue;
1788 }
1789 /*
1790 Write reference image.
1791 */
cristyb51dff52011-05-19 16:55:47 +00001792 (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001793 reference_formats[i].magick,output_filename);
1794 (void) CopyMagickString(image_info->magick,reference_formats[i].magick,
1795 MaxTextExtent);
1796 reference_image->depth=reference_types[j].depth;
cristy7998e5f2009-10-08 02:45:33 +00001797 reference_image->compression=reference_formats[i].compression;
cristy3ed852e2009-09-05 21:47:34 +00001798 length=8192;
1799 blob=ImageToBlob(image_info,reference_image,&length,exception);
1800 if (blob == (unsigned char *) NULL)
1801 {
cristy1e604812011-05-19 18:07:50 +00001802 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1803 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001804 (*fail)++;
1805 reference_image=DestroyImage(reference_image);
1806 continue;
1807 }
1808 /*
cristy2c404222012-06-10 15:36:30 +00001809 Ping reference blob.
1810 */
1811 ping_image=PingBlob(image_info,blob,length,exception);
1812 if (ping_image == (Image *) NULL)
1813 {
1814 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1815 GetMagickModule());
1816 (*fail)++;
1817 blob=(unsigned char *) RelinquishMagickMemory(blob);
1818 continue;
1819 }
1820 ping_image=DestroyImage(ping_image);
1821 /*
cristy3ed852e2009-09-05 21:47:34 +00001822 Read reconstruct image.
1823 */
cristyb51dff52011-05-19 16:55:47 +00001824 (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001825 reference_formats[i].magick,output_filename);
1826 reconstruct_image=BlobToImage(image_info,blob,length,exception);
1827 blob=(unsigned char *) RelinquishMagickMemory(blob);
1828 if (reconstruct_image == (Image *) NULL)
1829 {
cristy1e604812011-05-19 18:07:50 +00001830 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1831 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001832 (*fail)++;
1833 reference_image=DestroyImage(reference_image);
1834 continue;
1835 }
1836 /*
1837 Compare reference to reconstruct image.
1838 */
cristy93540ab2013-03-30 19:59:41 +00001839 fuzz=0.003; /* grayscale */
cristy3ed852e2009-09-05 21:47:34 +00001840 if (reference_formats[i].fuzz != 0.0)
1841 fuzz=reference_formats[i].fuzz;
cristy8a9106f2011-07-05 14:39:26 +00001842 difference_image=CompareImages(reference_image,reconstruct_image,
cristy864c6a82012-06-19 16:45:22 +00001843 RootMeanSquaredErrorMetric,&distortion,exception);
cristy3ed852e2009-09-05 21:47:34 +00001844 reconstruct_image=DestroyImage(reconstruct_image);
1845 reference_image=DestroyImage(reference_image);
1846 if (difference_image == (Image *) NULL)
1847 {
cristy1e604812011-05-19 18:07:50 +00001848 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1849 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001850 (*fail)++;
1851 continue;
1852 }
1853 difference_image=DestroyImage(difference_image);
cristy14154222012-06-15 23:21:49 +00001854 if ((QuantumScale*distortion) > fuzz)
cristy3ed852e2009-09-05 21:47:34 +00001855 {
cristyb51dff52011-05-19 16:55:47 +00001856 (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
cristy14154222012-06-15 23:21:49 +00001857 QuantumScale*distortion);
cristy3ed852e2009-09-05 21:47:34 +00001858 (*fail)++;
1859 continue;
1860 }
glennrp4084cda2012-12-11 14:13:35 +00001861#ifdef MagickCountTempFiles
1862 (void) FormatLocaleFile(stdout,"... pass, ");
1863 (void) fflush(stdout);
1864 SystemCommand[0]='\0';
cristy77b33ba2013-03-28 13:23:13 +00001865 (void) strncat(SystemCommand,"echo `ls ",9);
1866 (void) strncat(SystemCommand,path,MaxTextExtent-31);
1867 (void) strncat(SystemCommand,"* | wc -w` tmp files.",20);
1868 (void) system(SystemCommand);
glennrp4084cda2012-12-11 14:13:35 +00001869 (void) fflush(stdout);
1870#else
1871 (void) FormatLocaleFile(stdout,"... pass\n");
1872#endif
cristy3ed852e2009-09-05 21:47:34 +00001873 }
1874 }
cristyb51dff52011-05-19 16:55:47 +00001875 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00001876 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1877 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00001878 return(test);
1879}
1880
1881/*
1882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1883% %
1884% %
1885% %
1886% 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 %
1887% %
1888% %
1889% %
1890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1891%
1892% ValidateImageFormatsOnDisk() validates the ImageMagick image formats on disk
1893% and returns the number of validation tests that passed and failed.
1894%
1895% The format of the ValidateImageFormatsOnDisk method is:
1896%
cristybb503372010-05-27 20:51:26 +00001897% size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00001898% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00001899% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001900%
1901% A description of each parameter follows:
1902%
1903% o image_info: the image info.
1904%
1905% o reference_filename: the reference image filename.
1906%
1907% o output_filename: the output image filename.
1908%
1909% o fail: return the number of validation tests that pass.
1910%
1911% o exception: return any errors or warnings in this structure.
1912%
1913*/
cristybb503372010-05-27 20:51:26 +00001914static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00001915 const char *reference_filename,const char *output_filename,size_t *fail,
1916 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001917{
1918 char
1919 size[MaxTextExtent];
1920
1921 const MagickInfo
1922 *magick_info;
1923
1924 double
1925 distortion,
1926 fuzz;
1927
1928 Image
1929 *difference_image,
1930 *reference_image,
1931 *reconstruct_image;
1932
1933 MagickBooleanType
1934 status;
1935
cristybb503372010-05-27 20:51:26 +00001936 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001937 i,
1938 j;
1939
cristybb503372010-05-27 20:51:26 +00001940 size_t
cristy3ed852e2009-09-05 21:47:34 +00001941 test;
1942
1943 test=0;
cristyb51dff52011-05-19 16:55:47 +00001944 (void) FormatLocaleFile(stdout,"validate image formats on disk:\n");
cristy3ed852e2009-09-05 21:47:34 +00001945 for (i=0; reference_formats[i].magick != (char *) NULL; i++)
1946 {
1947 magick_info=GetMagickInfo(reference_formats[i].magick,exception);
1948 if ((magick_info == (const MagickInfo *) NULL) ||
1949 (magick_info->decoder == (DecodeImageHandler *) NULL) ||
1950 (magick_info->encoder == (EncodeImageHandler *) NULL))
1951 continue;
cristy5f1c1ff2010-12-23 21:38:06 +00001952 for (j=0; reference_types[j].type != UndefinedType; j++)
cristy3ed852e2009-09-05 21:47:34 +00001953 {
1954 /*
1955 Generate reference image.
1956 */
1957 CatchException(exception);
cristy1e604812011-05-19 18:07:50 +00001958 (void) FormatLocaleFile(stdout," test %.20g: %s/%s/%s/%.20g-bits",
1959 (double) (test++),reference_formats[i].magick,CommandOptionToMnemonic(
cristy7998e5f2009-10-08 02:45:33 +00001960 MagickCompressOptions,reference_formats[i].compression),
cristy042ee782011-04-22 18:48:30 +00001961 CommandOptionToMnemonic(MagickTypeOptions,reference_types[j].type),
cristy75a26232010-06-03 17:15:02 +00001962 (double) reference_types[j].depth);
cristy3ed852e2009-09-05 21:47:34 +00001963 (void) CopyMagickString(image_info->filename,reference_filename,
1964 MaxTextExtent);
1965 reference_image=ReadImage(image_info,exception);
1966 if (reference_image == (Image *) NULL)
1967 {
cristy1e604812011-05-19 18:07:50 +00001968 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1969 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001970 (*fail)++;
1971 continue;
1972 }
1973 /*
1974 Write reference image.
1975 */
cristyb51dff52011-05-19 16:55:47 +00001976 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",
cristy75a26232010-06-03 17:15:02 +00001977 (double) reference_image->columns,(double) reference_image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001978 (void) CloneString(&image_info->size,size);
1979 image_info->depth=reference_types[j].depth;
cristyb51dff52011-05-19 16:55:47 +00001980 (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00001981 reference_formats[i].magick,output_filename);
cristy018f07f2011-09-04 21:15:19 +00001982 status=SetImageType(reference_image,reference_types[j].type,exception);
cristy3ed852e2009-09-05 21:47:34 +00001983 if (status == MagickFalse)
1984 {
cristy1e604812011-05-19 18:07:50 +00001985 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1986 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001987 (*fail)++;
1988 reference_image=DestroyImage(reference_image);
1989 continue;
1990 }
cristy8a11cb12011-10-19 23:53:34 +00001991 status=SetImageDepth(reference_image,reference_types[j].depth,exception);
cristy3ed852e2009-09-05 21:47:34 +00001992 if (status == MagickFalse)
1993 {
cristy1e604812011-05-19 18:07:50 +00001994 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1995 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00001996 (*fail)++;
1997 reference_image=DestroyImage(reference_image);
1998 continue;
1999 }
cristy7998e5f2009-10-08 02:45:33 +00002000 reference_image->compression=reference_formats[i].compression;
cristy6f9e0d32011-08-28 16:32:09 +00002001 status=WriteImage(image_info,reference_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002002 reference_image=DestroyImage(reference_image);
2003 if (status == MagickFalse)
2004 {
cristy1e604812011-05-19 18:07:50 +00002005 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2006 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002007 (*fail)++;
2008 continue;
2009 }
2010 /*
2011 Read reference image.
2012 */
cristyb51dff52011-05-19 16:55:47 +00002013 (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00002014 reference_formats[i].magick,output_filename);
2015 reference_image=ReadImage(image_info,exception);
2016 if (reference_image == (Image *) NULL)
2017 {
cristy1e604812011-05-19 18:07:50 +00002018 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2019 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002020 (*fail)++;
2021 continue;
2022 }
2023 /*
2024 Write reference image.
2025 */
cristyb51dff52011-05-19 16:55:47 +00002026 (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00002027 reference_formats[i].magick,output_filename);
2028 reference_image->depth=reference_types[j].depth;
cristy7998e5f2009-10-08 02:45:33 +00002029 reference_image->compression=reference_formats[i].compression;
cristy6f9e0d32011-08-28 16:32:09 +00002030 status=WriteImage(image_info,reference_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002031 if (status == MagickFalse)
2032 {
cristy1e604812011-05-19 18:07:50 +00002033 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2034 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002035 (*fail)++;
2036 reference_image=DestroyImage(reference_image);
2037 continue;
2038 }
2039 /*
2040 Read reconstruct image.
2041 */
cristyb51dff52011-05-19 16:55:47 +00002042 (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +00002043 reference_formats[i].magick,output_filename);
2044 reconstruct_image=ReadImage(image_info,exception);
2045 if (reconstruct_image == (Image *) NULL)
2046 {
cristy1e604812011-05-19 18:07:50 +00002047 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2048 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002049 (*fail)++;
2050 reference_image=DestroyImage(reference_image);
2051 continue;
2052 }
2053 /*
2054 Compare reference to reconstruct image.
2055 */
cristy93540ab2013-03-30 19:59:41 +00002056 fuzz=0.003; /* grayscale */
cristy3ed852e2009-09-05 21:47:34 +00002057 if (reference_formats[i].fuzz != 0.0)
2058 fuzz=reference_formats[i].fuzz;
cristy8a9106f2011-07-05 14:39:26 +00002059 difference_image=CompareImages(reference_image,reconstruct_image,
cristy864c6a82012-06-19 16:45:22 +00002060 RootMeanSquaredErrorMetric,&distortion,exception);
cristy3ed852e2009-09-05 21:47:34 +00002061 reconstruct_image=DestroyImage(reconstruct_image);
2062 reference_image=DestroyImage(reference_image);
2063 if (difference_image == (Image *) NULL)
2064 {
cristy1e604812011-05-19 18:07:50 +00002065 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2066 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002067 (*fail)++;
2068 continue;
2069 }
2070 difference_image=DestroyImage(difference_image);
cristy14154222012-06-15 23:21:49 +00002071 if ((QuantumScale*distortion) > fuzz)
cristy3ed852e2009-09-05 21:47:34 +00002072 {
cristyb51dff52011-05-19 16:55:47 +00002073 (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
cristy14154222012-06-15 23:21:49 +00002074 QuantumScale*distortion);
cristy3ed852e2009-09-05 21:47:34 +00002075 (*fail)++;
2076 continue;
2077 }
cristyb51dff52011-05-19 16:55:47 +00002078 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00002079 }
2080 }
cristyb51dff52011-05-19 16:55:47 +00002081 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00002082 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2083 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00002084 return(test);
2085}
2086
2087/*
2088%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2089% %
2090% %
2091% %
2092% 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 %
2093% %
2094% %
2095% %
2096%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2097%
2098% ValidateImportExportPixels() validates the pixel import and export methods.
2099% It returns the number of validation tests that passed and failed.
2100%
2101% The format of the ValidateImportExportPixels method is:
2102%
cristybb503372010-05-27 20:51:26 +00002103% size_t ValidateImportExportPixels(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00002104% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00002105% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002106%
2107% A description of each parameter follows:
2108%
2109% o image_info: the image info.
2110%
2111% o reference_filename: the reference image filename.
2112%
2113% o output_filename: the output image filename.
2114%
2115% o fail: return the number of validation tests that pass.
2116%
2117% o exception: return any errors or warnings in this structure.
2118%
2119*/
cristybb503372010-05-27 20:51:26 +00002120static size_t ValidateImportExportPixels(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00002121 const char *reference_filename,const char *output_filename,size_t *fail,
2122 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002123{
2124 double
2125 distortion;
2126
2127 Image
2128 *difference_image,
2129 *reference_image,
2130 *reconstruct_image;
2131
2132 MagickBooleanType
2133 status;
2134
cristybb503372010-05-27 20:51:26 +00002135 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002136 i,
2137 j;
2138
2139 size_t
2140 length;
2141
2142 unsigned char
2143 *pixels;
2144
cristybb503372010-05-27 20:51:26 +00002145 size_t
cristy3ed852e2009-09-05 21:47:34 +00002146 test;
2147
2148 (void) output_filename;
2149 test=0;
cristy1e604812011-05-19 18:07:50 +00002150 (void) FormatLocaleFile(stdout,
2151 "validate the import and export of image pixels:\n");
cristy3ed852e2009-09-05 21:47:34 +00002152 for (i=0; reference_map[i] != (char *) NULL; i++)
2153 {
2154 for (j=0; reference_storage[j].type != UndefinedPixel; j++)
2155 {
2156 /*
2157 Generate reference image.
2158 */
2159 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00002160 (void) FormatLocaleFile(stdout," test %.20g: %s/%s",(double) (test++),
cristy042ee782011-04-22 18:48:30 +00002161 reference_map[i],CommandOptionToMnemonic(MagickStorageOptions,
cristy3ed852e2009-09-05 21:47:34 +00002162 reference_storage[j].type));
2163 (void) CopyMagickString(image_info->filename,reference_filename,
2164 MaxTextExtent);
2165 reference_image=ReadImage(image_info,exception);
2166 if (reference_image == (Image *) NULL)
2167 {
cristy1e604812011-05-19 18:07:50 +00002168 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2169 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002170 (*fail)++;
2171 continue;
2172 }
2173 if (LocaleNCompare(reference_map[i],"cmy",3) == 0)
cristy2c404222012-06-10 15:36:30 +00002174 (void) SetImageColorspace(reference_image,CMYKColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +00002175 length=strlen(reference_map[i])*reference_image->columns*
2176 reference_image->rows*reference_storage[j].quantum;
2177 pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
2178 if (pixels == (unsigned char *) NULL)
2179 {
cristy1e604812011-05-19 18:07:50 +00002180 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2181 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002182 (*fail)++;
2183 reference_image=DestroyImage(reference_image);
2184 continue;
2185 }
2186 (void) ResetMagickMemory(pixels,0,length*sizeof(*pixels));
2187 status=ExportImagePixels(reference_image,0,0,reference_image->columns,
2188 reference_image->rows,reference_map[i],reference_storage[j].type,pixels,
2189 exception);
2190 if (status == MagickFalse)
2191 {
cristy1e604812011-05-19 18:07:50 +00002192 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2193 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002194 (*fail)++;
2195 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2196 reference_image=DestroyImage(reference_image);
2197 continue;
2198 }
cristyd55c9352011-10-20 15:29:22 +00002199 (void) SetImageBackgroundColor(reference_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002200 status=ImportImagePixels(reference_image,0,0,reference_image->columns,
2201 reference_image->rows,reference_map[i],reference_storage[j].type,
cristy018f07f2011-09-04 21:15:19 +00002202 pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002203 if (status == MagickFalse)
2204 {
cristy1e604812011-05-19 18:07:50 +00002205 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2206 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002207 (*fail)++;
2208 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2209 reference_image=DestroyImage(reference_image);
2210 continue;
2211 }
2212 /*
2213 Read reconstruct image.
2214 */
cristy9950d572011-10-01 18:22:35 +00002215 reconstruct_image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00002216 (void) SetImageExtent(reconstruct_image,reference_image->columns,
cristy655a8d12011-08-05 19:24:28 +00002217 reference_image->rows,exception);
2218 (void) SetImageColorspace(reconstruct_image,reference_image->colorspace,
2219 exception);
cristyd55c9352011-10-20 15:29:22 +00002220 (void) SetImageBackgroundColor(reconstruct_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002221 status=ImportImagePixels(reconstruct_image,0,0,reconstruct_image->columns,
2222 reconstruct_image->rows,reference_map[i],reference_storage[j].type,
cristy018f07f2011-09-04 21:15:19 +00002223 pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002224 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2225 if (status == MagickFalse)
2226 {
cristy1e604812011-05-19 18:07:50 +00002227 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2228 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002229 (*fail)++;
2230 reference_image=DestroyImage(reference_image);
2231 continue;
2232 }
2233 /*
2234 Compare reference to reconstruct image.
2235 */
cristy8a9106f2011-07-05 14:39:26 +00002236 difference_image=CompareImages(reference_image,reconstruct_image,
cristy864c6a82012-06-19 16:45:22 +00002237 RootMeanSquaredErrorMetric,&distortion,exception);
cristy3ed852e2009-09-05 21:47:34 +00002238 reconstruct_image=DestroyImage(reconstruct_image);
2239 reference_image=DestroyImage(reference_image);
2240 if (difference_image == (Image *) NULL)
2241 {
cristy1e604812011-05-19 18:07:50 +00002242 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2243 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002244 (*fail)++;
2245 continue;
2246 }
2247 difference_image=DestroyImage(difference_image);
cristy14154222012-06-15 23:21:49 +00002248 if ((QuantumScale*distortion) > 0.0)
cristy3ed852e2009-09-05 21:47:34 +00002249 {
cristyb51dff52011-05-19 16:55:47 +00002250 (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
cristy14154222012-06-15 23:21:49 +00002251 QuantumScale*distortion);
cristy3ed852e2009-09-05 21:47:34 +00002252 (*fail)++;
2253 continue;
2254 }
cristyb51dff52011-05-19 16:55:47 +00002255 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00002256 }
2257 }
cristyb51dff52011-05-19 16:55:47 +00002258 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00002259 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2260 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00002261 return(test);
2262}
2263
2264/*
2265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2266% %
2267% %
2268% %
2269% V a l i d a t e M o n t a g e C o m m a n d %
2270% %
2271% %
2272% %
2273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274%
2275% ValidateMontageCommand() validates the ImageMagick montage command line
2276% program and returns the number of validation tests that passed and failed.
2277%
2278% The format of the ValidateMontageCommand method is:
2279%
cristybb503372010-05-27 20:51:26 +00002280% size_t ValidateMontageCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00002281% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00002282% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002283%
2284% A description of each parameter follows:
2285%
2286% o image_info: the image info.
2287%
2288% o reference_filename: the reference image filename.
2289%
2290% o output_filename: the output image filename.
2291%
2292% o fail: return the number of validation tests that pass.
2293%
2294% o exception: return any errors or warnings in this structure.
2295%
2296*/
cristybb503372010-05-27 20:51:26 +00002297static size_t ValidateMontageCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00002298 const char *reference_filename,const char *output_filename,size_t *fail,
2299 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002300{
2301 char
2302 **arguments,
2303 command[MaxTextExtent];
2304
2305 int
2306 number_arguments;
2307
2308 MagickBooleanType
2309 status;
2310
cristybb503372010-05-27 20:51:26 +00002311 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002312 i,
2313 j;
2314
cristybb503372010-05-27 20:51:26 +00002315 size_t
cristy3ed852e2009-09-05 21:47:34 +00002316 test;
2317
2318 test=0;
cristyb51dff52011-05-19 16:55:47 +00002319 (void) FormatLocaleFile(stdout,"validate montage command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00002320 for (i=0; montage_options[i] != (char *) NULL; i++)
2321 {
2322 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00002323 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
cristy6aa47ad2010-05-28 19:32:32 +00002324 montage_options[i]);
cristyb51dff52011-05-19 16:55:47 +00002325 (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s %s",
cristy3ed852e2009-09-05 21:47:34 +00002326 reference_filename,montage_options[i],reference_filename,
2327 output_filename);
2328 arguments=StringToArgv(command,&number_arguments);
2329 if (arguments == (char **) NULL)
2330 {
cristy1e604812011-05-19 18:07:50 +00002331 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2332 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002333 (*fail)++;
2334 continue;
2335 }
2336 status=MontageImageCommand(image_info,number_arguments,arguments,
2337 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00002338 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00002339 arguments[j]=DestroyString(arguments[j]);
2340 arguments=(char **) RelinquishMagickMemory(arguments);
2341 if (status != MagickFalse)
2342 {
cristy1e604812011-05-19 18:07:50 +00002343 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2344 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002345 (*fail)++;
2346 continue;
2347 }
cristyb51dff52011-05-19 16:55:47 +00002348 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00002349 }
cristyb51dff52011-05-19 16:55:47 +00002350 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00002351 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2352 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00002353 return(test);
2354}
2355
2356/*
2357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2358% %
2359% %
2360% %
2361% V a l i d a t e S t r e a m C o m m a n d %
2362% %
2363% %
2364% %
2365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2366%
2367% ValidateStreamCommand() validates the ImageMagick stream command line
2368% program and returns the number of validation tests that passed and failed.
2369%
2370% The format of the ValidateStreamCommand method is:
2371%
cristybb503372010-05-27 20:51:26 +00002372% size_t ValidateStreamCommand(ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00002373% const char *reference_filename,const char *output_filename,
cristybb503372010-05-27 20:51:26 +00002374% size_t *fail,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002375%
2376% A description of each parameter follows:
2377%
2378% o image_info: the image info.
2379%
2380% o reference_filename: the reference image filename.
2381%
2382% o output_filename: the output image filename.
2383%
2384% o fail: return the number of validation tests that pass.
2385%
2386% o exception: return any errors or warnings in this structure.
2387%
2388*/
cristybb503372010-05-27 20:51:26 +00002389static size_t ValidateStreamCommand(ImageInfo *image_info,
cristy0d772ed2012-11-10 14:34:50 +00002390 const char *reference_filename,const char *output_filename,size_t *fail,
2391 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002392{
2393 char
2394 **arguments,
2395 command[MaxTextExtent];
2396
2397 int
2398 number_arguments;
2399
2400 MagickBooleanType
2401 status;
2402
cristybb503372010-05-27 20:51:26 +00002403 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002404 i,
2405 j;
2406
cristybb503372010-05-27 20:51:26 +00002407 size_t
cristy3ed852e2009-09-05 21:47:34 +00002408 test;
2409
2410 test=0;
cristyb51dff52011-05-19 16:55:47 +00002411 (void) FormatLocaleFile(stdout,"validate stream command line program:\n");
cristy3ed852e2009-09-05 21:47:34 +00002412 for (i=0; stream_options[i] != (char *) NULL; i++)
2413 {
2414 CatchException(exception);
cristyb51dff52011-05-19 16:55:47 +00002415 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
cristy6aa47ad2010-05-28 19:32:32 +00002416 stream_options[i]);
cristyb51dff52011-05-19 16:55:47 +00002417 (void) FormatLocaleString(command,MaxTextExtent,"%s %s %s",
cristy3ed852e2009-09-05 21:47:34 +00002418 stream_options[i],reference_filename,output_filename);
2419 arguments=StringToArgv(command,&number_arguments);
2420 if (arguments == (char **) NULL)
2421 {
cristy1e604812011-05-19 18:07:50 +00002422 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2423 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002424 (*fail)++;
2425 continue;
2426 }
2427 status=StreamImageCommand(image_info,number_arguments,arguments,
2428 (char **) NULL,exception);
cristye42f6582012-02-11 17:59:50 +00002429 for (j=0; j < (ssize_t) number_arguments; j++)
cristy3ed852e2009-09-05 21:47:34 +00002430 arguments[j]=DestroyString(arguments[j]);
2431 arguments=(char **) RelinquishMagickMemory(arguments);
2432 if (status != MagickFalse)
2433 {
cristy1e604812011-05-19 18:07:50 +00002434 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2435 GetMagickModule());
cristy3ed852e2009-09-05 21:47:34 +00002436 (*fail)++;
2437 continue;
2438 }
cristyb51dff52011-05-19 16:55:47 +00002439 (void) FormatLocaleFile(stdout,"... pass.\n");
cristy3ed852e2009-09-05 21:47:34 +00002440 }
cristyb51dff52011-05-19 16:55:47 +00002441 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00002442 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2443 (double) (test-(*fail)),(double) *fail);
cristy3ed852e2009-09-05 21:47:34 +00002444 return(test);
2445}
2446
2447/*
2448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2449% %
2450% %
2451% %
2452% M a i n %
2453% %
2454% %
2455% %
2456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2457%
2458%
2459*/
2460
2461static MagickBooleanType ValidateUsage(void)
2462{
2463 const char
2464 **p;
2465
2466 static const char
2467 *miscellaneous[]=
2468 {
2469 "-debug events display copious debugging information",
2470 "-help print program options",
2471 "-log format format of debugging information",
2472 "-validate type validation type",
2473 "-version print version information",
2474 (char *) NULL
2475 },
2476 *settings[]=
2477 {
2478 "-regard-warnings pay attention to warning messages",
2479 "-verbose print detailed information about the image",
2480 (char *) NULL
2481 };
2482
cristybb503372010-05-27 20:51:26 +00002483 (void) printf("Version: %s\n",GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00002484 (void) printf("Copyright: %s\n\n",GetMagickCopyright());
cristyb28d6472009-10-17 20:13:35 +00002485 (void) printf("Features: %s\n",GetMagickFeatures());
cristy3ed852e2009-09-05 21:47:34 +00002486 (void) printf("Usage: %s [options ...] reference-file\n",GetClientName());
2487 (void) printf("\nValidate Settings:\n");
2488 for (p=settings; *p != (char *) NULL; p++)
2489 (void) printf(" %s\n",*p);
2490 (void) printf("\nMiscellaneous Options:\n");
2491 for (p=miscellaneous; *p != (char *) NULL; p++)
2492 (void) printf(" %s\n",*p);
2493 return(MagickTrue);
2494}
2495
2496int main(int argc,char **argv)
2497{
2498#define DestroyValidate() \
2499{ \
cristy3ed852e2009-09-05 21:47:34 +00002500 image_info=DestroyImageInfo(image_info); \
2501 exception=DestroyExceptionInfo(exception); \
2502}
2503#define ThrowValidateException(asperity,tag,option) \
2504{ \
2505 (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
2506 option); \
2507 CatchException(exception); \
2508 DestroyValidate(); \
2509 return(MagickFalse); \
2510}
2511
2512 char
2513 output_filename[MaxTextExtent],
2514 reference_filename[MaxTextExtent],
2515 *option;
2516
2517 double
2518 elapsed_time,
2519 user_time;
2520
2521 ExceptionInfo
2522 *exception;
2523
2524 Image
2525 *reference_image;
2526
2527 ImageInfo
2528 *image_info;
2529
2530 MagickBooleanType
2531 regard_warnings,
2532 status;
2533
cristy9cafe592012-11-17 21:17:59 +00002534 MagickSizeType
2535 memory_resource,
2536 map_resource;
2537
cristybb503372010-05-27 20:51:26 +00002538 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002539 i;
2540
2541 TimerInfo
2542 *timer;
2543
cristybb503372010-05-27 20:51:26 +00002544 size_t
cristy3ed852e2009-09-05 21:47:34 +00002545 fail,
2546 iterations,
2547 tests;
2548
2549 ValidateType
2550 type;
2551
2552 /*
2553 Validate the ImageMagick image processing suite.
2554 */
cristyb4d552c2012-12-13 15:42:17 +00002555 MagickCoreGenesis(*argv,MagickTrue);
cristyef2fdc62012-12-12 11:16:48 +00002556 (void) setlocale(LC_ALL,"");
2557 (void) setlocale(LC_NUMERIC,"C");
cristy3ed852e2009-09-05 21:47:34 +00002558 iterations=1;
2559 status=MagickFalse;
2560 type=AllValidate;
2561 regard_warnings=MagickFalse;
cristyd8862902011-02-20 21:12:27 +00002562 (void) regard_warnings;
cristy3ed852e2009-09-05 21:47:34 +00002563 exception=AcquireExceptionInfo();
2564 image_info=AcquireImageInfo();
2565 (void) CopyMagickString(image_info->filename,ReferenceFilename,MaxTextExtent);
cristybb503372010-05-27 20:51:26 +00002566 for (i=1; i < (ssize_t) argc; i++)
cristy3ed852e2009-09-05 21:47:34 +00002567 {
2568 option=argv[i];
cristy042ee782011-04-22 18:48:30 +00002569 if (IsCommandOption(option) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002570 {
2571 (void) CopyMagickString(image_info->filename,option,MaxTextExtent);
2572 continue;
2573 }
2574 switch (*(option+1))
2575 {
2576 case 'b':
2577 {
2578 if (LocaleCompare("bench",option+1) == 0)
2579 {
cristye27293e2009-12-18 02:53:20 +00002580 iterations=StringToUnsignedLong(argv[++i]);
cristy3ed852e2009-09-05 21:47:34 +00002581 break;
2582 }
2583 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2584 }
2585 case 'd':
2586 {
2587 if (LocaleCompare("debug",option+1) == 0)
2588 {
2589 (void) SetLogEventMask(argv[++i]);
2590 break;
2591 }
2592 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2593 }
2594 case 'h':
2595 {
2596 if (LocaleCompare("help",option+1) == 0)
2597 {
2598 (void) ValidateUsage();
2599 return(0);
2600 }
2601 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2602 }
2603 case 'l':
2604 {
2605 if (LocaleCompare("log",option+1) == 0)
2606 {
2607 if (*option != '+')
2608 (void) SetLogFormat(argv[i+1]);
2609 break;
2610 }
2611 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2612 }
2613 case 'r':
2614 {
2615 if (LocaleCompare("regard-warnings",option+1) == 0)
2616 {
2617 regard_warnings=MagickTrue;
2618 break;
2619 }
2620 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2621 }
2622 case 'v':
2623 {
2624 if (LocaleCompare("validate",option+1) == 0)
2625 {
cristybb503372010-05-27 20:51:26 +00002626 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002627 validate;
2628
2629 if (*option == '+')
2630 break;
2631 i++;
cristybb503372010-05-27 20:51:26 +00002632 if (i == (ssize_t) argc)
cristy3ed852e2009-09-05 21:47:34 +00002633 ThrowValidateException(OptionError,"MissingArgument",option);
cristy042ee782011-04-22 18:48:30 +00002634 validate=ParseCommandOption(MagickValidateOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +00002635 argv[i]);
2636 if (validate < 0)
2637 ThrowValidateException(OptionError,"UnrecognizedValidateType",
2638 argv[i]);
2639 type=(ValidateType) validate;
2640 break;
2641 }
2642 if ((LocaleCompare("version",option+1) == 0) ||
2643 (LocaleCompare("-version",option+1) == 0))
2644 {
cristyb51dff52011-05-19 16:55:47 +00002645 (void) FormatLocaleFile(stdout,"Version: %s\n",
cristybb503372010-05-27 20:51:26 +00002646 GetMagickVersion((size_t *) NULL));
cristy1e604812011-05-19 18:07:50 +00002647 (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
2648 GetMagickCopyright());
2649 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
2650 GetMagickFeatures());
cristy3ed852e2009-09-05 21:47:34 +00002651 return(0);
2652 }
2653 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2654 }
2655 default:
2656 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2657 }
2658 }
cristy205e21f2009-09-28 19:01:46 +00002659 timer=(TimerInfo *) NULL;
cristy8b76e552009-09-28 18:20:20 +00002660 if (iterations > 1)
2661 timer=AcquireTimerInfo();
cristy3ed852e2009-09-05 21:47:34 +00002662 reference_image=ReadImage(image_info,exception);
2663 tests=0;
2664 fail=0;
2665 if (reference_image == (Image *) NULL)
2666 fail++;
2667 else
2668 {
2669 if (LocaleCompare(image_info->filename,ReferenceFilename) == 0)
2670 (void) CopyMagickString(reference_image->magick,ReferenceImageFormat,
2671 MaxTextExtent);
2672 (void) AcquireUniqueFilename(reference_filename);
2673 (void) AcquireUniqueFilename(output_filename);
2674 (void) CopyMagickString(reference_image->filename,reference_filename,
2675 MaxTextExtent);
cristy6f9e0d32011-08-28 16:32:09 +00002676 status=WriteImage(image_info,reference_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002677 reference_image=DestroyImage(reference_image);
2678 if (status == MagickFalse)
2679 fail++;
2680 else
2681 {
cristyb51dff52011-05-19 16:55:47 +00002682 (void) FormatLocaleFile(stdout,"Version: %s\n",
cristybb503372010-05-27 20:51:26 +00002683 GetMagickVersion((size_t *) NULL));
cristyb51dff52011-05-19 16:55:47 +00002684 (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002685 GetMagickCopyright());
cristy1e604812011-05-19 18:07:50 +00002686 (void) FormatLocaleFile(stdout,
2687 "ImageMagick Validation Suite (%s)\n\n",CommandOptionToMnemonic(
2688 MagickValidateOptions,(ssize_t) type));
cristy80e870e2013-05-07 12:23:02 +00002689 if ((type & ColorspaceValidate) != 0)
cristy572e0972013-05-07 12:51:28 +00002690 tests+=ValidateColorspaces(image_info,&fail,exception);
cristy3ed852e2009-09-05 21:47:34 +00002691 if ((type & CompareValidate) != 0)
2692 tests+=ValidateCompareCommand(image_info,reference_filename,
2693 output_filename,&fail,exception);
2694 if ((type & CompositeValidate) != 0)
2695 tests+=ValidateCompositeCommand(image_info,reference_filename,
2696 output_filename,&fail,exception);
2697 if ((type & ConvertValidate) != 0)
2698 tests+=ValidateConvertCommand(image_info,reference_filename,
2699 output_filename,&fail,exception);
cristy247eebde2013-06-13 01:01:43 +00002700 if ((type & FormatsDiskValidate) != 0)
cristyf044a4d2012-11-17 21:10:20 +00002701 {
cristy9cafe592012-11-17 21:17:59 +00002702 memory_resource=SetMagickResourceLimit(MemoryResource,0);
cristy247eebde2013-06-13 01:01:43 +00002703 map_resource=SetMagickResourceLimit(MapResource,0);
2704 (void) FormatLocaleFile(stdout,"[pixel-cache: disk] ");
cristyf044a4d2012-11-17 21:10:20 +00002705 tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
2706 output_filename,&fail,exception);
2707 (void) FormatLocaleFile(stdout,"[pixel-cache: disk] ");
cristy247eebde2013-06-13 01:01:43 +00002708 tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
cristyf044a4d2012-11-17 21:10:20 +00002709 output_filename,&fail,exception);
cristy9cafe592012-11-17 21:17:59 +00002710 (void) SetMagickResourceLimit(MemoryResource,memory_resource);
2711 (void) SetMagickResourceLimit(MapResource,map_resource);
cristyf044a4d2012-11-17 21:10:20 +00002712 }
cristy247eebde2013-06-13 01:01:43 +00002713 if ((type & FormatsMapValidate) != 0)
cristybda201a2012-11-08 16:44:00 +00002714 {
cristy247eebde2013-06-13 01:01:43 +00002715 memory_resource=SetMagickResourceLimit(MemoryResource,0);
2716 (void) FormatLocaleFile(stdout,"[pixel-cache: memory-mapped] ");
2717 tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
cristybda201a2012-11-08 16:44:00 +00002718 output_filename,&fail,exception);
cristy34c290f2012-11-09 00:44:12 +00002719 (void) FormatLocaleFile(stdout,"[pixel-cache: memory-mapped] ");
cristybda201a2012-11-08 16:44:00 +00002720 tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
2721 output_filename,&fail,exception);
cristy9cafe592012-11-17 21:17:59 +00002722 (void) SetMagickResourceLimit(MemoryResource,memory_resource);
cristy247eebde2013-06-13 01:01:43 +00002723 }
2724 if ((type & FormatsMemoryValidate) != 0)
2725 {
2726 (void) FormatLocaleFile(stdout,"[pixel-cache: memory] ");
2727 tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
2728 output_filename,&fail,exception);
2729 (void) FormatLocaleFile(stdout,"[pixel-cache: memory] ");
2730 tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
2731 output_filename,&fail,exception);
cristybda201a2012-11-08 16:44:00 +00002732 }
cristy3ed852e2009-09-05 21:47:34 +00002733 if ((type & IdentifyValidate) != 0)
2734 tests+=ValidateIdentifyCommand(image_info,reference_filename,
2735 output_filename,&fail,exception);
2736 if ((type & ImportExportValidate) != 0)
2737 tests+=ValidateImportExportPixels(image_info,reference_filename,
2738 output_filename,&fail,exception);
2739 if ((type & MontageValidate) != 0)
2740 tests+=ValidateMontageCommand(image_info,reference_filename,
2741 output_filename,&fail,exception);
2742 if ((type & StreamValidate) != 0)
2743 tests+=ValidateStreamCommand(image_info,reference_filename,
2744 output_filename,&fail,exception);
cristyb51dff52011-05-19 16:55:47 +00002745 (void) FormatLocaleFile(stdout,
cristy75a26232010-06-03 17:15:02 +00002746 "validation suite: %.20g tests; %.20g passed; %.20g failed.\n",
2747 (double) tests,(double) (tests-fail),(double) fail);
cristy3ed852e2009-09-05 21:47:34 +00002748 }
2749 (void) RelinquishUniqueFileResource(output_filename);
2750 (void) RelinquishUniqueFileResource(reference_filename);
2751 }
2752 if (exception->severity != UndefinedException)
2753 CatchException(exception);
2754 if (iterations > 1)
2755 {
2756 elapsed_time=GetElapsedTime(timer);
2757 user_time=GetUserTime(timer);
cristyb51dff52011-05-19 16:55:47 +00002758 (void) FormatLocaleFile(stderr,
cristy75a26232010-06-03 17:15:02 +00002759 "Performance: %.20gi %gips %0.3fu %ld:%02ld.%03ld\n",(double)
cristy6aa47ad2010-05-28 19:32:32 +00002760 iterations,1.0*iterations/elapsed_time,user_time,(long)
2761 (elapsed_time/60.0),(long) ceil(fmod(elapsed_time,60.0)),
2762 (long) (1000.0*(elapsed_time-floor(elapsed_time))));
cristy8b76e552009-09-28 18:20:20 +00002763 timer=DestroyTimerInfo(timer);
cristy3ed852e2009-09-05 21:47:34 +00002764 }
2765 DestroyValidate();
2766 MagickCoreTerminus();
2767 return(fail == 0 ? 0 : 1);
2768}