X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=tests%2Fvalidate.c;h=5afb516d51c31de4e8bf3f076ca4c469d85e1cc3;hb=b56bb24a985ca4366713bcd8ffdfacbb48a98a2f;hp=64b3ec1b77a3f5db3aae016eb4ff7febab326199;hpb=bda201a1b108a687bb6889cb94b525e8fa5af79c;p=imagemagick diff --git a/tests/validate.c b/tests/validate.c index 64b3ec1b7..5afb516d5 100644 --- a/tests/validate.c +++ b/tests/validate.c @@ -14,11 +14,11 @@ % ImageMagick Validation Suite % % % % Software Design % -% John Cristy % +% Cristy % % March 2001 % % % % % -% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % +% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization % % dedicated to making software imaging solutions freely available. % % % % You may not use this file except in compliance with the License. You may % @@ -45,11 +45,1095 @@ #include #include #include +#include #include "MagickWand/MagickWand.h" #include "MagickCore/colorspace-private.h" +#include "MagickCore/gem.h" +#include "MagickCore/resource_.h" #include "MagickCore/string-private.h" #include "validate.h" +/* + Define declarations. +*/ +#define CIEEpsilon (216.0/24389.0) +#define CIEK (24389.0/27.0) +#define D65X 0.950456 +#define D65Y 1.0 +#define D65Z 1.088754 +#define ReferenceEpsilon (QuantumRange*1.0e-2) + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% V a l i d a t e C o l o r s p a c e s % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% ValidateColorspaces() validates the ImageMagick colorspaces and returns the +% number of validation tests that passed and failed. +% +% The format of the ValidateColorspaces method is: +% +% size_t ValidateColorspaces(ImageInfo *image_info,size_t *fail, +% ExceptionInfo *exception) +% +% A description of each parameter follows: +% +% o image_info: the image info. +% +% o fail: return the number of validation tests that pass. +% +% o exception: return any errors or warnings in this structure. +% +*/ + +static void ConvertHSIToRGB(const double hue,const double saturation, + const double intensity,double *red,double *green,double *blue) +{ + double + h; + + h=360.0*hue; + h-=360.0*floor(h/360.0); + if (h < 120.0) + { + *blue=intensity*(1.0-saturation); + *red=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)* + (MagickPI/180.0))); + *green=3.0*intensity-*red-*blue; + } + else + if (h < 240.0) + { + h-=120.0; + *red=intensity*(1.0-saturation); + *green=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)* + (MagickPI/180.0))); + *blue=3.0*intensity-*red-*green; + } + else + { + h-=240.0; + *green=intensity*(1.0-saturation); + *blue=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)* + (MagickPI/180.0))); + *red=3.0*intensity-*green-*blue; + } + *red*=QuantumRange; + *green*=QuantumRange; + *blue*=QuantumRange; +} + +static inline double MagickMin(const double x,const double y) +{ + if (x < y) + return(x); + return(y); +} + +static void ConvertRGBToHSI(const double red,const double green, + const double blue,double *hue,double *saturation,double *intensity) +{ + double + alpha, + beta; + + *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0; + if (*intensity <= 0.0) + { + *hue=0.0; + *saturation=0.0; + return; + } + *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green, + QuantumScale*blue))/(*intensity); + alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue); + beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue); + *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0; + if (*hue < 0.0) + *hue+=1.0; +} + +static inline double MagickMax(const double x,const double y) +{ + if (x > y) + return(x); + return(y); +} + +static void ConvertHSVToRGB(const double hue,const double saturation, + const double value,double *red,double *green,double *blue) +{ + double + c, + h, + min, + x; + + h=hue*360.0; + c=value*saturation; + min=value-c; + h-=360.0*floor(h/360.0); + h/=60.0; + x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0)); + switch ((int) floor(h)) + { + case 0: + { + *red=QuantumRange*(min+c); + *green=QuantumRange*(min+x); + *blue=QuantumRange*min; + break; + } + case 1: + { + *red=QuantumRange*(min+x); + *green=QuantumRange*(min+c); + *blue=QuantumRange*min; + break; + } + case 2: + { + *red=QuantumRange*min; + *green=QuantumRange*(min+c); + *blue=QuantumRange*(min+x); + break; + } + case 3: + { + *red=QuantumRange*min; + *green=QuantumRange*(min+x); + *blue=QuantumRange*(min+c); + break; + } + case 4: + { + *red=QuantumRange*(min+x); + *green=QuantumRange*min; + *blue=QuantumRange*(min+c); + break; + } + case 5: + { + *red=QuantumRange*(min+c); + *green=QuantumRange*min; + *blue=QuantumRange*(min+x); + break; + } + default: + { + *red=0.0; + *green=0.0; + *blue=0.0; + } + } +} + +static inline void ConvertRGBToXYZ(const double red,const double green, + const double blue,double *X,double *Y,double *Z) +{ + double + b, + g, + r; + + r=QuantumScale*DecodePixelGamma(red); + g=QuantumScale*DecodePixelGamma(green); + b=QuantumScale*DecodePixelGamma(blue); + *X=0.41239558896741421610*r+0.35758343076371481710*g+0.18049264738170157350*b; + *Y=0.21258623078559555160*r+0.71517030370341084990*g+0.07220049864333622685*b; + *Z=0.01929721549174694484*r+0.11918386458084853180*g+0.95049712513157976600*b; +} + +static inline void ConvertXYZToLab(const double X,const double Y,const double Z, + double *L,double *a,double *b) +{ + double + x, + y, + z; + + if ((X/D65X) > CIEEpsilon) + x=pow(X/D65X,1.0/3.0); + else + x=(CIEK*X/D65X+16.0)/116.0; + if ((Y/D65Y) > CIEEpsilon) + y=pow(Y/D65Y,1.0/3.0); + else + y=(CIEK*Y/D65Y+16.0)/116.0; + if ((Z/D65Z) > CIEEpsilon) + z=pow(Z/D65Z,1.0/3.0); + else + z=(CIEK*Z/D65Z+16.0)/116.0; + *L=((116.0*y)-16.0)/100.0; + *a=(500.0*(x-y))/255.0+0.5; + *b=(200.0*(y-z))/255.0+0.5; +} + +static void ConvertRGBToLab(const double red,const double green, + const double blue,double *L,double *a,double *b) +{ + double + X, + Y, + Z; + + ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z); + ConvertXYZToLab(X,Y,Z,L,a,b); +} + +static inline void ConvertLabToXYZ(const double L,const double a,const double b, + double *X,double *Y,double *Z) +{ + double + x, + y, + z; + + y=(L+16.0)/116.0; + x=y+a/500.0; + z=y-b/200.0; + if ((x*x*x) > CIEEpsilon) + x=(x*x*x); + else + x=(116.0*x-16.0)/CIEK; + if ((y*y*y) > CIEEpsilon) + y=(y*y*y); + else + y=L/CIEK; + if ((z*z*z) > CIEEpsilon) + z=(z*z*z); + else + z=(116.0*z-16.0)/CIEK; + *X=D65X*x; + *Y=D65Y*y; + *Z=D65Z*z; +} + +static inline void ConvertXYZToRGB(const double x,const double y,const double z, + double *red,double *green,double *blue) +{ + double + b, + g, + r; + + r=3.2406*x-1.5372*y-0.4986*z; + g=(-0.9689*x+1.8758*y+0.0415*z); + b=0.0557*x-0.2040*y+1.0570*z; + *red=EncodePixelGamma(QuantumRange*r); + *green=EncodePixelGamma(QuantumRange*g); + *blue=EncodePixelGamma(QuantumRange*b); +} + +static inline void ConvertLabToRGB(const double L,const double a, + const double b,double *red,double *green,double *blue) +{ + double + X, + Y, + Z; + + ConvertLabToXYZ(L*100.0,255.0*(a-0.5),255.0*(b-0.5),&X,&Y,&Z); + ConvertXYZToRGB(X,Y,Z,red,green,blue); +} + +static void ConvertRGBToYPbPr(const double red,const double green, + const double blue,double *Y,double *Pb,double *Pr) +{ + *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue); + *Pb=QuantumScale*((-0.1687367)*red-0.331264*green+0.5*blue)+0.5; + *Pr=QuantumScale*(0.5*red-0.418688*green-0.081312*blue)+0.5; +} + +static void ConvertRGBToYCbCr(const double red,const double green, + const double blue,double *Y,double *Cb,double *Cr) +{ + ConvertRGBToYPbPr(red,green,blue,Y,Cb,Cr); +} + +static void ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr, + double *red,double *green,double *blue) +{ + *red=QuantumRange*(0.99999999999914679361*Y-1.2188941887145875e-06*(Pb-0.5)+ + 1.4019995886561440468*(Pr-0.5)); + *green=QuantumRange*(0.99999975910502514331*Y-0.34413567816504303521*(Pb-0.5)- + 0.71413649331646789076*(Pr-0.5)); + *blue=QuantumRange*(1.00000124040004623180*Y+1.77200006607230409200*(Pb-0.5)+ + 2.1453384174593273e-06*(Pr-0.5)); +} + +static void ConvertYCbCrToRGB(const double Y,const double Cb, + const double Cr,double *red,double *green,double *blue) +{ + ConvertYPbPrToRGB(Y,Cb,Cr,red,green,blue); +} + +static inline void ConvertLCHabToXYZ(const double luma,const double chroma, + const double hue,double *X,double *Y,double *Z) +{ + ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma* + sin(hue*MagickPI/180.0),X,Y,Z); +} + +static void ConvertLCHabToRGB(const double luma,const double chroma, + const double hue,double *red,double *green,double *blue) +{ + double + X, + Y, + Z; + + ConvertLCHabToXYZ(luma*100.0,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z); + ConvertXYZToRGB(X,Y,Z,red,green,blue); +} + +static void ConvertRGBToHSV(const double red,const double green, + const double blue,double *hue,double *saturation,double *value) +{ + double + c, + max, + min; + + max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green, + QuantumScale*blue)); + min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green, + QuantumScale*blue)); + c=max-min; + *value=max; + if (c <= 0.0) + { + *hue=0.0; + *saturation=0.0; + return; + } + if (max == (QuantumScale*red)) + { + *hue=(QuantumScale*green-QuantumScale*blue)/c; + if ((QuantumScale*green) < (QuantumScale*blue)) + *hue+=6.0; + } + else + if (max == (QuantumScale*green)) + *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c; + else + *hue=4.0+(QuantumScale*red-QuantumScale*green)/c; + *hue*=60.0/360.0; + *saturation=c/max; +} + +static inline void ConvertXYZToLCHab(const double X,const double Y, + const double Z,double *luma,double *chroma,double *hue) +{ + double + a, + b; + + ConvertXYZToLab(X,Y,Z,luma,&a,&b); + *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5))/255.0+0.5; + *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI/360.0; + if (*hue < 0.0) + *hue+=1.0; +} + +static void ConvertRGBToLCHab(const double red,const double green, + const double blue,double *luma,double *chroma,double *hue) +{ + double + X, + Y, + Z; + + ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z); + ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue); +} + +static inline void ConvertLMSToXYZ(const double L,const double M,const double S, + double *X,double *Y,double *Z) +{ + *X=1.096123820835514*L-0.278869000218287*M+0.182745179382773*S; + *Y=0.454369041975359*L+0.473533154307412*M+0.072097803717229*S; + *Z=(-0.009627608738429)*L-0.005698031216113*M+1.015325639954543*S; +} + +static inline void ConvertLMSToRGB(const double L,const double M, + const double S,double *red,double *green,double *blue) +{ + double + X, + Y, + Z; + + ConvertLMSToXYZ(L,M,S,&X,&Y,&Z); + ConvertXYZToRGB(X,Y,Z,red,green,blue); +} + +static inline void ConvertXYZToLMS(const double x,const double y, + const double z,double *L,double *M,double *S) +{ + *L=0.7328*x+0.4296*y-0.1624*z; + *M=(-0.7036*x+1.6975*y+0.0061*z); + *S=0.0030*x+0.0136*y+0.9834*z; +} + +static void ConvertRGBToLMS(const double red,const double green, + const double blue,double *L,double *M,double *S) +{ + double + X, + Y, + Z; + + ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z); + ConvertXYZToLMS(X,Y,Z,L,M,S); +} + +static inline double PerceptibleReciprocal(const double x) +{ + double + sign; + + /* + Return 1/x where x is perceptible (not unlimited or infinitesimal). + */ + sign=x < 0.0 ? -1.0 : 1.0; + if ((sign*x) >= MagickEpsilon) + return(1.0/x); + return(sign/MagickEpsilon); +} + +static inline void ConvertXYZToLuv(const double X,const double Y,const double Z, + double *L,double *u,double *v) +{ + double + alpha; + + if ((Y/D65Y) > CIEEpsilon) + *L=(double) (116.0*pow(Y/D65Y,1.0/3.0)-16.0); + else + *L=CIEK*(Y/D65Y); + alpha=PerceptibleReciprocal(X+15.0*Y+3.0*Z); + *u=13.0*(*L)*((4.0*alpha*X)-(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))); + *v=13.0*(*L)*((9.0*alpha*Y)-(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z))); + *L/=100.0; + *u=(*u+134.0)/354.0; + *v=(*v+140.0)/262.0; +} + +static void ConvertRGBToLuv(const double red,const double green, + const double blue,double *L,double *u,double *v) +{ + double + X, + Y, + Z; + + ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z); + ConvertXYZToLuv(X,Y,Z,L,u,v); +} + +static inline void ConvertLuvToXYZ(const double L,const double u,const double v, + double *X,double *Y,double *Z) +{ + if (L > (CIEK*CIEEpsilon)) + *Y=(double) pow((L+16.0)/116.0,3.0); + else + *Y=L/CIEK; + *X=((*Y*((39.0*L/(v+13.0*L*(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z))))-5.0))+ + 5.0*(*Y))/((((52.0f*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/ + 3.0)-(-1.0/3.0)); + *Z=(*X*(((52.0f*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/3.0))- + 5.0*(*Y); +} + +static inline void ConvertLuvToRGB(const double L,const double u, + const double v,double *red,double *green,double *blue) +{ + double + X, + Y, + Z; + + ConvertLuvToXYZ(100.0*L,354.0*u-134.0,262.0*v-140.0,&X,&Y,&Z); + ConvertXYZToRGB(X,Y,Z,red,green,blue); +} + +static void ConvertRGBToYDbDr(const double red,const double green, + const double blue,double *Y,double *Db,double *Dr) +{ + *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue); + *Db=QuantumScale*(-0.450*red-0.883*green+1.333*blue)+0.5; + *Dr=QuantumScale*(-1.333*red+1.116*green+0.217*blue)+0.5; +} + +static void ConvertYDbDrToRGB(const double Y,const double Db,const double Dr, + double *red,double *green,double *blue) +{ + *red=QuantumRange*(Y+9.2303716147657e-05*(Db-0.5)-0.52591263066186533* + (Dr-0.5)); + *green=QuantumRange*(Y-0.12913289889050927*(Db-0.5)+0.26789932820759876* + (Dr-0.5)); + *blue=QuantumRange*(Y+0.66467905997895482*(Db-0.5)-7.9202543533108e-05* + (Dr-0.5)); +} + +static void ConvertRGBToYIQ(const double red,const double green, + const double blue,double *Y,double *I,double *Q) +{ + *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue); + *I=QuantumScale*(0.595716*red-0.274453*green-0.321263*blue)+0.5; + *Q=QuantumScale*(0.211456*red-0.522591*green+0.311135*blue)+0.5; +} + +static void ConvertYIQToRGB(const double Y,const double I,const double Q, + double *red,double *green,double *blue) +{ + *red=QuantumRange*(Y+0.9562957197589482261*(I-0.5)+0.6210244164652610754* + (Q-0.5)); + *green=QuantumRange*(Y-0.2721220993185104464*(I-0.5)-0.6473805968256950427* + (Q-0.5)); + *blue=QuantumRange*(Y-1.1069890167364901945*(I-0.5)+1.7046149983646481374* + (Q-0.5)); +} + +static void ConvertRGBToYUV(const double red,const double green, + const double blue,double *Y,double *U,double *V) +{ + *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue); + *U=QuantumScale*((-0.147)*red-0.289*green+0.436*blue)+0.5; + *V=QuantumScale*(0.615*red-0.515*green-0.100*blue)+0.5; +} + +static void ConvertYUVToRGB(const double Y,const double U,const double V, + double *red,double *green,double *blue) +{ + *red=QuantumRange*(Y-3.945707070708279e-05*(U-0.5)+1.1398279671717170825* + (V-0.5)); + *green=QuantumRange*(Y-0.3946101641414141437*(U-0.5)-0.5805003156565656797* + (V-0.5)); + *blue=QuantumRange*(Y+2.0319996843434342537*(U-0.5)-4.813762626262513e-04* + (V-0.5)); +} + +static MagickBooleanType ValidateHSIToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," HSIToRGB"); + ConvertHSIToRGB(111.244375/360.0,0.295985,0.658734,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToHSI() +{ + double + h, + i, + s; + + (void) FormatLocaleFile(stdout," RGBToHSI"); + ConvertRGBToHSI(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&h,&s,&i); + if ((fabs(h-111.244374/360.0) >= ReferenceEpsilon) || + (fabs(s-0.295985) >= ReferenceEpsilon) || + (fabs(i-0.658734) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateHSLToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," HSLToRGB"); + ConvertHSLToRGB(110.200859/360.0,0.882623,0.715163,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToHSL() +{ + double + h, + l, + s; + + (void) FormatLocaleFile(stdout," RGBToHSL"); + ConvertRGBToHSL(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&h,&s,&l); + if ((fabs(h-110.200859/360.0) >= ReferenceEpsilon) || + (fabs(s-0.882623) >= ReferenceEpsilon) || + (fabs(l-0.715163) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateHSVToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," HSVToRGB"); + ConvertHSVToRGB(110.200859/360.0,0.520200,0.966567,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToHSV() +{ + double + h, + s, + v; + + (void) FormatLocaleFile(stdout," RGBToHSV"); + ConvertRGBToHSV(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&h,&s,&v); + if ((fabs(h-110.200859/360.0) >= ReferenceEpsilon) || + (fabs(s-0.520200) >= ReferenceEpsilon) || + (fabs(v-0.966567) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToJPEGYCbCr() +{ + double + Cb, + Cr, + Y; + + (void) FormatLocaleFile(stdout," RGBToJPEGYCbCr"); + ConvertRGBToYCbCr(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&Y,&Cb,&Cr); + if ((fabs(Y-0.783460) >= ReferenceEpsilon) || + (fabs(Cb-0.319581) >= ReferenceEpsilon) || + (fabs(Cr-0.330539) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateJPEGYCbCrToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," JPEGYCbCrToRGB"); + ConvertYCbCrToRGB(0.783460,0.319581,0.330539,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateLabToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," LabToRGB"); + ConvertLabToRGB(88.456154/100.0,-54.671483/255+0.5,51.662818/255.0+0.5, + &r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToLab() +{ + double + a, + b, + L; + + (void) FormatLocaleFile(stdout," RGBToLab"); + ConvertRGBToLab(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&L,&a,&b); + if ((fabs(L-(88.456154/100.0)) >= ReferenceEpsilon) || + (fabs(a-(-54.671483/255.0+0.5)) >= ReferenceEpsilon) || + (fabs(b-(51.662818/255.0+0.5)) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateLchToRGB() +{ + double + b, + g, + r; + + (void) FormatLocaleFile(stdout," LchToRGB"); + ConvertLCHabToRGB(88.456154/100.0,75.219797/255.0+0.5,136.620717/360.0, + &r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToLch() +{ + double + c, + h, + L; + + (void) FormatLocaleFile(stdout," RGBToLch"); + ConvertRGBToLCHab(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&L,&c,&h); + if ((fabs(L-88.456154/100.0) >= ReferenceEpsilon) || + (fabs(c-(75.219797/255.0+0.5)) >= ReferenceEpsilon) || + (fabs(h-(136.620717/255.0+0.5)) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToLMS() +{ + double + L, + M, + S; + + (void) FormatLocaleFile(stdout," RGBToLMS"); + ConvertRGBToLMS(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&L,&M,&S); + if ((fabs(L-0.611749) >= ReferenceEpsilon) || + (fabs(M-0.910088) >= ReferenceEpsilon) || + (fabs(S-0.294880) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateLMSToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," LMSToRGB"); + ConvertLMSToRGB(0.611749,0.910088,0.294880,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToLuv() +{ + double + l, + u, + v; + + (void) FormatLocaleFile(stdout," RGBToLuv"); + ConvertRGBToLuv(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&l,&u,&v); + if ((fabs(l-88.456154/262.0) >= ReferenceEpsilon) || + (fabs(u-(-51.330414+134.0)/354.0) >= ReferenceEpsilon) || + (fabs(v-(76.405526+140.0)/262.0) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateLuvToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," LuvToRGB"); + ConvertLuvToRGB(88.456154/100.0,(-51.330414+134.0)/354.0, + (76.405526+140.0)/262.0,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToXYZ() +{ + double + x, + y, + z; + + (void) FormatLocaleFile(stdout," RGBToXYZ"); + ConvertRGBToXYZ(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&x,&y,&z); + if ((fabs(x-0.470646) >= ReferenceEpsilon) || + (fabs(y-0.730178) >= ReferenceEpsilon) || + (fabs(z-0.288324) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateXYZToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," XYZToRGB"); + ConvertXYZToRGB(0.470646,0.730178,0.288324,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateYDbDrToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," YDbDrToRGB"); + ConvertYDbDrToRGB(0.783460,-0.480932+0.5,0.451670+0.5,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToYDbDr() +{ + double + Db, + Dr, + Y; + + (void) FormatLocaleFile(stdout," RGBToYDbDr"); + ConvertRGBToYDbDr(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&Y,&Db,&Dr); + if ((fabs(Y-0.783460) >= ReferenceEpsilon) || + (fabs(Db-(-0.480932)) >= ReferenceEpsilon) || + (fabs(Dr-0.451670) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToYIQ() +{ + double + i, + q, + y; + + (void) FormatLocaleFile(stdout," RGBToYIQ"); + ConvertRGBToYIQ(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&y,&i,&q); + if ((fabs(y-0.783460) >= ReferenceEpsilon) || + (fabs(i-(-0.089078)) >= ReferenceEpsilon) || + (fabs(q-(-0.245399)) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateYIQToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," YIQToRGB"); + ConvertYIQToRGB(0.783460,-0.089078+0.5,-0.245399+0.5,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToYPbPr() +{ + double + Pb, + Pr, + y; + + (void) FormatLocaleFile(stdout," RGBToYPbPr"); + ConvertRGBToYPbPr(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&y,&Pb,&Pr); + if ((fabs(y-0.783460) >= ReferenceEpsilon) || + (fabs(Pb-(-0.180419)) >= ReferenceEpsilon) || + (fabs(Pr-(-0.169461)) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateYPbPrToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," YPbPrToRGB"); + ConvertYPbPrToRGB(0.783460,-0.180419+0.5,-0.169461+0.5,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateRGBToYUV() +{ + double + U, + V, + Y; + + (void) FormatLocaleFile(stdout," RGBToYUV"); + ConvertRGBToYUV(0.545877*QuantumRange,0.966567*QuantumRange, + 0.463759*QuantumRange,&Y,&U,&V); + if ((fabs(Y-0.783460) >= ReferenceEpsilon) || + (fabs(U-(-0.157383)) >= ReferenceEpsilon) || + (fabs(V-(-0.208443)) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ValidateYUVToRGB() +{ + double + r, + g, + b; + + (void) FormatLocaleFile(stdout," YUVToRGB"); + ConvertYUVToRGB(0.783460,-0.157383+0.5,-0.208443+0.5,&r,&g,&b); + if ((fabs(r-0.545877*QuantumRange) >= ReferenceEpsilon) || + (fabs(g-0.966567*QuantumRange) >= ReferenceEpsilon) || + (fabs(b-0.463759*QuantumRange) >= ReferenceEpsilon)) + return(MagickFalse); + return(MagickTrue); +} + +static size_t ValidateColorspaces(ImageInfo *image_info,size_t *fail, + ExceptionInfo *exception) +{ + MagickBooleanType + status; + + size_t + test; + + /* + Reference: https://code.google.com/p/chroma. + + Illuminant = D65 + Observer = 2° (1931) + + XYZ 0.470645, 0.730177, 0.288323 + sRGB 0.545877, 0.966567, 0.463759 + CAT02 LMS 0.611749, 0.910088, 0.294880 + Y'DbDr 0.783460, -0.480932, 0.451670 + Y'IQ 0.783460, -0.089078, -0.245399 + Y'PbPr 0.783460, -0.180419, -0.169461 + Y'UV 0.783460, -0.157383, -0.208443 + JPEG-Y'CbCr 0.783460, 0.319581, 0.330539 + L*u*v* 88.456154, -51.330414, 76.405526 + L*a*b* 88.456154, -54.671483, 51.662818 + L*C*H* 88.456154, 75.219797, 136.620717 + HSV 110.200859, 0.520200, 0.966567 + HSL 110.200859, 0.882623, 0.715163 + HSI 111.244375, 0.295985, 0.658734 + Y'CbCr 187.577791, 87.586330, 90.040886 + */ + (void) FormatLocaleFile(stdout,"validate colorspaces:\n"); + for (test=0; test < 26; test++) + { + CatchException(exception); + (void) FormatLocaleFile(stdout," test %.20g: ",(double) test); + switch (test) + { + case 0: status=ValidateHSIToRGB(); break; + case 1: status=ValidateRGBToHSI(); break; + case 2: status=ValidateHSLToRGB(); break; + case 3: status=ValidateRGBToHSL(); break; + case 4: status=ValidateHSVToRGB(); break; + case 5: status=ValidateRGBToHSV(); break; + case 6: status=ValidateJPEGYCbCrToRGB(); break; + case 7: status=ValidateRGBToJPEGYCbCr(); break; + case 8: status=ValidateLabToRGB(); break; + case 9: status=ValidateRGBToLab(); break; + case 10: status=ValidateLchToRGB(); break; + case 11: status=ValidateRGBToLch(); break; + case 12: status=ValidateLMSToRGB(); break; + case 13: status=ValidateRGBToLMS(); break; + case 14: status=ValidateLuvToRGB(); break; + case 15: status=ValidateRGBToLuv(); break; + case 16: status=ValidateXYZToRGB(); break; + case 17: status=ValidateRGBToXYZ(); break; + case 18: status=ValidateYDbDrToRGB(); break; + case 19: status=ValidateRGBToYDbDr(); break; + case 20: status=ValidateYIQToRGB(); break; + case 21: status=ValidateRGBToYIQ(); break; + case 22: status=ValidateYPbPrToRGB(); break; + case 23: status=ValidateRGBToYPbPr(); break; + case 24: status=ValidateYUVToRGB(); break; + case 25: status=ValidateRGBToYUV(); break; + default: status=MagickFalse; + } + if (status == MagickFalse) + { + (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", + GetMagickModule()); + (*fail)++; + continue; + } + (void) FormatLocaleFile(stdout,"... pass.\n"); + } + (void) FormatLocaleFile(stdout, + " summary: %.20g subtests; %.20g passed; %.20g failed.\n",(double) test, + (double) (test-(*fail)),(double) *fail); + return(test); +} + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % @@ -84,8 +1168,8 @@ % */ static size_t ValidateCompareCommand(ImageInfo *image_info, - const char *reference_filename,const char *output_filename, - size_t *fail,ExceptionInfo *exception) + const char *reference_filename,const char *output_filename,size_t *fail, + ExceptionInfo *exception) { char **arguments, @@ -126,7 +1210,7 @@ static size_t ValidateCompareCommand(ImageInfo *image_info, for (j=0; j < (ssize_t) number_arguments; j++) arguments[j]=DestroyString(arguments[j]); arguments=(char **) RelinquishMagickMemory(arguments); - if (status != MagickFalse) + if (status == MagickFalse) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); @@ -175,8 +1259,8 @@ static size_t ValidateCompareCommand(ImageInfo *image_info, % */ static size_t ValidateCompositeCommand(ImageInfo *image_info, - const char *reference_filename,const char *output_filename, - size_t *fail,ExceptionInfo *exception) + const char *reference_filename,const char *output_filename,size_t *fail, + ExceptionInfo *exception) { char **arguments, @@ -218,7 +1302,7 @@ static size_t ValidateCompositeCommand(ImageInfo *image_info, for (j=0; j < (ssize_t) number_arguments; j++) arguments[j]=DestroyString(arguments[j]); arguments=(char **) RelinquishMagickMemory(arguments); - if (status != MagickFalse) + if (status == MagickFalse) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); @@ -267,8 +1351,8 @@ static size_t ValidateCompositeCommand(ImageInfo *image_info, % */ static size_t ValidateConvertCommand(ImageInfo *image_info, - const char *reference_filename,const char *output_filename, - size_t *fail,ExceptionInfo *exception) + const char *reference_filename,const char *output_filename,size_t *fail, + ExceptionInfo *exception) { char **arguments, @@ -309,7 +1393,7 @@ static size_t ValidateConvertCommand(ImageInfo *image_info, for (j=0; j < (ssize_t) number_arguments; j++) arguments[j]=DestroyString(arguments[j]); arguments=(char **) RelinquishMagickMemory(arguments); - if (status != MagickFalse) + if (status == MagickFalse) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); @@ -358,8 +1442,8 @@ static size_t ValidateConvertCommand(ImageInfo *image_info, % */ static size_t ValidateIdentifyCommand(ImageInfo *image_info, - const char *reference_filename,const char *output_filename, - size_t *fail,ExceptionInfo *exception) + const char *reference_filename,const char *output_filename,size_t *fail, + ExceptionInfo *exception) { char **arguments, @@ -401,7 +1485,7 @@ static size_t ValidateIdentifyCommand(ImageInfo *image_info, for (j=0; j < (ssize_t) number_arguments; j++) arguments[j]=DestroyString(arguments[j]); arguments=(char **) RelinquishMagickMemory(arguments); - if (status != MagickFalse) + if (status == MagickFalse) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); @@ -449,11 +1533,22 @@ static size_t ValidateIdentifyCommand(ImageInfo *image_info, % o exception: return any errors or warnings in this structure. % */ + +/* + Enable this to count remaining $TMPDIR/magick-* files. Note that the count + includes any files left over from other runs. +*/ +#undef MagickCountTempFiles + static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, - const char *reference_filename,const char *output_filename, - size_t *fail,ExceptionInfo *exception) + const char *reference_filename,const char *output_filename,size_t *fail, + ExceptionInfo *exception) { char +#ifdef MagickCountTempFiles + path[MaxTextExtent], + SystemCommand[MaxTextExtent], +#endif size[MaxTextExtent]; const MagickInfo @@ -485,6 +1580,14 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, test=0; (void) FormatLocaleFile(stdout,"validate image formats in memory:\n"); + +#ifdef MagickCountTempFiles + (void)GetPathTemplate(path); + /* Remove file template except for the leading "/path/to/magick-" */ + path[strlen(path)-17]='\0'; + (void) FormatLocaleFile(stdout," tmp path is '%s*'\n",path); +#endif + for (i=0; reference_formats[i].magick != (char *) NULL; i++) { magick_info=GetMagickInfo(reference_formats[i].magick,exception); @@ -506,10 +1609,12 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, (void) CopyMagickString(image_info->filename,reference_filename, MaxTextExtent); reference_image=ReadImage(image_info,exception); - if (reference_image == (Image *) NULL) + if (reference_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -523,19 +1628,21 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s", reference_formats[i].magick,output_filename); status=SetImageType(reference_image,reference_types[j].type,exception); - if (status == MagickFalse) + if (status == MagickFalse || exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; reference_image=DestroyImage(reference_image); continue; } status=SetImageDepth(reference_image,reference_types[j].depth,exception); - if (status == MagickFalse) + if (status == MagickFalse || exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; reference_image=DestroyImage(reference_image); continue; @@ -543,10 +1650,11 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, reference_image->compression=reference_formats[i].compression; status=WriteImage(image_info,reference_image,exception); reference_image=DestroyImage(reference_image); - if (status == MagickFalse) + if (status == MagickFalse || exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -556,10 +1664,12 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s", reference_formats[i].magick,output_filename); ping_image=PingImage(image_info,exception); - if (ping_image == (Image *) NULL) + if (ping_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -568,10 +1678,12 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, Read reference image. */ reference_image=ReadImage(image_info,exception); - if (reference_image == (Image *) NULL) + if (reference_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -586,10 +1698,12 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, reference_image->compression=reference_formats[i].compression; length=8192; blob=ImageToBlob(image_info,reference_image,&length,exception); - if (blob == (unsigned char *) NULL) + if (blob == (unsigned char *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; reference_image=DestroyImage(reference_image); continue; @@ -598,10 +1712,12 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, Ping reference blob. */ ping_image=PingBlob(image_info,blob,length,exception); - if (ping_image == (Image *) NULL) + if (ping_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; blob=(unsigned char *) RelinquishMagickMemory(blob); continue; @@ -614,10 +1730,12 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, reference_formats[i].magick,output_filename); reconstruct_image=BlobToImage(image_info,blob,length,exception); blob=(unsigned char *) RelinquishMagickMemory(blob); - if (reconstruct_image == (Image *) NULL) + if (reconstruct_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; reference_image=DestroyImage(reference_image); continue; @@ -625,23 +1743,19 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, /* Compare reference to reconstruct image. */ - fuzz=0.0; + fuzz=0.003; /* grayscale */ if (reference_formats[i].fuzz != 0.0) fuzz=reference_formats[i].fuzz; -#if defined(MAGICKCORE_HDRI_SUPPORT) - fuzz+=0.003; -#endif - if (IssRGBColorspace(reference_image->colorspace) == MagickFalse) - fuzz+=0.3; - fuzz+=MagickEpsilon; difference_image=CompareImages(reference_image,reconstruct_image, RootMeanSquaredErrorMetric,&distortion,exception); reconstruct_image=DestroyImage(reconstruct_image); reference_image=DestroyImage(reference_image); - if (difference_image == (Image *) NULL) + if (difference_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -653,7 +1767,18 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, (*fail)++; continue; } - (void) FormatLocaleFile(stdout,"... pass.\n"); +#ifdef MagickCountTempFiles + (void) FormatLocaleFile(stdout,"... pass, "); + (void) fflush(stdout); + SystemCommand[0]='\0'; + (void) strncat(SystemCommand,"echo `ls ",9); + (void) strncat(SystemCommand,path,MaxTextExtent-31); + (void) strncat(SystemCommand,"* | wc -w` tmp files.",20); + (void) system(SystemCommand); + (void) fflush(stdout); +#else + (void) FormatLocaleFile(stdout,"... pass\n"); +#endif } } (void) FormatLocaleFile(stdout, @@ -696,8 +1821,8 @@ static size_t ValidateImageFormatsInMemory(ImageInfo *image_info, % */ static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info, - const char *reference_filename,const char *output_filename, - size_t *fail,ExceptionInfo *exception) + const char *reference_filename,const char *output_filename,size_t *fail, + ExceptionInfo *exception) { char size[MaxTextExtent]; @@ -747,10 +1872,12 @@ static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info, (void) CopyMagickString(image_info->filename,reference_filename, MaxTextExtent); reference_image=ReadImage(image_info,exception); - if (reference_image == (Image *) NULL) + if (reference_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -764,19 +1891,21 @@ static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info, (void) FormatLocaleString(reference_image->filename,MaxTextExtent,"%s:%s", reference_formats[i].magick,output_filename); status=SetImageType(reference_image,reference_types[j].type,exception); - if (status == MagickFalse) + if (status == MagickFalse || exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; reference_image=DestroyImage(reference_image); continue; } status=SetImageDepth(reference_image,reference_types[j].depth,exception); - if (status == MagickFalse) + if (status == MagickFalse || exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; reference_image=DestroyImage(reference_image); continue; @@ -784,10 +1913,11 @@ static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info, reference_image->compression=reference_formats[i].compression; status=WriteImage(image_info,reference_image,exception); reference_image=DestroyImage(reference_image); - if (status == MagickFalse) + if (status == MagickFalse || exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -797,10 +1927,12 @@ static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info, (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s", reference_formats[i].magick,output_filename); reference_image=ReadImage(image_info,exception); - if (reference_image == (Image *) NULL) + if (reference_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -812,10 +1944,11 @@ static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info, reference_image->depth=reference_types[j].depth; reference_image->compression=reference_formats[i].compression; status=WriteImage(image_info,reference_image,exception); - if (status == MagickFalse) + if (status == MagickFalse ||exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; reference_image=DestroyImage(reference_image); continue; @@ -826,10 +1959,12 @@ static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info, (void) FormatLocaleString(image_info->filename,MaxTextExtent,"%s:%s", reference_formats[i].magick,output_filename); reconstruct_image=ReadImage(image_info,exception); - if (reconstruct_image == (Image *) NULL) + if (reconstruct_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; reference_image=DestroyImage(reference_image); continue; @@ -837,23 +1972,19 @@ static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info, /* Compare reference to reconstruct image. */ - fuzz=0.0; + fuzz=0.003; /* grayscale */ if (reference_formats[i].fuzz != 0.0) fuzz=reference_formats[i].fuzz; -#if defined(MAGICKCORE_HDRI_SUPPORT) - fuzz+=0.003; -#endif - if (IssRGBColorspace(reference_image->colorspace) == MagickFalse) - fuzz+=0.3; - fuzz+=MagickEpsilon; difference_image=CompareImages(reference_image,reconstruct_image, RootMeanSquaredErrorMetric,&distortion,exception); reconstruct_image=DestroyImage(reconstruct_image); reference_image=DestroyImage(reference_image); - if (difference_image == (Image *) NULL) + if (difference_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -908,8 +2039,8 @@ static size_t ValidateImageFormatsOnDisk(ImageInfo *image_info, % */ static size_t ValidateImportExportPixels(ImageInfo *image_info, - const char *reference_filename,const char *output_filename, - size_t *fail,ExceptionInfo *exception) + const char *reference_filename,const char *output_filename,size_t *fail, + ExceptionInfo *exception) { double distortion; @@ -953,10 +2084,12 @@ static size_t ValidateImportExportPixels(ImageInfo *image_info, (void) CopyMagickString(image_info->filename,reference_filename, MaxTextExtent); reference_image=ReadImage(image_info,exception); - if (reference_image == (Image *) NULL) + if (reference_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -965,10 +2098,12 @@ static size_t ValidateImportExportPixels(ImageInfo *image_info, length=strlen(reference_map[i])*reference_image->columns* reference_image->rows*reference_storage[j].quantum; pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels)); - if (pixels == (unsigned char *) NULL) + if (pixels == (unsigned char *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; reference_image=DestroyImage(reference_image); continue; @@ -977,10 +2112,11 @@ static size_t ValidateImportExportPixels(ImageInfo *image_info, status=ExportImagePixels(reference_image,0,0,reference_image->columns, reference_image->rows,reference_map[i],reference_storage[j].type,pixels, exception); - if (status == MagickFalse) + if (status == MagickFalse || exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; pixels=(unsigned char *) RelinquishMagickMemory(pixels); reference_image=DestroyImage(reference_image); @@ -990,10 +2126,11 @@ static size_t ValidateImportExportPixels(ImageInfo *image_info, status=ImportImagePixels(reference_image,0,0,reference_image->columns, reference_image->rows,reference_map[i],reference_storage[j].type, pixels,exception); - if (status == MagickFalse) + if (status == MagickFalse || exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; pixels=(unsigned char *) RelinquishMagickMemory(pixels); reference_image=DestroyImage(reference_image); @@ -1012,10 +2149,11 @@ static size_t ValidateImportExportPixels(ImageInfo *image_info, reconstruct_image->rows,reference_map[i],reference_storage[j].type, pixels,exception); pixels=(unsigned char *) RelinquishMagickMemory(pixels); - if (status == MagickFalse) + if (status == MagickFalse || exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; reference_image=DestroyImage(reference_image); continue; @@ -1027,10 +2165,12 @@ static size_t ValidateImportExportPixels(ImageInfo *image_info, RootMeanSquaredErrorMetric,&distortion,exception); reconstruct_image=DestroyImage(reconstruct_image); reference_image=DestroyImage(reference_image); - if (difference_image == (Image *) NULL) + if (difference_image == (Image *) NULL || + exception->severity >= ErrorException) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); + CatchException(exception); (*fail)++; continue; } @@ -1085,8 +2225,8 @@ static size_t ValidateImportExportPixels(ImageInfo *image_info, % */ static size_t ValidateMontageCommand(ImageInfo *image_info, - const char *reference_filename,const char *output_filename, - size_t *fail,ExceptionInfo *exception) + const char *reference_filename,const char *output_filename,size_t *fail, + ExceptionInfo *exception) { char **arguments, @@ -1128,7 +2268,7 @@ static size_t ValidateMontageCommand(ImageInfo *image_info, for (j=0; j < (ssize_t) number_arguments; j++) arguments[j]=DestroyString(arguments[j]); arguments=(char **) RelinquishMagickMemory(arguments); - if (status != MagickFalse) + if (status == MagickFalse) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); @@ -1177,8 +2317,8 @@ static size_t ValidateMontageCommand(ImageInfo *image_info, % */ static size_t ValidateStreamCommand(ImageInfo *image_info, - const char *reference_filename,const char *output_filename, - size_t *fail,ExceptionInfo *exception) + const char *reference_filename,const char *output_filename,size_t *fail, + ExceptionInfo *exception) { char **arguments, @@ -1219,7 +2359,7 @@ static size_t ValidateStreamCommand(ImageInfo *image_info, for (j=0; j < (ssize_t) number_arguments; j++) arguments[j]=DestroyString(arguments[j]); arguments=(char **) RelinquishMagickMemory(arguments); - if (status != MagickFalse) + if (status == MagickFalse) { (void) FormatLocaleFile(stdout,"... fail @ %s/%s/%lu.\n", GetMagickModule()); @@ -1321,6 +2461,10 @@ int main(int argc,char **argv) regard_warnings, status; + MagickSizeType + memory_resource, + map_resource; + register ssize_t i; @@ -1338,7 +2482,9 @@ int main(int argc,char **argv) /* Validate the ImageMagick image processing suite. */ - MagickCoreGenesis(*argv,MagickFalse); + MagickCoreGenesis(*argv,MagickTrue); + (void) setlocale(LC_ALL,""); + (void) setlocale(LC_NUMERIC,"C"); iterations=1; status=MagickFalse; type=AllValidate; @@ -1413,7 +2559,7 @@ int main(int argc,char **argv) if (*option == '+') break; i++; - if (i == (ssize_t) argc) + if (i >= (ssize_t) argc) ThrowValidateException(OptionError,"MissingArgument",option); validate=ParseCommandOption(MagickValidateOptions,MagickFalse, argv[i]); @@ -1470,6 +2616,8 @@ int main(int argc,char **argv) (void) FormatLocaleFile(stdout, "ImageMagick Validation Suite (%s)\n\n",CommandOptionToMnemonic( MagickValidateOptions,(ssize_t) type)); + if ((type & ColorspaceValidate) != 0) + tests+=ValidateColorspaces(image_info,&fail,exception); if ((type & CompareValidate) != 0) tests+=ValidateCompareCommand(image_info,reference_filename, output_filename,&fail,exception); @@ -1479,21 +2627,36 @@ int main(int argc,char **argv) if ((type & ConvertValidate) != 0) tests+=ValidateConvertCommand(image_info,reference_filename, output_filename,&fail,exception); - if ((type & FormatsInMemoryValidate) != 0) - tests+=ValidateImageFormatsInMemory(image_info,reference_filename, - output_filename,&fail,exception); - if ((type & FormatsOnDiskValidate) != 0) + if ((type & FormatsDiskValidate) != 0) { - /* - Validate image formats on disk with pixel cache in - memory, memory-mapped, and on disk. - */ + memory_resource=SetMagickResourceLimit(MemoryResource,0); + map_resource=SetMagickResourceLimit(MapResource,0); + (void) FormatLocaleFile(stdout,"[pixel-cache: disk] "); + tests+=ValidateImageFormatsInMemory(image_info,reference_filename, + output_filename,&fail,exception); + (void) FormatLocaleFile(stdout,"[pixel-cache: disk] "); tests+=ValidateImageFormatsOnDisk(image_info,reference_filename, output_filename,&fail,exception); - (void) SetMagickResourceLimit(MemoryResource,0); + (void) SetMagickResourceLimit(MemoryResource,memory_resource); + (void) SetMagickResourceLimit(MapResource,map_resource); + } + if ((type & FormatsMapValidate) != 0) + { + memory_resource=SetMagickResourceLimit(MemoryResource,0); + (void) FormatLocaleFile(stdout,"[pixel-cache: memory-mapped] "); + tests+=ValidateImageFormatsInMemory(image_info,reference_filename, + output_filename,&fail,exception); + (void) FormatLocaleFile(stdout,"[pixel-cache: memory-mapped] "); tests+=ValidateImageFormatsOnDisk(image_info,reference_filename, output_filename,&fail,exception); - (void) SetMagickResourceLimit(MapResource,0); + (void) SetMagickResourceLimit(MemoryResource,memory_resource); + } + if ((type & FormatsMemoryValidate) != 0) + { + (void) FormatLocaleFile(stdout,"[pixel-cache: memory] "); + tests+=ValidateImageFormatsInMemory(image_info,reference_filename, + output_filename,&fail,exception); + (void) FormatLocaleFile(stdout,"[pixel-cache: memory] "); tests+=ValidateImageFormatsOnDisk(image_info,reference_filename, output_filename,&fail,exception); }