1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % %
7 % V V AAA L IIIII DDDD AAA TTTTT EEEEE %
8 % V V A A L I D D A A T E %
9 % V V AAAAA L I D D AAAAA T EEE %
10 % V V A A L I D D A A T E %
11 % V A A LLLLL IIIII DDDD A A T EEEEE %
12 % %
13 % %
14 % ImageMagick Validation Suite %
15 % %
16 % Software Design %
17 % Cristy %
18 % March 2001 %
19 % %
20 % %
21 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
22 % dedicated to making software imaging solutions freely available. %
23 % %
24 % You may not use this file except in compliance with the License. You may %
25 % obtain a copy of the License at %
26 % %
27 % https://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 "MagickWand/studio.h"
44 #include "MagickWand/MagickWand.h"
45 #include "MagickCore/colorspace-private.h"
46 #include "MagickCore/gem.h"
47 #include "MagickCore/resource_.h"
48 #include "MagickCore/string-private.h"
49 #include "validate.h"
50
51 /*
52 Define declarations.
53 */
54 #define CIEEpsilon (216.0/24389.0)
55 #define CIEK (24389.0/27.0)
56 #define D65X 0.95047
57 #define D65Y 1.0
58 #define D65Z 1.08883
59 #define ReferenceEpsilon (QuantumRange*1.0e-2)
60
61 /*
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 % %
64 % %
65 % %
66 % V a l i d a t e C o l o r s p a c e s %
67 % %
68 % %
69 % %
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 %
72 % ValidateColorspaces() validates the ImageMagick colorspaces and returns the
73 % number of validation tests that passed and failed.
74 %
75 % The format of the ValidateColorspaces method is:
76 %
77 % size_t ValidateColorspaces(ImageInfo *image_info,size_t *fails,
78 % ExceptionInfo *exception)
79 %
80 % A description of each parameter follows:
81 %
82 % o image_info: the image info.
83 %
84 % o fail: return the number of validation tests that pass.
85 %
86 % o exception: return any errors or warnings in this structure.
87 %
88 */
89
ConvertHSIToRGB(const double hue,const double saturation,const double intensity,double * red,double * green,double * blue)90 static void ConvertHSIToRGB(const double hue,const double saturation,
91 const double intensity,double *red,double *green,double *blue)
92 {
93 double
94 h;
95
96 h=360.0*hue;
97 h-=360.0*floor(h/360.0);
98 if (h < 120.0)
99 {
100 *blue=intensity*(1.0-saturation);
101 *red=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
102 (MagickPI/180.0)));
103 *green=3.0*intensity-*red-*blue;
104 }
105 else
106 if (h < 240.0)
107 {
108 h-=120.0;
109 *red=intensity*(1.0-saturation);
110 *green=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
111 (MagickPI/180.0)));
112 *blue=3.0*intensity-*red-*green;
113 }
114 else
115 {
116 h-=240.0;
117 *green=intensity*(1.0-saturation);
118 *blue=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
119 (MagickPI/180.0)));
120 *red=3.0*intensity-*green-*blue;
121 }
122 *red*=QuantumRange;
123 *green*=QuantumRange;
124 *blue*=QuantumRange;
125 }
126
ConvertRGBToHSI(const double red,const double green,const double blue,double * hue,double * saturation,double * intensity)127 static void ConvertRGBToHSI(const double red,const double green,
128 const double blue,double *hue,double *saturation,double *intensity)
129 {
130 double
131 alpha,
132 beta;
133
134 *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0;
135 if (*intensity <= 0.0)
136 {
137 *hue=0.0;
138 *saturation=0.0;
139 return;
140 }
141 *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
142 QuantumScale*blue))/(*intensity);
143 alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
144 beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue);
145 *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
146 if (*hue < 0.0)
147 *hue+=1.0;
148 }
149
ConvertHSVToRGB(const double hue,const double saturation,const double value,double * red,double * green,double * blue)150 static void ConvertHSVToRGB(const double hue,const double saturation,
151 const double value,double *red,double *green,double *blue)
152 {
153 double
154 c,
155 h,
156 min,
157 x;
158
159 h=hue*360.0;
160 c=value*saturation;
161 min=value-c;
162 h-=360.0*floor(h/360.0);
163 h/=60.0;
164 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
165 switch ((int) floor(h))
166 {
167 case 0:
168 {
169 *red=QuantumRange*(min+c);
170 *green=QuantumRange*(min+x);
171 *blue=QuantumRange*min;
172 break;
173 }
174 case 1:
175 {
176 *red=QuantumRange*(min+x);
177 *green=QuantumRange*(min+c);
178 *blue=QuantumRange*min;
179 break;
180 }
181 case 2:
182 {
183 *red=QuantumRange*min;
184 *green=QuantumRange*(min+c);
185 *blue=QuantumRange*(min+x);
186 break;
187 }
188 case 3:
189 {
190 *red=QuantumRange*min;
191 *green=QuantumRange*(min+x);
192 *blue=QuantumRange*(min+c);
193 break;
194 }
195 case 4:
196 {
197 *red=QuantumRange*(min+x);
198 *green=QuantumRange*min;
199 *blue=QuantumRange*(min+c);
200 break;
201 }
202 case 5:
203 {
204 *red=QuantumRange*(min+c);
205 *green=QuantumRange*min;
206 *blue=QuantumRange*(min+x);
207 break;
208 }
209 default:
210 {
211 *red=0.0;
212 *green=0.0;
213 *blue=0.0;
214 }
215 }
216 }
217
ConvertRGBToXYZ(const double red,const double green,const double blue,double * X,double * Y,double * Z)218 static inline void ConvertRGBToXYZ(const double red,const double green,
219 const double blue,double *X,double *Y,double *Z)
220 {
221 double
222 b,
223 g,
224 r;
225
226 r=QuantumScale*DecodePixelGamma(red);
227 g=QuantumScale*DecodePixelGamma(green);
228 b=QuantumScale*DecodePixelGamma(blue);
229 *X=0.41239558896741421610*r+0.35758343076371481710*g+0.18049264738170157350*b;
230 *Y=0.21258623078559555160*r+0.71517030370341084990*g+0.07220049864333622685*b;
231 *Z=0.01929721549174694484*r+0.11918386458084853180*g+0.95049712513157976600*b;
232 }
233
ConvertXYZToLab(const double X,const double Y,const double Z,double * L,double * a,double * b)234 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
235 double *L,double *a,double *b)
236 {
237 double
238 x,
239 y,
240 z;
241
242 if ((X/D65X) > CIEEpsilon)
243 x=pow(X/D65X,1.0/3.0);
244 else
245 x=(CIEK*X/D65X+16.0)/116.0;
246 if ((Y/D65Y) > CIEEpsilon)
247 y=pow(Y/D65Y,1.0/3.0);
248 else
249 y=(CIEK*Y/D65Y+16.0)/116.0;
250 if ((Z/D65Z) > CIEEpsilon)
251 z=pow(Z/D65Z,1.0/3.0);
252 else
253 z=(CIEK*Z/D65Z+16.0)/116.0;
254 *L=((116.0*y)-16.0)/100.0;
255 *a=(500.0*(x-y))/255.0+0.5;
256 *b=(200.0*(y-z))/255.0+0.5;
257 }
258
ConvertRGBToLab(const double red,const double green,const double blue,double * L,double * a,double * b)259 static void ConvertRGBToLab(const double red,const double green,
260 const double blue,double *L,double *a,double *b)
261 {
262 double
263 X,
264 Y,
265 Z;
266
267 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
268 ConvertXYZToLab(X,Y,Z,L,a,b);
269 }
270
ConvertLabToXYZ(const double L,const double a,const double b,double * X,double * Y,double * Z)271 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
272 double *X,double *Y,double *Z)
273 {
274 double
275 x,
276 y,
277 z;
278
279 y=(L+16.0)/116.0;
280 x=y+a/500.0;
281 z=y-b/200.0;
282 if ((x*x*x) > CIEEpsilon)
283 x=(x*x*x);
284 else
285 x=(116.0*x-16.0)/CIEK;
286 if ((y*y*y) > CIEEpsilon)
287 y=(y*y*y);
288 else
289 y=L/CIEK;
290 if ((z*z*z) > CIEEpsilon)
291 z=(z*z*z);
292 else
293 z=(116.0*z-16.0)/CIEK;
294 *X=D65X*x;
295 *Y=D65Y*y;
296 *Z=D65Z*z;
297 }
298
ConvertXYZToRGB(const double x,const double y,const double z,double * red,double * green,double * blue)299 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
300 double *red,double *green,double *blue)
301 {
302 double
303 b,
304 g,
305 r;
306
307 r=3.2406*x-1.5372*y-0.4986*z;
308 g=(-0.9689*x+1.8758*y+0.0415*z);
309 b=0.0557*x-0.2040*y+1.0570*z;
310 *red=EncodePixelGamma(QuantumRange*r);
311 *green=EncodePixelGamma(QuantumRange*g);
312 *blue=EncodePixelGamma(QuantumRange*b);
313 }
314
ConvertLabToRGB(const double L,const double a,const double b,double * red,double * green,double * blue)315 static inline void ConvertLabToRGB(const double L,const double a,
316 const double b,double *red,double *green,double *blue)
317 {
318 double
319 X,
320 Y,
321 Z;
322
323 ConvertLabToXYZ(L*100.0,255.0*(a-0.5),255.0*(b-0.5),&X,&Y,&Z);
324 ConvertXYZToRGB(X,Y,Z,red,green,blue);
325 }
326
ConvertRGBToYPbPr(const double red,const double green,const double blue,double * Y,double * Pb,double * Pr)327 static void ConvertRGBToYPbPr(const double red,const double green,
328 const double blue,double *Y,double *Pb,double *Pr)
329 {
330 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
331 *Pb=QuantumScale*((-0.1687367)*red-0.331264*green+0.5*blue)+0.5;
332 *Pr=QuantumScale*(0.5*red-0.418688*green-0.081312*blue)+0.5;
333 }
334
ConvertRGBToYCbCr(const double red,const double green,const double blue,double * Y,double * Cb,double * Cr)335 static void ConvertRGBToYCbCr(const double red,const double green,
336 const double blue,double *Y,double *Cb,double *Cr)
337 {
338 ConvertRGBToYPbPr(red,green,blue,Y,Cb,Cr);
339 }
340
ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr,double * red,double * green,double * blue)341 static void ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr,
342 double *red,double *green,double *blue)
343 {
344 *red=QuantumRange*(0.99999999999914679361*Y-1.2188941887145875e-06*(Pb-0.5)+
345 1.4019995886561440468*(Pr-0.5));
346 *green=QuantumRange*(0.99999975910502514331*Y-0.34413567816504303521*(Pb-0.5)-
347 0.71413649331646789076*(Pr-0.5));
348 *blue=QuantumRange*(1.00000124040004623180*Y+1.77200006607230409200*(Pb-0.5)+
349 2.1453384174593273e-06*(Pr-0.5));
350 }
351
ConvertYCbCrToRGB(const double Y,const double Cb,const double Cr,double * red,double * green,double * blue)352 static void ConvertYCbCrToRGB(const double Y,const double Cb,
353 const double Cr,double *red,double *green,double *blue)
354 {
355 ConvertYPbPrToRGB(Y,Cb,Cr,red,green,blue);
356 }
357
ConvertLCHabToXYZ(const double luma,const double chroma,const double hue,double * X,double * Y,double * Z)358 static inline void ConvertLCHabToXYZ(const double luma,const double chroma,
359 const double hue,double *X,double *Y,double *Z)
360 {
361 ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
362 sin(hue*MagickPI/180.0),X,Y,Z);
363 }
364
ConvertLCHabToRGB(const double luma,const double chroma,const double hue,double * red,double * green,double * blue)365 static void ConvertLCHabToRGB(const double luma,const double chroma,
366 const double hue,double *red,double *green,double *blue)
367 {
368 double
369 X,
370 Y,
371 Z;
372
373 ConvertLCHabToXYZ(luma*100.0,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z);
374 ConvertXYZToRGB(X,Y,Z,red,green,blue);
375 }
376
ConvertRGBToHSV(const double red,const double green,const double blue,double * hue,double * saturation,double * value)377 static void ConvertRGBToHSV(const double red,const double green,
378 const double blue,double *hue,double *saturation,double *value)
379 {
380 double
381 c,
382 max,
383 min;
384
385 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
386 QuantumScale*blue));
387 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
388 QuantumScale*blue));
389 c=max-min;
390 *value=max;
391 if (c <= 0.0)
392 {
393 *hue=0.0;
394 *saturation=0.0;
395 return;
396 }
397 if (max == (QuantumScale*red))
398 {
399 *hue=(QuantumScale*green-QuantumScale*blue)/c;
400 if ((QuantumScale*green) < (QuantumScale*blue))
401 *hue+=6.0;
402 }
403 else
404 if (max == (QuantumScale*green))
405 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
406 else
407 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
408 *hue*=60.0/360.0;
409 *saturation=c/max;
410 }
411
ConvertXYZToLCHab(const double X,const double Y,const double Z,double * luma,double * chroma,double * hue)412 static inline void ConvertXYZToLCHab(const double X,const double Y,
413 const double Z,double *luma,double *chroma,double *hue)
414 {
415 double
416 a,
417 b;
418
419 ConvertXYZToLab(X,Y,Z,luma,&a,&b);
420 *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5))/255.0+0.5;
421 *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI/360.0;
422 if (*hue < 0.0)
423 *hue+=1.0;
424 }
425
ConvertRGBToLCHab(const double red,const double green,const double blue,double * luma,double * chroma,double * hue)426 static void ConvertRGBToLCHab(const double red,const double green,
427 const double blue,double *luma,double *chroma,double *hue)
428 {
429 double
430 X,
431 Y,
432 Z;
433
434 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
435 ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue);
436 }
437
ConvertLMSToXYZ(const double L,const double M,const double S,double * X,double * Y,double * Z)438 static inline void ConvertLMSToXYZ(const double L,const double M,const double S,
439 double *X,double *Y,double *Z)
440 {
441 *X=1.096123820835514*L-0.278869000218287*M+0.182745179382773*S;
442 *Y=0.454369041975359*L+0.473533154307412*M+0.072097803717229*S;
443 *Z=(-0.009627608738429)*L-0.005698031216113*M+1.015325639954543*S;
444 }
445
ConvertLMSToRGB(const double L,const double M,const double S,double * red,double * green,double * blue)446 static inline void ConvertLMSToRGB(const double L,const double M,
447 const double S,double *red,double *green,double *blue)
448 {
449 double
450 X,
451 Y,
452 Z;
453
454 ConvertLMSToXYZ(L,M,S,&X,&Y,&Z);
455 ConvertXYZToRGB(X,Y,Z,red,green,blue);
456 }
457
ConvertXYZToLMS(const double x,const double y,const double z,double * L,double * M,double * S)458 static inline void ConvertXYZToLMS(const double x,const double y,
459 const double z,double *L,double *M,double *S)
460 {
461 *L=0.7328*x+0.4296*y-0.1624*z;
462 *M=(-0.7036*x+1.6975*y+0.0061*z);
463 *S=0.0030*x+0.0136*y+0.9834*z;
464 }
465
ConvertRGBToLMS(const double red,const double green,const double blue,double * L,double * M,double * S)466 static void ConvertRGBToLMS(const double red,const double green,
467 const double blue,double *L,double *M,double *S)
468 {
469 double
470 X,
471 Y,
472 Z;
473
474 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
475 ConvertXYZToLMS(X,Y,Z,L,M,S);
476 }
477
ConvertXYZToLuv(const double X,const double Y,const double Z,double * L,double * u,double * v)478 static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
479 double *L,double *u,double *v)
480 {
481 double
482 alpha;
483
484 if ((Y/D65Y) > CIEEpsilon)
485 *L=(double) (116.0*pow(Y/D65Y,1.0/3.0)-16.0);
486 else
487 *L=CIEK*(Y/D65Y);
488 alpha=PerceptibleReciprocal(X+15.0*Y+3.0*Z);
489 *u=13.0*(*L)*((4.0*alpha*X)-(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z)));
490 *v=13.0*(*L)*((9.0*alpha*Y)-(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z)));
491 *L/=100.0;
492 *u=(*u+134.0)/354.0;
493 *v=(*v+140.0)/262.0;
494 }
495
ConvertRGBToLuv(const double red,const double green,const double blue,double * L,double * u,double * v)496 static void ConvertRGBToLuv(const double red,const double green,
497 const double blue,double *L,double *u,double *v)
498 {
499 double
500 X,
501 Y,
502 Z;
503
504 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
505 ConvertXYZToLuv(X,Y,Z,L,u,v);
506 }
507
ConvertLuvToXYZ(const double L,const double u,const double v,double * X,double * Y,double * Z)508 static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
509 double *X,double *Y,double *Z)
510 {
511 if (L > (CIEK*CIEEpsilon))
512 *Y=(double) pow((L+16.0)/116.0,3.0);
513 else
514 *Y=L/CIEK;
515 *X=((*Y*((39.0*L/(v+13.0*L*(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z))))-5.0))+
516 5.0*(*Y))/((((52.0f*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/
517 3.0)-(-1.0/3.0));
518 *Z=(*X*(((52.0f*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/3.0))-
519 5.0*(*Y);
520 }
521
ConvertLuvToRGB(const double L,const double u,const double v,double * red,double * green,double * blue)522 static inline void ConvertLuvToRGB(const double L,const double u,
523 const double v,double *red,double *green,double *blue)
524 {
525 double
526 X,
527 Y,
528 Z;
529
530 ConvertLuvToXYZ(100.0*L,354.0*u-134.0,262.0*v-140.0,&X,&Y,&Z);
531 ConvertXYZToRGB(X,Y,Z,red,green,blue);
532 }
533
ConvertRGBToYDbDr(const double red,const double green,const double blue,double * Y,double * Db,double * Dr)534 static void ConvertRGBToYDbDr(const double red,const double green,
535 const double blue,double *Y,double *Db,double *Dr)
536 {
537 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
538 *Db=QuantumScale*(-0.450*red-0.883*green+1.333*blue)+0.5;
539 *Dr=QuantumScale*(-1.333*red+1.116*green+0.217*blue)+0.5;
540 }
541
ConvertYDbDrToRGB(const double Y,const double Db,const double Dr,double * red,double * green,double * blue)542 static void ConvertYDbDrToRGB(const double Y,const double Db,const double Dr,
543 double *red,double *green,double *blue)
544 {
545 *red=QuantumRange*(Y+9.2303716147657e-05*(Db-0.5)-0.52591263066186533*
546 (Dr-0.5));
547 *green=QuantumRange*(Y-0.12913289889050927*(Db-0.5)+0.26789932820759876*
548 (Dr-0.5));
549 *blue=QuantumRange*(Y+0.66467905997895482*(Db-0.5)-7.9202543533108e-05*
550 (Dr-0.5));
551 }
552
ConvertRGBToYIQ(const double red,const double green,const double blue,double * Y,double * I,double * Q)553 static void ConvertRGBToYIQ(const double red,const double green,
554 const double blue,double *Y,double *I,double *Q)
555 {
556 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
557 *I=QuantumScale*(0.595716*red-0.274453*green-0.321263*blue)+0.5;
558 *Q=QuantumScale*(0.211456*red-0.522591*green+0.311135*blue)+0.5;
559 }
560
ConvertYIQToRGB(const double Y,const double I,const double Q,double * red,double * green,double * blue)561 static void ConvertYIQToRGB(const double Y,const double I,const double Q,
562 double *red,double *green,double *blue)
563 {
564 *red=QuantumRange*(Y+0.9562957197589482261*(I-0.5)+0.6210244164652610754*
565 (Q-0.5));
566 *green=QuantumRange*(Y-0.2721220993185104464*(I-0.5)-0.6473805968256950427*
567 (Q-0.5));
568 *blue=QuantumRange*(Y-1.1069890167364901945*(I-0.5)+1.7046149983646481374*
569 (Q-0.5));
570 }
571
ConvertRGBToYUV(const double red,const double green,const double blue,double * Y,double * U,double * V)572 static void ConvertRGBToYUV(const double red,const double green,
573 const double blue,double *Y,double *U,double *V)
574 {
575 *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
576 *U=QuantumScale*((-0.147)*red-0.289*green+0.436*blue)+0.5;
577 *V=QuantumScale*(0.615*red-0.515*green-0.100*blue)+0.5;
578 }
579
ConvertYUVToRGB(const double Y,const double U,const double V,double * red,double * green,double * blue)580 static void ConvertYUVToRGB(const double Y,const double U,const double V,
581 double *red,double *green,double *blue)
582 {
583 *red=QuantumRange*(Y-3.945707070708279e-05*(U-0.5)+1.1398279671717170825*
584 (V-0.5));
585 *green=QuantumRange*(Y-0.3946101641414141437*(U-0.5)-0.5805003156565656797*
586 (V-0.5));
587 *blue=QuantumRange*(Y+2.0319996843434342537*(U-0.5)-4.813762626262513e-04*
588 (V-0.5));
589 }
590
ValidateHSIToRGB()591 static MagickBooleanType ValidateHSIToRGB()
592 {
593 double
594 r,
595 g,
596 b;
597
598 (void) FormatLocaleFile(stdout," HSIToRGB");
599 ConvertHSIToRGB(111.244375/360.0,0.295985,0.658734,&r,&g,&b);
600 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
601 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
602 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
603 return(MagickFalse);
604 return(MagickTrue);
605 }
606
ValidateRGBToHSI()607 static MagickBooleanType ValidateRGBToHSI()
608 {
609 double
610 h,
611 i,
612 s;
613
614 (void) FormatLocaleFile(stdout," RGBToHSI");
615 ConvertRGBToHSI(0.545877*QuantumRange,0.966567*QuantumRange,
616 0.463759*QuantumRange,&h,&s,&i);
617 if ((fabs(h-111.244374/360.0) >= ReferenceEpsilon) ||
618 (fabs(s-0.295985) >= ReferenceEpsilon) ||
619 (fabs(i-0.658734) >= ReferenceEpsilon))
620 return(MagickFalse);
621 return(MagickTrue);
622 }
623
ValidateHSLToRGB()624 static MagickBooleanType ValidateHSLToRGB()
625 {
626 double
627 r,
628 g,
629 b;
630
631 (void) FormatLocaleFile(stdout," HSLToRGB");
632 ConvertHSLToRGB(110.200859/360.0,0.882623,0.715163,&r,&g,&b);
633 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
634 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
635 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
636 return(MagickFalse);
637 return(MagickTrue);
638 }
639
ValidateRGBToHSL()640 static MagickBooleanType ValidateRGBToHSL()
641 {
642 double
643 h,
644 l,
645 s;
646
647 (void) FormatLocaleFile(stdout," RGBToHSL");
648 ConvertRGBToHSL(0.545877*QuantumRange,0.966567*QuantumRange,
649 0.463759*QuantumRange,&h,&s,&l);
650 if ((fabs(h-110.200859/360.0) >= ReferenceEpsilon) ||
651 (fabs(s-0.882623) >= ReferenceEpsilon) ||
652 (fabs(l-0.715163) >= ReferenceEpsilon))
653 return(MagickFalse);
654 return(MagickTrue);
655 }
656
ValidateHSVToRGB()657 static MagickBooleanType ValidateHSVToRGB()
658 {
659 double
660 r,
661 g,
662 b;
663
664 (void) FormatLocaleFile(stdout," HSVToRGB");
665 ConvertHSVToRGB(110.200859/360.0,0.520200,0.966567,&r,&g,&b);
666 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
667 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
668 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
669 return(MagickFalse);
670 return(MagickTrue);
671 }
672
ValidateRGBToHSV()673 static MagickBooleanType ValidateRGBToHSV()
674 {
675 double
676 h,
677 s,
678 v;
679
680 (void) FormatLocaleFile(stdout," RGBToHSV");
681 ConvertRGBToHSV(0.545877*QuantumRange,0.966567*QuantumRange,
682 0.463759*QuantumRange,&h,&s,&v);
683 if ((fabs(h-110.200859/360.0) >= ReferenceEpsilon) ||
684 (fabs(s-0.520200) >= ReferenceEpsilon) ||
685 (fabs(v-0.966567) >= ReferenceEpsilon))
686 return(MagickFalse);
687 return(MagickTrue);
688 }
689
ValidateRGBToJPEGYCbCr()690 static MagickBooleanType ValidateRGBToJPEGYCbCr()
691 {
692 double
693 Cb,
694 Cr,
695 Y;
696
697 (void) FormatLocaleFile(stdout," RGBToJPEGYCbCr");
698 ConvertRGBToYCbCr(0.545877*QuantumRange,0.966567*QuantumRange,
699 0.463759*QuantumRange,&Y,&Cb,&Cr);
700 if ((fabs(Y-0.783460) >= ReferenceEpsilon) ||
701 (fabs(Cb-0.319581) >= ReferenceEpsilon) ||
702 (fabs(Cr-0.330539) >= ReferenceEpsilon))
703 return(MagickFalse);
704 return(MagickTrue);
705 }
706
ValidateJPEGYCbCrToRGB()707 static MagickBooleanType ValidateJPEGYCbCrToRGB()
708 {
709 double
710 r,
711 g,
712 b;
713
714 (void) FormatLocaleFile(stdout," JPEGYCbCrToRGB");
715 ConvertYCbCrToRGB(0.783460,0.319581,0.330539,&r,&g,&b);
716 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
717 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
718 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
719 return(MagickFalse);
720 return(MagickTrue);
721 }
722
ValidateLabToRGB()723 static MagickBooleanType ValidateLabToRGB()
724 {
725 double
726 r,
727 g,
728 b;
729
730 (void) FormatLocaleFile(stdout," LabToRGB");
731 ConvertLabToRGB(88.456154/100.0,-54.671483/255+0.5,51.662818/255.0+0.5,
732 &r,&g,&b);
733 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
734 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
735 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
736 return(MagickFalse);
737 return(MagickTrue);
738 }
739
ValidateRGBToLab()740 static MagickBooleanType ValidateRGBToLab()
741 {
742 double
743 a,
744 b,
745 L;
746
747 (void) FormatLocaleFile(stdout," RGBToLab");
748 ConvertRGBToLab(0.545877*QuantumRange,0.966567*QuantumRange,
749 0.463759*QuantumRange,&L,&a,&b);
750 if ((fabs(L-(88.456154/100.0)) >= ReferenceEpsilon) ||
751 (fabs(a-(-54.671483/255.0+0.5)) >= ReferenceEpsilon) ||
752 (fabs(b-(51.662818/255.0+0.5)) >= ReferenceEpsilon))
753 return(MagickFalse);
754 return(MagickTrue);
755 }
756
ValidateLchToRGB()757 static MagickBooleanType ValidateLchToRGB()
758 {
759 double
760 b,
761 g,
762 r;
763
764 (void) FormatLocaleFile(stdout," LchToRGB");
765 ConvertLCHabToRGB(88.456154/100.0,75.219797/255.0+0.5,136.620717/360.0,
766 &r,&g,&b);
767 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
768 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
769 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
770 return(MagickFalse);
771 return(MagickTrue);
772 }
773
ValidateRGBToLch()774 static MagickBooleanType ValidateRGBToLch()
775 {
776 double
777 c,
778 h,
779 L;
780
781 (void) FormatLocaleFile(stdout," RGBToLch");
782 ConvertRGBToLCHab(0.545877*QuantumRange,0.966567*QuantumRange,
783 0.463759*QuantumRange,&L,&c,&h);
784 if ((fabs(L-88.456154/100.0) >= ReferenceEpsilon) ||
785 (fabs(c-(75.219797/255.0+0.5)) >= ReferenceEpsilon) ||
786 (fabs(h-(136.620717/255.0+0.5)) >= ReferenceEpsilon))
787 return(MagickFalse);
788 return(MagickTrue);
789 }
790
ValidateRGBToLMS()791 static MagickBooleanType ValidateRGBToLMS()
792 {
793 double
794 L,
795 M,
796 S;
797
798 (void) FormatLocaleFile(stdout," RGBToLMS");
799 ConvertRGBToLMS(0.545877*QuantumRange,0.966567*QuantumRange,
800 0.463759*QuantumRange,&L,&M,&S);
801 if ((fabs(L-0.611749) >= ReferenceEpsilon) ||
802 (fabs(M-0.910088) >= ReferenceEpsilon) ||
803 (fabs(S-0.294880) >= ReferenceEpsilon))
804 return(MagickFalse);
805 return(MagickTrue);
806 }
807
ValidateLMSToRGB()808 static MagickBooleanType ValidateLMSToRGB()
809 {
810 double
811 r,
812 g,
813 b;
814
815 (void) FormatLocaleFile(stdout," LMSToRGB");
816 ConvertLMSToRGB(0.611749,0.910088,0.294880,&r,&g,&b);
817 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
818 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
819 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
820 return(MagickFalse);
821 return(MagickTrue);
822 }
823
ValidateRGBToLuv()824 static MagickBooleanType ValidateRGBToLuv()
825 {
826 double
827 l,
828 u,
829 v;
830
831 (void) FormatLocaleFile(stdout," RGBToLuv");
832 ConvertRGBToLuv(0.545877*QuantumRange,0.966567*QuantumRange,
833 0.463759*QuantumRange,&l,&u,&v);
834 if ((fabs(l-88.456154/262.0) >= ReferenceEpsilon) ||
835 (fabs(u-(-51.330414+134.0)/354.0) >= ReferenceEpsilon) ||
836 (fabs(v-(76.405526+140.0)/262.0) >= ReferenceEpsilon))
837 return(MagickFalse);
838 return(MagickTrue);
839 }
840
ValidateLuvToRGB()841 static MagickBooleanType ValidateLuvToRGB()
842 {
843 double
844 r,
845 g,
846 b;
847
848 (void) FormatLocaleFile(stdout," LuvToRGB");
849 ConvertLuvToRGB(88.456154/100.0,(-51.330414+134.0)/354.0,
850 (76.405526+140.0)/262.0,&r,&g,&b);
851 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
852 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
853 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
854 return(MagickFalse);
855 return(MagickTrue);
856 }
857
ValidateRGBToXYZ()858 static MagickBooleanType ValidateRGBToXYZ()
859 {
860 double
861 x,
862 y,
863 z;
864
865 (void) FormatLocaleFile(stdout," RGBToXYZ");
866 ConvertRGBToXYZ(0.545877*QuantumRange,0.966567*QuantumRange,
867 0.463759*QuantumRange,&x,&y,&z);
868 if ((fabs(x-0.470646) >= ReferenceEpsilon) ||
869 (fabs(y-0.730178) >= ReferenceEpsilon) ||
870 (fabs(z-0.288324) >= ReferenceEpsilon))
871 return(MagickFalse);
872 return(MagickTrue);
873 }
874
ValidateXYZToRGB()875 static MagickBooleanType ValidateXYZToRGB()
876 {
877 double
878 r,
879 g,
880 b;
881
882 (void) FormatLocaleFile(stdout," XYZToRGB");
883 ConvertXYZToRGB(0.470646,0.730178,0.288324,&r,&g,&b);
884 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
885 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
886 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
887 return(MagickFalse);
888 return(MagickTrue);
889 }
890
ValidateYDbDrToRGB()891 static MagickBooleanType ValidateYDbDrToRGB()
892 {
893 double
894 r,
895 g,
896 b;
897
898 (void) FormatLocaleFile(stdout," YDbDrToRGB");
899 ConvertYDbDrToRGB(0.783460,-0.480932+0.5,0.451670+0.5,&r,&g,&b);
900 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
901 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
902 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
903 return(MagickFalse);
904 return(MagickTrue);
905 }
906
ValidateRGBToYDbDr()907 static MagickBooleanType ValidateRGBToYDbDr()
908 {
909 double
910 Db,
911 Dr,
912 Y;
913
914 (void) FormatLocaleFile(stdout," RGBToYDbDr");
915 ConvertRGBToYDbDr(0.545877*QuantumRange,0.966567*QuantumRange,
916 0.463759*QuantumRange,&Y,&Db,&Dr);
917 if ((fabs(Y-0.783460) >= ReferenceEpsilon) ||
918 (fabs(Db-(-0.480932)) >= ReferenceEpsilon) ||
919 (fabs(Dr-0.451670) >= ReferenceEpsilon))
920 return(MagickFalse);
921 return(MagickTrue);
922 }
923
ValidateRGBToYIQ()924 static MagickBooleanType ValidateRGBToYIQ()
925 {
926 double
927 i,
928 q,
929 y;
930
931 (void) FormatLocaleFile(stdout," RGBToYIQ");
932 ConvertRGBToYIQ(0.545877*QuantumRange,0.966567*QuantumRange,
933 0.463759*QuantumRange,&y,&i,&q);
934 if ((fabs(y-0.783460) >= ReferenceEpsilon) ||
935 (fabs(i-(-0.089078)) >= ReferenceEpsilon) ||
936 (fabs(q-(-0.245399)) >= ReferenceEpsilon))
937 return(MagickFalse);
938 return(MagickTrue);
939 }
940
ValidateYIQToRGB()941 static MagickBooleanType ValidateYIQToRGB()
942 {
943 double
944 r,
945 g,
946 b;
947
948 (void) FormatLocaleFile(stdout," YIQToRGB");
949 ConvertYIQToRGB(0.783460,-0.089078+0.5,-0.245399+0.5,&r,&g,&b);
950 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
951 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
952 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
953 return(MagickFalse);
954 return(MagickTrue);
955 }
956
ValidateRGBToYPbPr()957 static MagickBooleanType ValidateRGBToYPbPr()
958 {
959 double
960 Pb,
961 Pr,
962 y;
963
964 (void) FormatLocaleFile(stdout," RGBToYPbPr");
965 ConvertRGBToYPbPr(0.545877*QuantumRange,0.966567*QuantumRange,
966 0.463759*QuantumRange,&y,&Pb,&Pr);
967 if ((fabs(y-0.783460) >= ReferenceEpsilon) ||
968 (fabs(Pb-(-0.180419)) >= ReferenceEpsilon) ||
969 (fabs(Pr-(-0.169461)) >= ReferenceEpsilon))
970 return(MagickFalse);
971 return(MagickTrue);
972 }
973
ValidateYPbPrToRGB()974 static MagickBooleanType ValidateYPbPrToRGB()
975 {
976 double
977 r,
978 g,
979 b;
980
981 (void) FormatLocaleFile(stdout," YPbPrToRGB");
982 ConvertYPbPrToRGB(0.783460,-0.180419+0.5,-0.169461+0.5,&r,&g,&b);
983 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
984 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
985 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
986 return(MagickFalse);
987 return(MagickTrue);
988 }
989
ValidateRGBToYUV()990 static MagickBooleanType ValidateRGBToYUV()
991 {
992 double
993 U,
994 V,
995 Y;
996
997 (void) FormatLocaleFile(stdout," RGBToYUV");
998 ConvertRGBToYUV(0.545877*QuantumRange,0.966567*QuantumRange,
999 0.463759*QuantumRange,&Y,&U,&V);
1000 if ((fabs(Y-0.783460) >= ReferenceEpsilon) ||
1001 (fabs(U-(-0.157383)) >= ReferenceEpsilon) ||
1002 (fabs(V-(-0.208443)) >= ReferenceEpsilon))
1003 return(MagickFalse);
1004 return(MagickTrue);
1005 }
1006
ValidateYUVToRGB()1007 static MagickBooleanType ValidateYUVToRGB()
1008 {
1009 double
1010 r,
1011 g,
1012 b;
1013
1014 (void) FormatLocaleFile(stdout," YUVToRGB");
1015 ConvertYUVToRGB(0.783460,-0.157383+0.5,-0.208443+0.5,&r,&g,&b);
1016 if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) ||
1017 (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) ||
1018 (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon))
1019 return(MagickFalse);
1020 return(MagickTrue);
1021 }
1022
ValidateColorspaces(ImageInfo * image_info,size_t * fails,ExceptionInfo * exception)1023 static size_t ValidateColorspaces(ImageInfo *image_info,size_t *fails,
1024 ExceptionInfo *exception)
1025 {
1026 MagickBooleanType
1027 status;
1028
1029 size_t
1030 fail,
1031 test;
1032
1033 /*
1034 Reference: https://code.google.com/p/chroma.
1035
1036 Illuminant = D65
1037 Observer = 2° (1931)
1038
1039 XYZ 0.470645, 0.730177, 0.288323
1040 sRGB 0.545877, 0.966567, 0.463759
1041 CAT02 LMS 0.611749, 0.910088, 0.294880
1042 Y'DbDr 0.783460, -0.480932, 0.451670
1043 Y'IQ 0.783460, -0.089078, -0.245399
1044 Y'PbPr 0.783460, -0.180419, -0.169461
1045 Y'UV 0.783460, -0.157383, -0.208443
1046 JPEG-Y'CbCr 0.783460, 0.319581, 0.330539
1047 L*u*v* 88.456154, -51.330414, 76.405526
1048 L*a*b* 88.456154, -54.671483, 51.662818
1049 L*C*H* 88.456154, 75.219797, 136.620717
1050 HSV 110.200859, 0.520200, 0.966567
1051 HSL 110.200859, 0.882623, 0.715163
1052 HSI 111.244375, 0.295985, 0.658734
1053 Y'CbCr 187.577791, 87.586330, 90.040886
1054 */
1055 (void) FormatLocaleFile(stdout,"validate colorspaces:\n");
1056 fail=0;
1057 for (test=0; test < 26; test++)
1058 {
1059 CatchException(exception);
1060 (void) FormatLocaleFile(stdout," test %.20g: ",(double) test);
1061 switch (test)
1062 {
1063 case 0: status=ValidateHSIToRGB(); break;
1064 case 1: status=ValidateRGBToHSI(); break;
1065 case 2: status=ValidateHSLToRGB(); break;
1066 case 3: status=ValidateRGBToHSL(); break;
1067 case 4: status=ValidateHSVToRGB(); break;
1068 case 5: status=ValidateRGBToHSV(); break;
1069 case 6: status=ValidateJPEGYCbCrToRGB(); break;
1070 case 7: status=ValidateRGBToJPEGYCbCr(); break;
1071 case 8: status=ValidateLabToRGB(); break;
1072 case 9: status=ValidateRGBToLab(); break;
1073 case 10: status=ValidateLchToRGB(); break;
1074 case 11: status=ValidateRGBToLch(); break;
1075 case 12: status=ValidateLMSToRGB(); break;
1076 case 13: status=ValidateRGBToLMS(); break;
1077 case 14: status=ValidateLuvToRGB(); break;
1078 case 15: status=ValidateRGBToLuv(); break;
1079 case 16: status=ValidateXYZToRGB(); break;
1080 case 17: status=ValidateRGBToXYZ(); break;
1081 case 18: status=ValidateYDbDrToRGB(); break;
1082 case 19: status=ValidateRGBToYDbDr(); break;
1083 case 20: status=ValidateYIQToRGB(); break;
1084 case 21: status=ValidateRGBToYIQ(); break;
1085 case 22: status=ValidateYPbPrToRGB(); break;
1086 case 23: status=ValidateRGBToYPbPr(); break;
1087 case 24: status=ValidateYUVToRGB(); break;
1088 case 25: status=ValidateRGBToYUV(); break;
1089 default: status=MagickFalse;
1090 }
1091 if (status == MagickFalse)
1092 {
1093 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1094 GetMagickModule());
1095 fail++;
1096 continue;
1097 }
1098 (void) FormatLocaleFile(stdout,"... pass.\n");
1099 }
1100 (void) FormatLocaleFile(stdout,
1101 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1102 (double) (test-fail),(double) fail);
1103 *fails+=fail;
1104 return(test);
1105 }
1106
1107 /*
1108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109 % %
1110 % %
1111 % %
1112 % V a l i d a t e C o m p a r e C o m m a n d %
1113 % %
1114 % %
1115 % %
1116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117 %
1118 % ValidateCompareCommand() validates the ImageMagick compare command line
1119 % program and returns the number of validation tests that passed and failed.
1120 %
1121 % The format of the ValidateCompareCommand method is:
1122 %
1123 % size_t ValidateCompareCommand(ImageInfo *image_info,
1124 % const char *reference_filename,const char *output_filename,
1125 % size_t *fails,ExceptionInfo *exception)
1126 %
1127 % A description of each parameter follows:
1128 %
1129 % o image_info: the image info.
1130 %
1131 % o reference_filename: the reference image filename.
1132 %
1133 % o output_filename: the output image filename.
1134 %
1135 % o fail: return the number of validation tests that pass.
1136 %
1137 % o exception: return any errors or warnings in this structure.
1138 %
1139 */
ValidateCompareCommand(ImageInfo * image_info,const char * reference_filename,const char * output_filename,size_t * fails,ExceptionInfo * exception)1140 static size_t ValidateCompareCommand(ImageInfo *image_info,
1141 const char *reference_filename,const char *output_filename,size_t *fails,
1142 ExceptionInfo *exception)
1143 {
1144 char
1145 **arguments,
1146 command[MagickPathExtent];
1147
1148 int
1149 number_arguments;
1150
1151 MagickBooleanType
1152 status;
1153
1154 ssize_t
1155 i,
1156 j;
1157
1158 size_t
1159 fail,
1160 test;
1161
1162 fail=0;
1163 test=0;
1164 (void) FormatLocaleFile(stdout,"validate compare command line program:\n");
1165 for (i=0; compare_options[i] != (char *) NULL; i++)
1166 {
1167 CatchException(exception);
1168 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
1169 compare_options[i]);
1170 (void) FormatLocaleString(command,MagickPathExtent,"%s %s %s %s",
1171 compare_options[i],reference_filename,reference_filename,output_filename);
1172 arguments=StringToArgv(command,&number_arguments);
1173 if (arguments == (char **) NULL)
1174 {
1175 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1176 GetMagickModule());
1177 (void) LogMagickEvent(ExceptionEvent,GetMagickModule(),"%s",
1178 exception->reason);
1179 fail++;
1180 continue;
1181 }
1182 status=CompareImagesCommand(image_info,number_arguments,arguments,
1183 (char **) NULL,exception);
1184 for (j=0; j < (ssize_t) number_arguments; j++)
1185 arguments[j]=DestroyString(arguments[j]);
1186 arguments=(char **) RelinquishMagickMemory(arguments);
1187 if (status == MagickFalse)
1188 {
1189 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1190 GetMagickModule());
1191 (void) LogMagickEvent(ExceptionEvent,GetMagickModule(),"%s",
1192 exception->reason);
1193 fail++;
1194 continue;
1195 }
1196 (void) FormatLocaleFile(stdout,"... pass.\n");
1197 }
1198 (void) FormatLocaleFile(stdout,
1199 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1200 (double) (test-fail),(double) fail);
1201 *fails+=fail;
1202 return(test);
1203 }
1204
1205 /*
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1207 % %
1208 % %
1209 % %
1210 % V a l i d a t e C o m p o s i t e C o m m a n d %
1211 % %
1212 % %
1213 % %
1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1215 %
1216 % ValidateCompositeCommand() validates the ImageMagick composite command line
1217 % program and returns the number of validation tests that passed and failed.
1218 %
1219 % The format of the ValidateCompositeCommand method is:
1220 %
1221 % size_t ValidateCompositeCommand(ImageInfo *image_info,
1222 % const char *reference_filename,const char *output_filename,
1223 % size_t *fails,ExceptionInfo *exception)
1224 %
1225 % A description of each parameter follows:
1226 %
1227 % o image_info: the image info.
1228 %
1229 % o reference_filename: the reference image filename.
1230 %
1231 % o output_filename: the output image filename.
1232 %
1233 % o fail: return the number of validation tests that pass.
1234 %
1235 % o exception: return any errors or warnings in this structure.
1236 %
1237 */
ValidateCompositeCommand(ImageInfo * image_info,const char * reference_filename,const char * output_filename,size_t * fails,ExceptionInfo * exception)1238 static size_t ValidateCompositeCommand(ImageInfo *image_info,
1239 const char *reference_filename,const char *output_filename,size_t *fails,
1240 ExceptionInfo *exception)
1241 {
1242 char
1243 **arguments,
1244 command[MagickPathExtent];
1245
1246 int
1247 number_arguments;
1248
1249 MagickBooleanType
1250 status;
1251
1252 ssize_t
1253 i,
1254 j;
1255
1256 size_t
1257 fail,
1258 test;
1259
1260 fail=0;
1261 test=0;
1262 (void) FormatLocaleFile(stdout,"validate composite command line program:\n");
1263 for (i=0; composite_options[i] != (char *) NULL; i++)
1264 {
1265 CatchException(exception);
1266 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
1267 composite_options[i]);
1268 (void) FormatLocaleString(command,MagickPathExtent,"%s %s %s %s",
1269 reference_filename,composite_options[i],reference_filename,
1270 output_filename);
1271 arguments=StringToArgv(command,&number_arguments);
1272 if (arguments == (char **) NULL)
1273 {
1274 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1275 GetMagickModule());
1276 fail++;
1277 continue;
1278 }
1279 status=CompositeImageCommand(image_info,number_arguments,arguments,
1280 (char **) NULL,exception);
1281 for (j=0; j < (ssize_t) number_arguments; j++)
1282 arguments[j]=DestroyString(arguments[j]);
1283 arguments=(char **) RelinquishMagickMemory(arguments);
1284 if (status == MagickFalse)
1285 {
1286 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1287 GetMagickModule());
1288 fail++;
1289 continue;
1290 }
1291 (void) FormatLocaleFile(stdout,"... pass.\n");
1292 }
1293 (void) FormatLocaleFile(stdout,
1294 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1295 (double) (test-fail),(double) fail);
1296 *fails+=fail;
1297 return(test);
1298 }
1299
1300 /*
1301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1302 % %
1303 % %
1304 % %
1305 % V a l i d a t e C o n v e r t C o m m a n d %
1306 % %
1307 % %
1308 % %
1309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1310 %
1311 % ValidateConvertCommand() validates the ImageMagick convert command line
1312 % program and returns the number of validation tests that passed and failed.
1313 %
1314 % The format of the ValidateConvertCommand method is:
1315 %
1316 % size_t ValidateConvertCommand(ImageInfo *image_info,
1317 % const char *reference_filename,const char *output_filename,
1318 % size_t *fails,ExceptionInfo *exception)
1319 %
1320 % A description of each parameter follows:
1321 %
1322 % o image_info: the image info.
1323 %
1324 % o reference_filename: the reference image filename.
1325 %
1326 % o output_filename: the output image filename.
1327 %
1328 % o fail: return the number of validation tests that pass.
1329 %
1330 % o exception: return any errors or warnings in this structure.
1331 %
1332 */
ValidateConvertCommand(ImageInfo * image_info,const char * reference_filename,const char * output_filename,size_t * fails,ExceptionInfo * exception)1333 static size_t ValidateConvertCommand(ImageInfo *image_info,
1334 const char *reference_filename,const char *output_filename,size_t *fails,
1335 ExceptionInfo *exception)
1336 {
1337 char
1338 **arguments,
1339 command[MagickPathExtent];
1340
1341 int
1342 number_arguments;
1343
1344 MagickBooleanType
1345 status;
1346
1347 ssize_t
1348 i,
1349 j;
1350
1351 size_t
1352 fail,
1353 test;
1354
1355 fail=0;
1356 test=0;
1357 (void) FormatLocaleFile(stdout,"validate convert command line program:\n");
1358 for (i=0; convert_options[i] != (char *) NULL; i++)
1359 {
1360 CatchException(exception);
1361 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) test++,
1362 convert_options[i]);
1363 (void) FormatLocaleString(command,MagickPathExtent,"%s %s %s %s",
1364 reference_filename,convert_options[i],reference_filename,output_filename);
1365 arguments=StringToArgv(command,&number_arguments);
1366 if (arguments == (char **) NULL)
1367 {
1368 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1369 GetMagickModule());
1370 fail++;
1371 continue;
1372 }
1373 status=ConvertImageCommand(image_info,number_arguments,arguments,
1374 (char **) NULL,exception);
1375 for (j=0; j < (ssize_t) number_arguments; j++)
1376 arguments[j]=DestroyString(arguments[j]);
1377 arguments=(char **) RelinquishMagickMemory(arguments);
1378 if (status == MagickFalse)
1379 {
1380 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1381 GetMagickModule());
1382 fail++;
1383 continue;
1384 }
1385 (void) FormatLocaleFile(stdout,"... pass.\n");
1386 }
1387 (void) FormatLocaleFile(stdout,
1388 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1389 (double) (test-fail),(double) fail);
1390 *fails+=fail;
1391 return(test);
1392 }
1393
1394 /*
1395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1396 % %
1397 % %
1398 % %
1399 % V a l i d a t e I d e n t i f y C o m m a n d %
1400 % %
1401 % %
1402 % %
1403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1404 %
1405 % ValidateIdentifyCommand() validates the ImageMagick identify command line
1406 % program and returns the number of validation tests that passed and failed.
1407 %
1408 % The format of the ValidateIdentifyCommand method is:
1409 %
1410 % size_t ValidateIdentifyCommand(ImageInfo *image_info,
1411 % const char *reference_filename,const char *output_filename,
1412 % size_t *fails,ExceptionInfo *exception)
1413 %
1414 % A description of each parameter follows:
1415 %
1416 % o image_info: the image info.
1417 %
1418 % o reference_filename: the reference image filename.
1419 %
1420 % o output_filename: the output image filename.
1421 %
1422 % o fail: return the number of validation tests that pass.
1423 %
1424 % o exception: return any errors or warnings in this structure.
1425 %
1426 */
ValidateIdentifyCommand(ImageInfo * image_info,const char * reference_filename,const char * output_filename,size_t * fails,ExceptionInfo * exception)1427 static size_t ValidateIdentifyCommand(ImageInfo *image_info,
1428 const char *reference_filename,const char *output_filename,size_t *fails,
1429 ExceptionInfo *exception)
1430 {
1431 char
1432 **arguments,
1433 command[MagickPathExtent];
1434
1435 int
1436 number_arguments;
1437
1438 MagickBooleanType
1439 status;
1440
1441 ssize_t
1442 i,
1443 j;
1444
1445 size_t
1446 fail,
1447 test;
1448
1449 (void) output_filename;
1450 fail=0;
1451 test=0;
1452 (void) FormatLocaleFile(stdout,"validate identify command line program:\n");
1453 for (i=0; identify_options[i] != (char *) NULL; i++)
1454 {
1455 CatchException(exception);
1456 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) test++,
1457 identify_options[i]);
1458 (void) FormatLocaleString(command,MagickPathExtent,"%s %s",
1459 identify_options[i],reference_filename);
1460 arguments=StringToArgv(command,&number_arguments);
1461 if (arguments == (char **) NULL)
1462 {
1463 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1464 GetMagickModule());
1465 fail++;
1466 continue;
1467 }
1468 status=IdentifyImageCommand(image_info,number_arguments,arguments,
1469 (char **) NULL,exception);
1470 for (j=0; j < (ssize_t) number_arguments; j++)
1471 arguments[j]=DestroyString(arguments[j]);
1472 arguments=(char **) RelinquishMagickMemory(arguments);
1473 if (status == MagickFalse)
1474 {
1475 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1476 GetMagickModule());
1477 fail++;
1478 continue;
1479 }
1480 (void) FormatLocaleFile(stdout,"... pass.\n");
1481 }
1482 (void) FormatLocaleFile(stdout,
1483 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1484 (double) (test-fail),(double) fail);
1485 *fails+=fail;
1486 return(test);
1487 }
1488
1489 /*
1490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1491 % %
1492 % %
1493 % %
1494 % 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 %
1495 % %
1496 % %
1497 % %
1498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1499 %
1500 % ValidateImageFormatsInMemory() validates the ImageMagick image formats in
1501 % memory and returns the number of validation tests that passed and failed.
1502 %
1503 % The format of the ValidateImageFormatsInMemory method is:
1504 %
1505 % size_t ValidateImageFormatsInMemory(ImageInfo *image_info,
1506 % const char *reference_filename,const char *output_filename,
1507 % size_t *fails,ExceptionInfo *exception)
1508 %
1509 % A description of each parameter follows:
1510 %
1511 % o image_info: the image info.
1512 %
1513 % o reference_filename: the reference image filename.
1514 %
1515 % o output_filename: the output image filename.
1516 %
1517 % o fail: return the number of validation tests that pass.
1518 %
1519 % o exception: return any errors or warnings in this structure.
1520 %
1521 */
1522
1523 /*
1524 Enable this to count remaining $TMPDIR/magick-* files. Note that the count
1525 includes any files left over from other runs.
1526 */
1527 #undef MagickCountTempFiles
1528
ValidateImageFormatsInMemory(ImageInfo * image_info,const char * reference_filename,const char * output_filename,size_t * fails,ExceptionInfo * exception)1529 static size_t ValidateImageFormatsInMemory(ImageInfo *image_info,
1530 const char *reference_filename,const char *output_filename,size_t *fails,
1531 ExceptionInfo *exception)
1532 {
1533 char
1534 #ifdef MagickCountTempFiles
1535 path[MagickPathExtent],
1536 SystemCommand[MagickPathExtent],
1537 #endif
1538 size[MagickPathExtent];
1539
1540 const MagickInfo
1541 *magick_info;
1542
1543 double
1544 distortion,
1545 fuzz;
1546
1547 Image
1548 *difference_image,
1549 *ping_image,
1550 *reconstruct_image,
1551 *reference_image;
1552
1553 MagickBooleanType
1554 status;
1555
1556 ssize_t
1557 i,
1558 j;
1559
1560 size_t
1561 fail,
1562 length,
1563 test;
1564
1565 unsigned char
1566 *blob;
1567
1568 fail=0;
1569 test=0;
1570 (void) FormatLocaleFile(stdout,"validate image formats in memory:\n");
1571
1572 #ifdef MagickCountTempFiles
1573 (void)GetPathTemplate(path);
1574 /* Remove file template except for the leading "/path/to/magick-" */
1575 path[strlen(path)-17]='\0';
1576 (void) FormatLocaleFile(stdout," tmp path is '%s*'\n",path);
1577 #endif
1578
1579 for (i=0; reference_formats[i].magick != (char *) NULL; i++)
1580 {
1581 magick_info=GetMagickInfo(reference_formats[i].magick,exception);
1582 if ((magick_info == (const MagickInfo *) NULL) ||
1583 (magick_info->decoder == (DecodeImageHandler *) NULL) ||
1584 (magick_info->encoder == (EncodeImageHandler *) NULL))
1585 continue;
1586 for (j=0; reference_types[j].type != UndefinedType; j++)
1587 {
1588 /*
1589 Generate reference image.
1590 */
1591 CatchException(exception);
1592 (void) FormatLocaleFile(stdout," test %.20g: %s/%s/%s/%.20g-bits",
1593 (double) (test++),reference_formats[i].magick,CommandOptionToMnemonic(
1594 MagickCompressOptions,reference_formats[i].compression),
1595 CommandOptionToMnemonic(MagickTypeOptions,reference_types[j].type),
1596 (double) reference_types[j].depth);
1597 (void) CopyMagickString(image_info->filename,reference_filename,
1598 MagickPathExtent);
1599 reference_image=ReadImage(image_info,exception);
1600 if ((reference_image == (Image *) NULL) ||
1601 (exception->severity >= ErrorException))
1602 {
1603 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1604 GetMagickModule());
1605 if (exception->reason != (char *) NULL)
1606 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1607 CatchException(exception);
1608 fail++;
1609 continue;
1610 }
1611 /*
1612 Write reference image.
1613 */
1614 (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",
1615 (double) reference_image->columns,(double) reference_image->rows);
1616 (void) CloneString(&image_info->size,size);
1617 image_info->depth=reference_types[j].depth;
1618 (void) FormatLocaleString(reference_image->filename,MagickPathExtent,
1619 "%s:%s",reference_formats[i].magick,output_filename);
1620 status=SetImageType(reference_image,reference_types[j].type,exception);
1621 if (status == MagickFalse || (exception->severity >= ErrorException))
1622 {
1623 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1624 GetMagickModule());
1625 if (exception->reason != (char *) NULL)
1626 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1627 CatchException(exception);
1628 fail++;
1629 reference_image=DestroyImage(reference_image);
1630 continue;
1631 }
1632 status=SetImageDepth(reference_image,reference_types[j].depth,exception);
1633 if (status == MagickFalse || (exception->severity >= ErrorException))
1634 {
1635 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1636 GetMagickModule());
1637 CatchException(exception);
1638 fail++;
1639 reference_image=DestroyImage(reference_image);
1640 continue;
1641 }
1642 reference_image->compression=reference_formats[i].compression;
1643 status=WriteImage(image_info,reference_image,exception);
1644 reference_image=DestroyImage(reference_image);
1645 if (status == MagickFalse || (exception->severity >= ErrorException))
1646 {
1647 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1648 GetMagickModule());
1649 if (exception->reason != (char *) NULL)
1650 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1651 CatchException(exception);
1652 fail++;
1653 continue;
1654 }
1655 /*
1656 Ping reference image.
1657 */
1658 (void) FormatLocaleString(image_info->filename,MagickPathExtent,"%s:%s",
1659 reference_formats[i].magick,output_filename);
1660 ping_image=PingImage(image_info,exception);
1661 if (ping_image == (Image *) NULL ||
1662 (exception->severity >= ErrorException))
1663 {
1664 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1665 GetMagickModule());
1666 if (exception->reason != (char *) NULL)
1667 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1668 CatchException(exception);
1669 fail++;
1670 continue;
1671 }
1672 ping_image=DestroyImage(ping_image);
1673 /*
1674 Read reference image.
1675 */
1676 reference_image=ReadImage(image_info,exception);
1677 if ((reference_image == (Image *) NULL) ||
1678 (exception->severity >= ErrorException))
1679 {
1680 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1681 GetMagickModule());
1682 if (exception->reason != (char *) NULL)
1683 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1684 CatchException(exception);
1685 fail++;
1686 continue;
1687 }
1688 /*
1689 Write reference image.
1690 */
1691 (void) FormatLocaleString(reference_image->filename,MagickPathExtent,
1692 "%s:%s",reference_formats[i].magick,output_filename);
1693 (void) CopyMagickString(image_info->magick,reference_formats[i].magick,
1694 MagickPathExtent);
1695 reference_image->depth=reference_types[j].depth;
1696 reference_image->compression=reference_formats[i].compression;
1697 length=8192;
1698 blob=(unsigned char *) ImageToBlob(image_info,reference_image,&length,
1699 exception);
1700 if ((blob == (unsigned char *) NULL) ||
1701 (exception->severity >= ErrorException))
1702 {
1703 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1704 GetMagickModule());
1705 if (exception->reason != (char *) NULL)
1706 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1707 CatchException(exception);
1708 fail++;
1709 reference_image=DestroyImage(reference_image);
1710 continue;
1711 }
1712 /*
1713 Ping reference blob.
1714 */
1715 ping_image=PingBlob(image_info,blob,length,exception);
1716 if (ping_image == (Image *) NULL ||
1717 (exception->severity >= ErrorException))
1718 {
1719 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1720 GetMagickModule());
1721 if (exception->reason != (char *) NULL)
1722 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1723 CatchException(exception);
1724 fail++;
1725 blob=(unsigned char *) RelinquishMagickMemory(blob);
1726 continue;
1727 }
1728 ping_image=DestroyImage(ping_image);
1729 /*
1730 Read reconstruct image.
1731 */
1732 (void) FormatLocaleString(image_info->filename,MagickPathExtent,"%s:%s",
1733 reference_formats[i].magick,output_filename);
1734 reconstruct_image=BlobToImage(image_info,blob,length,exception);
1735 blob=(unsigned char *) RelinquishMagickMemory(blob);
1736 if (reconstruct_image == (Image *) NULL ||
1737 (exception->severity >= ErrorException))
1738 {
1739 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1740 GetMagickModule());
1741 if (exception->reason != (char *) NULL)
1742 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1743 CatchException(exception);
1744 fail++;
1745 reference_image=DestroyImage(reference_image);
1746 continue;
1747 }
1748 /*
1749 Compare reference to reconstruct image.
1750 */
1751 fuzz=0.003; /* grayscale */
1752 if (reference_formats[i].fuzz != 0.0)
1753 fuzz=reference_formats[i].fuzz;
1754 difference_image=CompareImages(reference_image,reconstruct_image,
1755 RootMeanSquaredErrorMetric,&distortion,exception);
1756 reconstruct_image=DestroyImage(reconstruct_image);
1757 reference_image=DestroyImage(reference_image);
1758 if (difference_image == (Image *) NULL ||
1759 (exception->severity >= ErrorException))
1760 {
1761 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1762 GetMagickModule());
1763 if (exception->reason != (char *) NULL)
1764 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1765 CatchException(exception);
1766 fail++;
1767 continue;
1768 }
1769 difference_image=DestroyImage(difference_image);
1770 if ((QuantumScale*distortion) > fuzz)
1771 {
1772 (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
1773 QuantumScale*distortion);
1774 fail++;
1775 continue;
1776 }
1777 #ifdef MagickCountTempFiles
1778 (void) FormatLocaleFile(stdout,"... pass, ");
1779 (void) fflush(stdout);
1780 SystemCommand[0]='\0';
1781 (void) strncat(SystemCommand,"echo `ls ",9);
1782 (void) strncat(SystemCommand,path,MagickPathExtent-31);
1783 (void) strncat(SystemCommand,"* | wc -w` tmp files.",20);
1784 (void) system(SystemCommand);
1785 (void) fflush(stdout);
1786 #else
1787 (void) FormatLocaleFile(stdout,"... pass\n");
1788 #endif
1789 }
1790 }
1791 (void) FormatLocaleFile(stdout,
1792 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
1793 (double) (test-fail),(double) fail);
1794 *fails+=fail;
1795 return(test);
1796 }
1797
1798 /*
1799 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1800 % %
1801 % %
1802 % %
1803 % 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 %
1804 % %
1805 % %
1806 % %
1807 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1808 %
1809 % ValidateImageFormatsOnDisk() validates the ImageMagick image formats on disk
1810 % and returns the number of validation tests that passed and failed.
1811 %
1812 % The format of the ValidateImageFormatsOnDisk method is:
1813 %
1814 % size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
1815 % const char *reference_filename,const char *output_filename,
1816 % size_t *fails,ExceptionInfo *exception)
1817 %
1818 % A description of each parameter follows:
1819 %
1820 % o image_info: the image info.
1821 %
1822 % o reference_filename: the reference image filename.
1823 %
1824 % o output_filename: the output image filename.
1825 %
1826 % o fail: return the number of validation tests that pass.
1827 %
1828 % o exception: return any errors or warnings in this structure.
1829 %
1830 */
ValidateImageFormatsOnDisk(ImageInfo * image_info,const char * reference_filename,const char * output_filename,size_t * fails,ExceptionInfo * exception)1831 static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info,
1832 const char *reference_filename,const char *output_filename,size_t *fails,
1833 ExceptionInfo *exception)
1834 {
1835 char
1836 size[MagickPathExtent];
1837
1838 const MagickInfo
1839 *magick_info;
1840
1841 double
1842 distortion,
1843 fuzz;
1844
1845 Image
1846 *difference_image,
1847 *reference_image,
1848 *reconstruct_image;
1849
1850 MagickBooleanType
1851 status;
1852
1853 ssize_t
1854 i,
1855 j;
1856
1857 size_t
1858 fail,
1859 test;
1860
1861 fail=0;
1862 test=0;
1863 (void) FormatLocaleFile(stdout,"validate image formats on disk:\n");
1864 for (i=0; reference_formats[i].magick != (char *) NULL; i++)
1865 {
1866 magick_info=GetMagickInfo(reference_formats[i].magick,exception);
1867 if ((magick_info == (const MagickInfo *) NULL) ||
1868 (magick_info->decoder == (DecodeImageHandler *) NULL) ||
1869 (magick_info->encoder == (EncodeImageHandler *) NULL))
1870 continue;
1871 for (j=0; reference_types[j].type != UndefinedType; j++)
1872 {
1873 /*
1874 Generate reference image.
1875 */
1876 CatchException(exception);
1877 (void) FormatLocaleFile(stdout," test %.20g: %s/%s/%s/%.20g-bits",
1878 (double) (test++),reference_formats[i].magick,CommandOptionToMnemonic(
1879 MagickCompressOptions,reference_formats[i].compression),
1880 CommandOptionToMnemonic(MagickTypeOptions,reference_types[j].type),
1881 (double) reference_types[j].depth);
1882 (void) CopyMagickString(image_info->filename,reference_filename,
1883 MagickPathExtent);
1884 reference_image=ReadImage(image_info,exception);
1885 if ((reference_image == (Image *) NULL) ||
1886 (exception->severity >= ErrorException))
1887 {
1888 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1889 GetMagickModule());
1890 if (exception->reason != (char *) NULL)
1891 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1892 CatchException(exception);
1893 fail++;
1894 continue;
1895 }
1896 /*
1897 Write reference image.
1898 */
1899 (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",
1900 (double) reference_image->columns,(double) reference_image->rows);
1901 (void) CloneString(&image_info->size,size);
1902 image_info->depth=reference_types[j].depth;
1903 (void) FormatLocaleString(reference_image->filename,MagickPathExtent,
1904 "%s:%s",reference_formats[i].magick,output_filename);
1905 status=SetImageType(reference_image,reference_types[j].type,exception);
1906 if (status == MagickFalse || (exception->severity >= ErrorException))
1907 {
1908 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1909 GetMagickModule());
1910 if (exception->reason != (char *) NULL)
1911 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1912 CatchException(exception);
1913 fail++;
1914 reference_image=DestroyImage(reference_image);
1915 continue;
1916 }
1917 status=SetImageDepth(reference_image,reference_types[j].depth,exception);
1918 if (status == MagickFalse || (exception->severity >= ErrorException))
1919 {
1920 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1921 GetMagickModule());
1922 CatchException(exception);
1923 fail++;
1924 reference_image=DestroyImage(reference_image);
1925 continue;
1926 }
1927 reference_image->compression=reference_formats[i].compression;
1928 status=WriteImage(image_info,reference_image,exception);
1929 reference_image=DestroyImage(reference_image);
1930 if (status == MagickFalse || (exception->severity >= ErrorException))
1931 {
1932 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1933 GetMagickModule());
1934 if (exception->reason != (char *) NULL)
1935 (void) FormatLocaleFile(stdout," reason:%s\n",exception->reason);
1936 CatchException(exception);
1937 fail++;
1938 continue;
1939 }
1940 /*
1941 Read reference image.
1942 */
1943 (void) FormatLocaleString(image_info->filename,MagickPathExtent,"%s:%s",
1944 reference_formats[i].magick,output_filename);
1945 reference_image=ReadImage(image_info,exception);
1946 if ((reference_image == (Image *) NULL) ||
1947 (exception->severity >= ErrorException))
1948 {
1949 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1950 GetMagickModule());
1951 CatchException(exception);
1952 fail++;
1953 continue;
1954 }
1955 /*
1956 Write reference image.
1957 */
1958 (void) FormatLocaleString(reference_image->filename,MagickPathExtent,
1959 "%s:%s",reference_formats[i].magick,output_filename);
1960 reference_image->depth=reference_types[j].depth;
1961 reference_image->compression=reference_formats[i].compression;
1962 status=WriteImage(image_info,reference_image,exception);
1963 if (status == MagickFalse ||exception->severity >= ErrorException)
1964 {
1965 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1966 GetMagickModule());
1967 CatchException(exception);
1968 fail++;
1969 reference_image=DestroyImage(reference_image);
1970 continue;
1971 }
1972 /*
1973 Read reconstruct image.
1974 */
1975 (void) FormatLocaleString(image_info->filename,MagickPathExtent,"%s:%s",
1976 reference_formats[i].magick,output_filename);
1977 reconstruct_image=ReadImage(image_info,exception);
1978 if (reconstruct_image == (Image *) NULL ||
1979 (exception->severity >= ErrorException))
1980 {
1981 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
1982 GetMagickModule());
1983 CatchException(exception);
1984 fail++;
1985 reference_image=DestroyImage(reference_image);
1986 continue;
1987 }
1988 /*
1989 Compare reference to reconstruct image.
1990 */
1991 fuzz=0.003; /* grayscale */
1992 if (reference_formats[i].fuzz != 0.0)
1993 fuzz=reference_formats[i].fuzz;
1994 difference_image=CompareImages(reference_image,reconstruct_image,
1995 RootMeanSquaredErrorMetric,&distortion,exception);
1996 reconstruct_image=DestroyImage(reconstruct_image);
1997 reference_image=DestroyImage(reference_image);
1998 if (difference_image == (Image *) NULL ||
1999 (exception->severity >= ErrorException))
2000 {
2001 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2002 GetMagickModule());
2003 CatchException(exception);
2004 fail++;
2005 continue;
2006 }
2007 difference_image=DestroyImage(difference_image);
2008 if ((QuantumScale*distortion) > fuzz)
2009 {
2010 (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
2011 QuantumScale*distortion);
2012 fail++;
2013 continue;
2014 }
2015 (void) FormatLocaleFile(stdout,"... pass.\n");
2016 }
2017 }
2018 (void) FormatLocaleFile(stdout,
2019 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2020 (double) (test-fail),(double) fail);
2021 *fails+=fail;
2022 return(test);
2023 }
2024
2025 /*
2026 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2027 % %
2028 % %
2029 % %
2030 % 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 %
2031 % %
2032 % %
2033 % %
2034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2035 %
2036 % ValidateImportExportPixels() validates the pixel import and export methods.
2037 % It returns the number of validation tests that passed and failed.
2038 %
2039 % The format of the ValidateImportExportPixels method is:
2040 %
2041 % size_t ValidateImportExportPixels(ImageInfo *image_info,
2042 % const char *reference_filename,const char *output_filename,
2043 % size_t *fails,ExceptionInfo *exception)
2044 %
2045 % A description of each parameter follows:
2046 %
2047 % o image_info: the image info.
2048 %
2049 % o reference_filename: the reference image filename.
2050 %
2051 % o output_filename: the output image filename.
2052 %
2053 % o fail: return the number of validation tests that pass.
2054 %
2055 % o exception: return any errors or warnings in this structure.
2056 %
2057 */
ValidateImportExportPixels(ImageInfo * image_info,const char * reference_filename,const char * output_filename,size_t * fails,ExceptionInfo * exception)2058 static size_t ValidateImportExportPixels(ImageInfo *image_info,
2059 const char *reference_filename,const char *output_filename,size_t *fails,
2060 ExceptionInfo *exception)
2061 {
2062 double
2063 distortion;
2064
2065 Image
2066 *difference_image,
2067 *reference_image,
2068 *reconstruct_image;
2069
2070 MagickBooleanType
2071 status;
2072
2073 ssize_t
2074 i,
2075 j;
2076
2077 size_t
2078 length;
2079
2080 unsigned char
2081 *pixels;
2082
2083 size_t
2084 fail,
2085 test;
2086
2087 (void) output_filename;
2088 fail=0;
2089 test=0;
2090 (void) FormatLocaleFile(stdout,
2091 "validate the import and export of image pixels:\n");
2092 for (i=0; reference_map[i] != (char *) NULL; i++)
2093 {
2094 for (j=0; reference_storage[j].type != UndefinedPixel; j++)
2095 {
2096 /*
2097 Generate reference image.
2098 */
2099 CatchException(exception);
2100 (void) FormatLocaleFile(stdout," test %.20g: %s/%s",(double) (test++),
2101 reference_map[i],CommandOptionToMnemonic(MagickStorageOptions,
2102 reference_storage[j].type));
2103 (void) CopyMagickString(image_info->filename,reference_filename,
2104 MagickPathExtent);
2105 reference_image=ReadImage(image_info,exception);
2106 if ((reference_image == (Image *) NULL) ||
2107 (exception->severity >= ErrorException))
2108 {
2109 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2110 GetMagickModule());
2111 CatchException(exception);
2112 fail++;
2113 continue;
2114 }
2115 if (LocaleNCompare(reference_map[i],"cmy",3) == 0)
2116 (void) SetImageColorspace(reference_image,CMYKColorspace,exception);
2117 length=strlen(reference_map[i])*reference_image->columns*
2118 reference_image->rows*reference_storage[j].quantum;
2119 pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
2120 if ((pixels == (unsigned char *) NULL) ||
2121 (exception->severity >= ErrorException))
2122 {
2123 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2124 GetMagickModule());
2125 CatchException(exception);
2126 fail++;
2127 reference_image=DestroyImage(reference_image);
2128 continue;
2129 }
2130 (void) memset(pixels,0,length*sizeof(*pixels));
2131 status=ExportImagePixels(reference_image,0,0,reference_image->columns,
2132 reference_image->rows,reference_map[i],reference_storage[j].type,pixels,
2133 exception);
2134 if (status == MagickFalse || (exception->severity >= ErrorException))
2135 {
2136 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2137 GetMagickModule());
2138 CatchException(exception);
2139 fail++;
2140 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2141 reference_image=DestroyImage(reference_image);
2142 continue;
2143 }
2144 (void) SetImageBackgroundColor(reference_image,exception);
2145 status=ImportImagePixels(reference_image,0,0,reference_image->columns,
2146 reference_image->rows,reference_map[i],reference_storage[j].type,
2147 pixels,exception);
2148 if (status == MagickFalse || (exception->severity >= ErrorException))
2149 {
2150 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2151 GetMagickModule());
2152 CatchException(exception);
2153 fail++;
2154 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2155 reference_image=DestroyImage(reference_image);
2156 continue;
2157 }
2158 /*
2159 Read reconstruct image.
2160 */
2161 reconstruct_image=AcquireImage(image_info,exception);
2162 (void) SetImageExtent(reconstruct_image,reference_image->columns,
2163 reference_image->rows,exception);
2164 (void) SetImageColorspace(reconstruct_image,reference_image->colorspace,
2165 exception);
2166 (void) SetImageBackgroundColor(reconstruct_image,exception);
2167 status=ImportImagePixels(reconstruct_image,0,0,reconstruct_image->columns,
2168 reconstruct_image->rows,reference_map[i],reference_storage[j].type,
2169 pixels,exception);
2170 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2171 if (status == MagickFalse || (exception->severity >= ErrorException))
2172 {
2173 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2174 GetMagickModule());
2175 CatchException(exception);
2176 fail++;
2177 reference_image=DestroyImage(reference_image);
2178 continue;
2179 }
2180 /*
2181 Compare reference to reconstruct image.
2182 */
2183 difference_image=CompareImages(reference_image,reconstruct_image,
2184 RootMeanSquaredErrorMetric,&distortion,exception);
2185 reconstruct_image=DestroyImage(reconstruct_image);
2186 reference_image=DestroyImage(reference_image);
2187 if (difference_image == (Image *) NULL ||
2188 (exception->severity >= ErrorException))
2189 {
2190 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2191 GetMagickModule());
2192 CatchException(exception);
2193 fail++;
2194 continue;
2195 }
2196 difference_image=DestroyImage(difference_image);
2197 if ((QuantumScale*distortion) > 0.0)
2198 {
2199 (void) FormatLocaleFile(stdout,"... fail (with distortion %g).\n",
2200 QuantumScale*distortion);
2201 fail++;
2202 continue;
2203 }
2204 (void) FormatLocaleFile(stdout,"... pass.\n");
2205 }
2206 }
2207 (void) FormatLocaleFile(stdout,
2208 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2209 (double) (test-fail),(double) fail);
2210 *fails+=fail;
2211 return(test);
2212 }
2213
2214 /*
2215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2216 % %
2217 % %
2218 % %
2219 % V a l i d a t e M o n t a g e C o m m a n d %
2220 % %
2221 % %
2222 % %
2223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2224 %
2225 % ValidateMontageCommand() validates the ImageMagick montage command line
2226 % program and returns the number of validation tests that passed and failed.
2227 %
2228 % The format of the ValidateMontageCommand method is:
2229 %
2230 % size_t ValidateMontageCommand(ImageInfo *image_info,
2231 % const char *reference_filename,const char *output_filename,
2232 % size_t *fails,ExceptionInfo *exception)
2233 %
2234 % A description of each parameter follows:
2235 %
2236 % o image_info: the image info.
2237 %
2238 % o reference_filename: the reference image filename.
2239 %
2240 % o output_filename: the output image filename.
2241 %
2242 % o fail: return the number of validation tests that pass.
2243 %
2244 % o exception: return any errors or warnings in this structure.
2245 %
2246 */
ValidateMontageCommand(ImageInfo * image_info,const char * reference_filename,const char * output_filename,size_t * fails,ExceptionInfo * exception)2247 static size_t ValidateMontageCommand(ImageInfo *image_info,
2248 const char *reference_filename,const char *output_filename,size_t *fails,
2249 ExceptionInfo *exception)
2250 {
2251 char
2252 **arguments,
2253 command[MagickPathExtent];
2254
2255 int
2256 number_arguments;
2257
2258 MagickBooleanType
2259 status;
2260
2261 ssize_t
2262 i,
2263 j;
2264
2265 size_t
2266 fail,
2267 test;
2268
2269 fail=0;
2270 test=0;
2271 (void) FormatLocaleFile(stdout,"validate montage command line program:\n");
2272 for (i=0; montage_options[i] != (char *) NULL; i++)
2273 {
2274 CatchException(exception);
2275 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
2276 montage_options[i]);
2277 (void) FormatLocaleString(command,MagickPathExtent,"%s %s %s %s",
2278 reference_filename,montage_options[i],reference_filename,
2279 output_filename);
2280 arguments=StringToArgv(command,&number_arguments);
2281 if (arguments == (char **) NULL)
2282 {
2283 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2284 GetMagickModule());
2285 fail++;
2286 continue;
2287 }
2288 status=MontageImageCommand(image_info,number_arguments,arguments,
2289 (char **) NULL,exception);
2290 for (j=0; j < (ssize_t) number_arguments; j++)
2291 arguments[j]=DestroyString(arguments[j]);
2292 arguments=(char **) RelinquishMagickMemory(arguments);
2293 if (status == MagickFalse)
2294 {
2295 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2296 GetMagickModule());
2297 fail++;
2298 continue;
2299 }
2300 (void) FormatLocaleFile(stdout,"... pass.\n");
2301 }
2302 (void) FormatLocaleFile(stdout,
2303 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2304 (double) (test-fail),(double) fail);
2305 *fails+=fail;
2306 return(test);
2307 }
2308
2309 /*
2310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2311 % %
2312 % %
2313 % %
2314 % V a l i d a t e S t r e a m C o m m a n d %
2315 % %
2316 % %
2317 % %
2318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2319 %
2320 % ValidateStreamCommand() validates the ImageMagick stream command line
2321 % program and returns the number of validation tests that passed and failed.
2322 %
2323 % The format of the ValidateStreamCommand method is:
2324 %
2325 % size_t ValidateStreamCommand(ImageInfo *image_info,
2326 % const char *reference_filename,const char *output_filename,
2327 % size_t *fails,ExceptionInfo *exception)
2328 %
2329 % A description of each parameter follows:
2330 %
2331 % o image_info: the image info.
2332 %
2333 % o reference_filename: the reference image filename.
2334 %
2335 % o output_filename: the output image filename.
2336 %
2337 % o fail: return the number of validation tests that pass.
2338 %
2339 % o exception: return any errors or warnings in this structure.
2340 %
2341 */
ValidateStreamCommand(ImageInfo * image_info,const char * reference_filename,const char * output_filename,size_t * fails,ExceptionInfo * exception)2342 static size_t ValidateStreamCommand(ImageInfo *image_info,
2343 const char *reference_filename,const char *output_filename,size_t *fails,
2344 ExceptionInfo *exception)
2345 {
2346 char
2347 **arguments,
2348 command[MagickPathExtent];
2349
2350 int
2351 number_arguments;
2352
2353 MagickBooleanType
2354 status;
2355
2356 ssize_t
2357 i,
2358 j;
2359
2360 size_t
2361 fail,
2362 test;
2363
2364 fail=0;
2365 test=0;
2366 (void) FormatLocaleFile(stdout,"validate stream command line program:\n");
2367 for (i=0; stream_options[i] != (char *) NULL; i++)
2368 {
2369 CatchException(exception);
2370 (void) FormatLocaleFile(stdout," test %.20g: %s",(double) (test++),
2371 stream_options[i]);
2372 (void) FormatLocaleString(command,MagickPathExtent,"%s %s %s",
2373 stream_options[i],reference_filename,output_filename);
2374 arguments=StringToArgv(command,&number_arguments);
2375 if (arguments == (char **) NULL)
2376 {
2377 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2378 GetMagickModule());
2379 fail++;
2380 continue;
2381 }
2382 status=StreamImageCommand(image_info,number_arguments,arguments,
2383 (char **) NULL,exception);
2384 for (j=0; j < (ssize_t) number_arguments; j++)
2385 arguments[j]=DestroyString(arguments[j]);
2386 arguments=(char **) RelinquishMagickMemory(arguments);
2387 if (status == MagickFalse)
2388 {
2389 (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n",
2390 GetMagickModule());
2391 fail++;
2392 continue;
2393 }
2394 (void) FormatLocaleFile(stdout,"... pass.\n");
2395 }
2396 (void) FormatLocaleFile(stdout,
2397 " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test,
2398 (double) (test-fail),(double) fail);
2399 *fails+=fail;
2400 return(test);
2401 }
2402
2403 /*
2404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2405 % %
2406 % %
2407 % %
2408 % M a i n %
2409 % %
2410 % %
2411 % %
2412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2413 %
2414 %
2415 */
2416
ValidateUsage(void)2417 static MagickBooleanType ValidateUsage(void)
2418 {
2419 const char
2420 **p;
2421
2422 static const char
2423 *miscellaneous[]=
2424 {
2425 "-debug events display copious debugging information",
2426 "-help print program options",
2427 "-log format format of debugging information",
2428 "-validate type validation type",
2429 "-version print version information",
2430 (char *) NULL
2431 },
2432 *settings[]=
2433 {
2434 "-regard-warnings pay attention to warning messages",
2435 "-verbose print detailed information about the image",
2436 (char *) NULL
2437 };
2438
2439 (void) printf("Version: %s\n",GetMagickVersion((size_t *) NULL));
2440 (void) printf("Copyright: %s\n\n",GetMagickCopyright());
2441 (void) printf("Features: %s\n",GetMagickFeatures());
2442 (void) printf("Usage: %s [options ...] reference-file\n",GetClientName());
2443 (void) printf("\nValidate Settings:\n");
2444 for (p=settings; *p != (char *) NULL; p++)
2445 (void) printf(" %s\n",*p);
2446 (void) printf("\nMiscellaneous Options:\n");
2447 for (p=miscellaneous; *p != (char *) NULL; p++)
2448 (void) printf(" %s\n",*p);
2449 return(MagickTrue);
2450 }
2451
main(int argc,char ** argv)2452 int main(int argc,char **argv)
2453 {
2454 #define DestroyValidate() \
2455 { \
2456 image_info=DestroyImageInfo(image_info); \
2457 exception=DestroyExceptionInfo(exception); \
2458 }
2459 #define ThrowValidateException(asperity,tag,option) \
2460 { \
2461 (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
2462 option); \
2463 CatchException(exception); \
2464 DestroyValidate(); \
2465 return(MagickFalse); \
2466 }
2467
2468 char
2469 output_filename[MagickPathExtent],
2470 reference_filename[MagickPathExtent],
2471 *option;
2472
2473 double
2474 elapsed_time,
2475 user_time;
2476
2477 ExceptionInfo
2478 *exception;
2479
2480 Image
2481 *reference_image;
2482
2483 ImageInfo
2484 *image_info;
2485
2486 MagickBooleanType
2487 regard_warnings,
2488 status;
2489
2490 MagickSizeType
2491 memory_resource,
2492 map_resource;
2493
2494 ssize_t
2495 i;
2496
2497 TimerInfo
2498 *timer;
2499
2500 size_t
2501 fail,
2502 iterations,
2503 tests;
2504
2505 ValidateType
2506 type;
2507
2508 /*
2509 Validate the ImageMagick image processing suite.
2510 */
2511 MagickCoreGenesis(*argv,MagickTrue);
2512 (void) setlocale(LC_ALL,"");
2513 (void) setlocale(LC_NUMERIC,"C");
2514 iterations=1;
2515 status=MagickFalse;
2516 type=AllValidate;
2517 regard_warnings=MagickFalse;
2518 (void) regard_warnings;
2519 exception=AcquireExceptionInfo();
2520 image_info=AcquireImageInfo();
2521 (void) CopyMagickString(image_info->filename,ReferenceFilename,
2522 MagickPathExtent);
2523 for (i=1; i < (ssize_t) argc; i++)
2524 {
2525 option=argv[i];
2526 if (IsCommandOption(option) == MagickFalse)
2527 {
2528 (void) CopyMagickString(image_info->filename,option,MagickPathExtent);
2529 continue;
2530 }
2531 switch (*(option+1))
2532 {
2533 case 'b':
2534 {
2535 if (LocaleCompare("bench",option+1) == 0)
2536 {
2537 iterations=StringToUnsignedLong(argv[++i]);
2538 break;
2539 }
2540 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2541 }
2542 case 'd':
2543 {
2544 if (LocaleCompare("debug",option+1) == 0)
2545 {
2546 (void) SetLogEventMask(argv[++i]);
2547 break;
2548 }
2549 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2550 }
2551 case 'h':
2552 {
2553 if (LocaleCompare("help",option+1) == 0)
2554 {
2555 (void) ValidateUsage();
2556 return(0);
2557 }
2558 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2559 }
2560 case 'l':
2561 {
2562 if (LocaleCompare("log",option+1) == 0)
2563 {
2564 if (*option != '+')
2565 (void) SetLogFormat(argv[i+1]);
2566 break;
2567 }
2568 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2569 }
2570 case 'r':
2571 {
2572 if (LocaleCompare("regard-warnings",option+1) == 0)
2573 {
2574 regard_warnings=MagickTrue;
2575 break;
2576 }
2577 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2578 }
2579 case 'v':
2580 {
2581 if (LocaleCompare("validate",option+1) == 0)
2582 {
2583 ssize_t
2584 validate;
2585
2586 if (*option == '+')
2587 break;
2588 i++;
2589 if (i >= (ssize_t) argc)
2590 ThrowValidateException(OptionError,"MissingArgument",option);
2591 validate=ParseCommandOption(MagickValidateOptions,MagickFalse,
2592 argv[i]);
2593 if (validate < 0)
2594 ThrowValidateException(OptionError,"UnrecognizedValidateType",
2595 argv[i]);
2596 type=(ValidateType) validate;
2597 break;
2598 }
2599 if ((LocaleCompare("version",option+1) == 0) ||
2600 (LocaleCompare("-version",option+1) == 0))
2601 {
2602 (void) FormatLocaleFile(stdout,"Version: %s\n",
2603 GetMagickVersion((size_t *) NULL));
2604 (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
2605 GetMagickCopyright());
2606 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
2607 GetMagickFeatures());
2608 return(0);
2609 }
2610 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2611 }
2612 default:
2613 ThrowValidateException(OptionError,"UnrecognizedOption",option)
2614 }
2615 }
2616 timer=(TimerInfo *) NULL;
2617 if (iterations > 1)
2618 timer=AcquireTimerInfo();
2619 reference_image=ReadImage(image_info,exception);
2620 tests=0;
2621 fail=0;
2622 if (reference_image == (Image *) NULL)
2623 fail++;
2624 else
2625 {
2626 if (LocaleCompare(image_info->filename,ReferenceFilename) == 0)
2627 (void) CopyMagickString(reference_image->magick,ReferenceImageFormat,
2628 MagickPathExtent);
2629 (void) AcquireUniqueFilename(reference_filename);
2630 (void) AcquireUniqueFilename(output_filename);
2631 (void) CopyMagickString(reference_image->filename,reference_filename,
2632 MagickPathExtent);
2633 status=WriteImage(image_info,reference_image,exception);
2634 reference_image=DestroyImage(reference_image);
2635 if (status == MagickFalse)
2636 fail++;
2637 else
2638 {
2639 (void) FormatLocaleFile(stdout,"Version: %s\n",
2640 GetMagickVersion((size_t *) NULL));
2641 (void) FormatLocaleFile(stdout,"Copyright: %s\n\n",
2642 GetMagickCopyright());
2643 (void) FormatLocaleFile(stdout,
2644 "ImageMagick Validation Suite (%s)\n\n",CommandOptionToMnemonic(
2645 MagickValidateOptions,(ssize_t) type));
2646 if ((type & ColorspaceValidate) != 0)
2647 tests+=ValidateColorspaces(image_info,&fail,exception);
2648 if ((type & CompareValidate) != 0)
2649 tests+=ValidateCompareCommand(image_info,reference_filename,
2650 output_filename,&fail,exception);
2651 if ((type & CompositeValidate) != 0)
2652 tests+=ValidateCompositeCommand(image_info,reference_filename,
2653 output_filename,&fail,exception);
2654 if ((type & ConvertValidate) != 0)
2655 tests+=ValidateConvertCommand(image_info,reference_filename,
2656 output_filename,&fail,exception);
2657 if ((type & FormatsDiskValidate) != 0)
2658 {
2659 memory_resource=SetMagickResourceLimit(MemoryResource,0);
2660 map_resource=SetMagickResourceLimit(MapResource,0);
2661 (void) FormatLocaleFile(stdout,"[pixel-cache: disk] ");
2662 tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
2663 output_filename,&fail,exception);
2664 (void) FormatLocaleFile(stdout,"[pixel-cache: disk] ");
2665 tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
2666 output_filename,&fail,exception);
2667 (void) SetMagickResourceLimit(MemoryResource,memory_resource);
2668 (void) SetMagickResourceLimit(MapResource,map_resource);
2669 }
2670 if ((type & FormatsMapValidate) != 0)
2671 {
2672 memory_resource=SetMagickResourceLimit(MemoryResource,0);
2673 (void) FormatLocaleFile(stdout,"[pixel-cache: memory-mapped] ");
2674 tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
2675 output_filename,&fail,exception);
2676 (void) FormatLocaleFile(stdout,"[pixel-cache: memory-mapped] ");
2677 tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
2678 output_filename,&fail,exception);
2679 (void) SetMagickResourceLimit(MemoryResource,memory_resource);
2680 }
2681 if ((type & FormatsMemoryValidate) != 0)
2682 {
2683 (void) FormatLocaleFile(stdout,"[pixel-cache: memory] ");
2684 tests+=ValidateImageFormatsInMemory(image_info,reference_filename,
2685 output_filename,&fail,exception);
2686 (void) FormatLocaleFile(stdout,"[pixel-cache: memory] ");
2687 tests+=ValidateImageFormatsOnDisk(image_info,reference_filename,
2688 output_filename,&fail,exception);
2689 }
2690 if ((type & IdentifyValidate) != 0)
2691 tests+=ValidateIdentifyCommand(image_info,reference_filename,
2692 output_filename,&fail,exception);
2693 if ((type & ImportExportValidate) != 0)
2694 tests+=ValidateImportExportPixels(image_info,reference_filename,
2695 output_filename,&fail,exception);
2696 if ((type & MontageValidate) != 0)
2697 tests+=ValidateMontageCommand(image_info,reference_filename,
2698 output_filename,&fail,exception);
2699 if ((type & StreamValidate) != 0)
2700 tests+=ValidateStreamCommand(image_info,reference_filename,
2701 output_filename,&fail,exception);
2702 (void) FormatLocaleFile(stdout,
2703 "validation suite: %.20g tests; %.20g passed; %.20g failed.\n",
2704 (double) tests,(double) (tests-fail),(double) fail);
2705 }
2706 (void) RelinquishUniqueFileResource(output_filename);
2707 (void) RelinquishUniqueFileResource(reference_filename);
2708 }
2709 if (exception->severity != UndefinedException)
2710 CatchException(exception);
2711 if (iterations > 1)
2712 {
2713 elapsed_time=GetElapsedTime(timer);
2714 user_time=GetUserTime(timer);
2715 (void) FormatLocaleFile(stderr,
2716 "Performance: %.20gi %.3fips %0.6fu %ld:%02ld.%03ld\n",(double)
2717 iterations,1.0*iterations/elapsed_time,user_time,(long)
2718 (elapsed_time/60.0),(long) ceil(fmod(elapsed_time,60.0)),
2719 (long) (1000.0*(elapsed_time-floor(elapsed_time))));
2720 timer=DestroyTimerInfo(timer);
2721 }
2722 DestroyValidate();
2723 MagickCoreTerminus();
2724 return(fail == 0 ? 0 : 1);
2725 }
2726