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