% August 1996 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2013 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 %
#include "MagickCore/log.h"
#include "MagickCore/memory_.h"
#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/pixel-private.h"
#include "MagickCore/quantum.h"
#include "MagickCore/quantum-private.h"
#include "MagickCore/random_.h"
% %
% %
% %
+% C o n v e r t H C L T o R G B %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertHCLToRGB() transforms a (hue, chroma, luma) to a (red, green,
+% blue) triple.
+%
+% The format of the ConvertHCLToRGBImage method is:
+%
+% void ConvertHCLToRGB(const double hue,const double chroma,
+% const double luma,double *red,double *green,double *blue)
+%
+% A description of each parameter follows:
+%
+% o hue, chroma, luma: A double value representing a component of the
+% HCL color space.
+%
+% o red, green, blue: A pointer to a pixel component of type Quantum.
+%
+*/
+MagickPrivate void ConvertHCLToRGB(const double hue,const double chroma,
+ const double luma,double *red,double *green,double *blue)
+{
+ double
+ b,
+ c,
+ g,
+ h,
+ m,
+ r,
+ x;
+
+ /*
+ Convert HCL to RGB colorspace.
+ */
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
+ h=6.0*hue;
+ c=chroma;
+ x=c*(1.0-fabs(fmod(h,2.0)-1.0));
+ r=0.0;
+ g=0.0;
+ b=0.0;
+ if ((0.0 <= h) && (h < 1.0))
+ {
+ r=c;
+ g=x;
+ }
+ else
+ if ((1.0 <= h) && (h < 2.0))
+ {
+ r=x;
+ g=c;
+ }
+ else
+ if ((2.0 <= h) && (h < 3.0))
+ {
+ g=c;
+ b=x;
+ }
+ else
+ if ((3.0 <= h) && (h < 4.0))
+ {
+ g=x;
+ b=c;
+ }
+ else
+ if ((4.0 <= h) && (h < 5.0))
+ {
+ r=x;
+ b=c;
+ }
+ else
+ if ((5.0 <= h) && (h < 6.0))
+ {
+ r=c;
+ b=x;
+ }
+ m=luma-(0.298839*r+0.586811*g+0.114350*b);
+ *red=QuantumRange*(r+m);
+ *green=QuantumRange*(g+m);
+ *blue=QuantumRange*(b+m);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C o n v e r t H C L p T o R G B %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertHCLpToRGB() transforms a (hue, chroma, luma) to a (red, green,
+% blue) triple. Since HCL colorspace is wider than RGB, we instead choose a
+% saturation strategy to project it on the RGB cube.
+%
+% The format of the ConvertHCLpToRGBImage method is:
+%
+% void ConvertHCLpToRGB(const double hue,const double chroma,
+% const double luma,double *red,double *green,double *blue)
+%
+% A description of each parameter follows:
+%
+% o hue, chroma, luma: A double value representing a componenet of the
+% HCLp color space.
+%
+% o red, green, blue: A pointer to a pixel component of type Quantum.
+%
+*/
+MagickPrivate void ConvertHCLpToRGB(const double hue,const double chroma,
+ const double luma,double *red,double *green,double *blue)
+{
+ double
+ b,
+ c,
+ g,
+ h,
+ m,
+ r,
+ x,
+ z;
+
+ /*
+ Convert HCLp to RGB colorspace.
+ */
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
+ h=6.0*hue;
+ c=chroma;
+ x=c*(1.0-fabs(fmod(h,2.0)-1.0));
+ r=0.0;
+ g=0.0;
+ b=0.0;
+ if ((0.0 <= h) && (h < 1.0))
+ {
+ r=c;
+ g=x;
+ }
+ else
+ if ((1.0 <= h) && (h < 2.0))
+ {
+ r=x;
+ g=c;
+ }
+ else
+ if ((2.0 <= h) && (h < 3.0))
+ {
+ g=c;
+ b=x;
+ }
+ else
+ if ((3.0 <= h) && (h < 4.0))
+ {
+ g=x;
+ b=c;
+ }
+ else
+ if ((4.0 <= h) && (h < 5.0))
+ {
+ r=x;
+ b=c;
+ }
+ else
+ if ((5.0 <= h) && (h < 6.0))
+ {
+ r=c;
+ b=x;
+ }
+ m=luma-(0.298839*r+0.586811*g+0.114350*b);
+ z=1.0;
+ if (m < 0.0)
+ {
+ z=luma/(luma-m);
+ m=0.0;
+ }
+ else
+ if (m+c > 1.0)
+ {
+ z=(1.0-luma)/(m+c-luma);
+ m=1.0-z*c;
+ }
+ *red=QuantumRange*(z*r+m);
+ *green=QuantumRange*(z*g+m);
+ *blue=QuantumRange*(z*b+m);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% C o n v e r t H S B T o R G B %
% %
% %
MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
const double brightness,double *red,double *green,double *blue)
{
- MagickRealType
+ double
f,
h,
p,
assert(blue != (double *) NULL);
if (saturation == 0.0)
{
- *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
+ *red=QuantumRange*brightness;
*green=(*red);
*blue=(*red);
return;
case 0:
default:
{
- *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
- *green=ClampToQuantum((MagickRealType) QuantumRange*t);
- *blue=ClampToQuantum((MagickRealType) QuantumRange*p);
+ *red=QuantumRange*brightness;
+ *green=QuantumRange*t;
+ *blue=QuantumRange*p;
break;
}
case 1:
{
- *red=ClampToQuantum((MagickRealType) QuantumRange*q);
- *green=ClampToQuantum((MagickRealType) QuantumRange*brightness);
- *blue=ClampToQuantum((MagickRealType) QuantumRange*p);
+ *red=QuantumRange*q;
+ *green=QuantumRange*brightness;
+ *blue=QuantumRange*p;
break;
}
case 2:
{
- *red=ClampToQuantum((MagickRealType) QuantumRange*p);
- *green=ClampToQuantum((MagickRealType) QuantumRange*brightness);
- *blue=ClampToQuantum((MagickRealType) QuantumRange*t);
+ *red=QuantumRange*p;
+ *green=QuantumRange*brightness;
+ *blue=QuantumRange*t;
break;
}
case 3:
{
- *red=ClampToQuantum((MagickRealType) QuantumRange*p);
- *green=ClampToQuantum((MagickRealType) QuantumRange*q);
- *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
+ *red=QuantumRange*p;
+ *green=QuantumRange*q;
+ *blue=QuantumRange*brightness;
break;
}
case 4:
{
- *red=ClampToQuantum((MagickRealType) QuantumRange*t);
- *green=ClampToQuantum((MagickRealType) QuantumRange*p);
- *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
+ *red=QuantumRange*t;
+ *green=QuantumRange*p;
+ *blue=QuantumRange*brightness;
break;
}
case 5:
{
- *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
- *green=ClampToQuantum((MagickRealType) QuantumRange*p);
- *blue=ClampToQuantum((MagickRealType) QuantumRange*q);
+ *red=QuantumRange*brightness;
+ *green=QuantumRange*p;
+ *blue=QuantumRange*q;
break;
}
}
% %
% %
% %
+% C o n v e r t H S I T o R G B %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertHSIToRGB() transforms a (hue, saturation, intensity) to a (red,
+% green, blue) triple.
+%
+% The format of the ConvertHSIToRGBImage method is:
+%
+% void ConvertHSIToRGB(const double hue,const double saturation,
+% const double intensity,double *red,double *green,double *blue)
+%
+% A description of each parameter follows:
+%
+% o hue, saturation, intensity: A double value representing a
+% component of the HSI color space.
+%
+% o red, green, blue: A pointer to a pixel component of type Quantum.
+%
+*/
+MagickPrivate void ConvertHSIToRGB(const double hue,const double saturation,
+ const double intensity,double *red,double *green,double *blue)
+{
+ double
+ b,
+ g,
+ h,
+ r;
+
+ /*
+ Convert HSI to RGB colorspace.
+ */
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
+ h=360.0*hue;
+ h-=360.0*floor(h/360.0);
+ if (h < 120.0)
+ {
+ b=intensity*(1.0-saturation);
+ r=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
+ (MagickPI/180.0)));
+ g=3.0*intensity-r-b;
+ }
+ else
+ if (h < 240.0)
+ {
+ h-=120.0;
+ r=intensity*(1.0-saturation);
+ g=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
+ (MagickPI/180.0)));
+ b=3.0*intensity-r-g;
+ }
+ else
+ {
+ h-=240.0;
+ g=intensity*(1.0-saturation);
+ b=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
+ (MagickPI/180.0)));
+ r=3.0*intensity-g-b;
+ }
+ *red=QuantumRange*r;
+ *green=QuantumRange*g;
+ *blue=QuantumRange*b;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% C o n v e r t H S L T o R G B %
% %
% %
% o red, green, blue: A pointer to a pixel component of type Quantum.
%
*/
-
-static inline MagickRealType ConvertHueToRGB(MagickRealType m1,
- MagickRealType m2,MagickRealType hue)
-{
- if (hue < 0.0)
- hue+=1.0;
- if (hue > 1.0)
- hue-=1.0;
- if ((6.0*hue) < 1.0)
- return(m1+6.0*(m2-m1)*hue);
- if ((2.0*hue) < 1.0)
- return(m2);
- if ((3.0*hue) < 2.0)
- return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
- return(m1);
-}
-
MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
const double lightness,double *red,double *green,double *blue)
{
- MagickRealType
- b,
- g,
- r,
- m1,
- m2;
+ double
+ c,
+ h,
+ min,
+ x;
/*
Convert HSL to RGB colorspace.
assert(red != (double *) NULL);
assert(green != (double *) NULL);
assert(blue != (double *) NULL);
- if (saturation == 0)
+ h=hue*360.0;
+ if (lightness <= 0.5)
+ c=2.0*lightness*saturation;
+ else
+ c=(2.0-2.0*lightness)*saturation;
+ min=lightness-0.5*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=ClampToQuantum((MagickRealType) QuantumRange*lightness);
- *green=(*red);
- *blue=(*red);
- return;
+ *red=QuantumRange*(min+c);
+ *green=QuantumRange*(min+x);
+ *blue=QuantumRange*min;
+ break;
}
- if (lightness < 0.5)
- m2=lightness*(saturation+1.0);
- else
- m2=(lightness+saturation)-(lightness*saturation);
- m1=2.0*lightness-m2;
- r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
- g=ConvertHueToRGB(m1,m2,hue);
- b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
- *red=ClampToQuantum((MagickRealType) QuantumRange*r);
- *green=ClampToQuantum((MagickRealType) QuantumRange*g);
- *blue=ClampToQuantum((MagickRealType) QuantumRange*b);
+ 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;
+ }
+ }
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C o n v e r t H S V T o R G B %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertHSVToRGB() transforms a (hue, saturation, value) to a (red,
+% green, blue) triple.
+%
+% The format of the ConvertHSVToRGBImage method is:
+%
+% void ConvertHSVToRGB(const double hue,const double saturation,
+% const double value,double *red,double *green,double *blue)
+%
+% A description of each parameter follows:
+%
+% o hue, saturation, value: A double value representing a
+% component of the HSV color space.
+%
+% o red, green, blue: A pointer to a pixel component of type Quantum.
+%
+*/
+MagickPrivate void ConvertHSVToRGB(const double hue,const double saturation,
+ const double value,double *red,double *green,double *blue)
+{
+ double
+ c,
+ h,
+ min,
+ x;
+
+ /*
+ Convert HSV to RGB colorspace.
+ */
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
+ 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;
+ }
+ }
}
\f
/*
% o hue, whiteness, blackness: A double value representing a
% component of the HWB color space.
%
-% o red, green, blue: A pointer to a pixel component of type Quantum.
+% o red, green, blue: A pointer to a pixel component of type Quantum.
+%
+*/
+MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
+ const double blackness,double *red,double *green,double *blue)
+{
+ double
+ b,
+ f,
+ g,
+ n,
+ r,
+ v;
+
+ register ssize_t
+ i;
+
+ /*
+ Convert HWB to RGB colorspace.
+ */
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
+ v=1.0-blackness;
+ if (hue == -1.0)
+ {
+ *red=QuantumRange*v;
+ *green=QuantumRange*v;
+ *blue=QuantumRange*v;
+ return;
+ }
+ i=(ssize_t) floor(6.0*hue);
+ f=6.0*hue-i;
+ if ((i & 0x01) != 0)
+ f=1.0-f;
+ n=whiteness+f*(v-whiteness); /* linear interpolation */
+ switch (i)
+ {
+ default:
+ case 6:
+ case 0: r=v; g=n; b=whiteness; break;
+ case 1: r=n; g=v; b=whiteness; break;
+ case 2: r=whiteness; g=v; b=n; break;
+ case 3: r=whiteness; g=n; b=v; break;
+ case 4: r=n; g=whiteness; b=v; break;
+ case 5: r=v; g=whiteness; b=n; break;
+ }
+ *red=QuantumRange*r;
+ *green=QuantumRange*g;
+ *blue=QuantumRange*b;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C o n v e r t L C H a b T o R G B %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertLCHabToRGB() transforms a (luma, chroma, hue) to a (red, green,
+% blue) triple.
+%
+% The format of the ConvertLCHabToRGBImage method is:
+%
+% void ConvertLCHabToRGB(const double luma,const double chroma,
+% const double hue,double *red,double *green,double *blue)
+%
+% A description of each parameter follows:
+%
+% o luma, chroma, hue: A double value representing a component of the
+% LCHab color space.
+%
+% o red, green, blue: A pointer to a pixel component of type Quantum.
+%
+*/
+
+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);
+}
+
+MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
+ const double hue,double *red,double *green,double *blue)
+{
+ double
+ X,
+ Y,
+ Z;
+
+ /*
+ Convert LCHab to RGB colorspace.
+ */
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
+ ConvertLCHabToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*(hue-0.5),&X,&Y,&Z);
+ ConvertXYZToRGB(X,Y,Z,red,green,blue);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C o n v e r t L C H u v T o R G B %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertLCHuvToRGB() transforms a (luma, chroma, hue) to a (red, green,
+% blue) triple.
+%
+% The format of the ConvertLCHuvToRGBImage method is:
+%
+% void ConvertLCHuvToRGB(const double luma,const double chroma,
+% const double hue,double *red,double *green,double *blue)
+%
+% A description of each parameter follows:
+%
+% o luma, chroma, hue: A double value representing a component of the
+% LCHuv color space.
+%
+% o red, green, blue: A pointer to a pixel component of type Quantum.
+%
+*/
+
+static inline void ConvertLCHuvToXYZ(const double luma,const double chroma,
+ const double hue,double *X,double *Y,double *Z)
+{
+ ConvertLuvToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
+ sin(hue*MagickPI/180.0),X,Y,Z);
+}
+
+MagickPrivate void ConvertLCHuvToRGB(const double luma,const double chroma,
+ const double hue,double *red,double *green,double *blue)
+{
+ double
+ X,
+ Y,
+ Z;
+
+ /*
+ Convert LCHuv to RGB colorspace.
+ */
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
+ ConvertLCHuvToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*(hue-0.5),&X,&Y,&Z)
+ ConvertXYZToRGB(X,Y,Z,red,green,blue);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C o n v e r t R G B T o H C L %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
+% luma) triple.
+%
+% The format of the ConvertRGBToHCL method is:
+%
+% void ConvertRGBToHCL(const double red,const double green,
+% const double blue,double *hue,double *chroma,double *luma)
+%
+% A description of each parameter follows:
+%
+% o red, green, blue: A Quantum value representing the red, green, and
+% blue component of a pixel.
+%
+% o hue, chroma, luma: A pointer to a double value representing a
+% component of the HCL color space.
+%
+*/
+
+static inline double MagickMax(const double x,const double y)
+{
+ if (x > y)
+ return(x);
+ return(y);
+}
+
+static inline double MagickMin(const double x,const double y)
+{
+ if (x < y)
+ return(x);
+ return(y);
+}
+
+MagickPrivate void ConvertRGBToHCL(const double red,const double green,
+ const double blue,double *hue,double *chroma,double *luma)
+{
+ double
+ b,
+ c,
+ g,
+ h,
+ max,
+ r;
+
+ /*
+ Convert RGB to HCL colorspace.
+ */
+ assert(hue != (double *) NULL);
+ assert(chroma != (double *) NULL);
+ assert(luma != (double *) NULL);
+ r=red;
+ g=green;
+ b=blue;
+ max=MagickMax(r,MagickMax(g,b));
+ c=max-(double) MagickMin(r,MagickMin(g,b));
+ h=0.0;
+ if (c == 0.0)
+ h=0.0;
+ else
+ if (red == max)
+ h=fmod((g-b)/c+6.0,6.0);
+ else
+ if (green == max)
+ h=((b-r)/c)+2.0;
+ else
+ if (blue == max)
+ h=((r-g)/c)+4.0;
+ *hue=(h/6.0);
+ *chroma=QuantumScale*c;
+ *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C o n v e r t R G B T o H C L p %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertRGBToHCLp() transforms a (red, green, blue) to a (hue, chroma,
+% luma) triple.
+%
+% The format of the ConvertRGBToHCLp method is:
+%
+% void ConvertRGBToHCLp(const double red,const double green,
+% const double blue,double *hue,double *chroma,double *luma)
+%
+% A description of each parameter follows:
+%
+% o red, green, blue: A Quantum value representing the red, green, and
+% blue component of a pixel.
+%
+% o hue, chroma, luma: A pointer to a double value representing a
+% component of the HCL color space.
%
*/
-MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
- const double blackness,double *red,double *green,double *blue)
+MagickPrivate void ConvertRGBToHCLp(const double red,const double green,
+ const double blue,double *hue,double *chroma,double *luma)
{
- MagickRealType
+ double
b,
- f,
+ c,
g,
- n,
- r,
- v;
-
- register ssize_t
- i;
+ h,
+ max,
+ r;
/*
- Convert HWB to RGB colorspace.
+ Convert RGB to HCL colorspace.
*/
- assert(red != (double *) NULL);
- assert(green != (double *) NULL);
- assert(blue != (double *) NULL);
- v=1.0-blackness;
- if (hue == 0.0)
- {
- *red=ClampToQuantum((MagickRealType) QuantumRange*v);
- *green=ClampToQuantum((MagickRealType) QuantumRange*v);
- *blue=ClampToQuantum((MagickRealType) QuantumRange*v);
- return;
- }
- i=(ssize_t) floor(6.0*hue);
- f=6.0*hue-i;
- if ((i & 0x01) != 0)
- f=1.0-f;
- n=whiteness+f*(v-whiteness); /* linear interpolation */
- switch (i)
- {
- default:
- case 6:
- case 0: r=v; g=n; b=whiteness; break;
- case 1: r=n; g=v; b=whiteness; break;
- case 2: r=whiteness; g=v; b=n; break;
- case 3: r=whiteness; g=n; b=v; break;
- case 4: r=n; g=whiteness; b=v; break;
- case 5: r=v; g=whiteness; b=n; break;
- }
- *red=ClampToQuantum((MagickRealType) QuantumRange*r);
- *green=ClampToQuantum((MagickRealType) QuantumRange*g);
- *blue=ClampToQuantum((MagickRealType) QuantumRange*b);
+ assert(hue != (double *) NULL);
+ assert(chroma != (double *) NULL);
+ assert(luma != (double *) NULL);
+ r=red;
+ g=green;
+ b=blue;
+ max=MagickMax(r,MagickMax(g,b));
+ c=max-(double) MagickMin(r,MagickMin(g,b));
+ h=0.0;
+ if (c == 0.0)
+ h=0.0;
+ else
+ if (red == max)
+ h=fmod((g-b)/c+6.0,6.0);
+ else
+ if (green == max)
+ h=((b-r)/c)+2.0;
+ else
+ if (blue == max)
+ h=((r-g)/c)+4.0;
+ *hue=(h/6.0);
+ *chroma=QuantumScale*c;
+ *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
}
\f
/*
MagickPrivate void ConvertRGBToHSB(const double red,const double green,
const double blue,double *hue,double *saturation,double *brightness)
{
- MagickRealType
+ double
+ b,
delta,
+ g,
max,
- min;
+ min,
+ r;
/*
Convert RGB to HSB colorspace.
*hue=0.0;
*saturation=0.0;
*brightness=0.0;
- min=(MagickRealType) (red < green ? red : green);
- if ((MagickRealType) blue < min)
- min=(MagickRealType) blue;
- max=(MagickRealType) (red > green ? red : green);
- if ((MagickRealType) blue > max)
- max=(MagickRealType) blue;
+ r=red;
+ g=green;
+ b=blue;
+ min=r < g ? r : g;
+ if (b < min)
+ min=b;
+ max=r > g ? r : g;
+ if (b > max)
+ max=b;
if (max == 0.0)
return;
delta=max-min;
- *saturation=(double) (delta/max);
- *brightness=(double) (QuantumScale*max);
+ *saturation=delta/max;
+ *brightness=QuantumScale*max;
if (delta == 0.0)
return;
- if ((MagickRealType) red == max)
- *hue=(double) ((green-(MagickRealType) blue)/delta);
+ if (r == max)
+ *hue=(g-b)/delta;
else
- if ((MagickRealType) green == max)
- *hue=(double) (2.0+(blue-(MagickRealType) red)/delta);
+ if (g == max)
+ *hue=2.0+(b-r)/delta;
else
- *hue=(double) (4.0+(red-(MagickRealType) green)/delta);
+ *hue=4.0+(r-g)/delta;
*hue/=6.0;
if (*hue < 0.0)
*hue+=1.0;
% %
% %
% %
+% C o n v e r t R G B T o H S I %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertRGBToHSI() transforms a (red, green, blue) to a (hue, saturation,
+% intensity) triple.
+%
+% The format of the ConvertRGBToHSI method is:
+%
+% void ConvertRGBToHSI(const double red,const double green,
+% const double blue,double *hue,double *saturation,double *intensity)
+%
+% A description of each parameter follows:
+%
+% o red, green, blue: A Quantum value representing the red, green, and
+% blue component of a pixel..
+%
+% o hue, saturation, intensity: A pointer to a double value representing a
+% component of the HSI color space.
+%
+*/
+MagickPrivate void ConvertRGBToHSI(const double red,const double green,
+ const double blue,double *hue,double *saturation,double *intensity)
+{
+ double
+ alpha,
+ beta;
+
+ /*
+ Convert RGB to HSI colorspace.
+ */
+ assert(hue != (double *) NULL);
+ assert(saturation != (double *) NULL);
+ assert(intensity != (double *) NULL);
+ *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;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% C o n v e r t R G B T o H S L %
% %
% %
% component of the HSL color space.
%
*/
-
-static inline double MagickMax(const double x,const double y)
-{
- if (x > y)
- return(x);
- return(y);
-}
-
-static inline double MagickMin(const double x,const double y)
-{
- if (x < y)
- return(x);
- return(y);
-}
-
MagickExport void ConvertRGBToHSL(const double red,const double green,
const double blue,double *hue,double *saturation,double *lightness)
{
- MagickRealType
- b,
- delta,
- g,
+ double
+ c,
max,
- min,
- r;
+ min;
/*
Convert RGB to HSL colorspace.
assert(hue != (double *) NULL);
assert(saturation != (double *) NULL);
assert(lightness != (double *) NULL);
- r=QuantumScale*red;
- g=QuantumScale*green;
- b=QuantumScale*blue;
- max=MagickMax(r,MagickMax(g,b));
- min=MagickMin(r,MagickMin(g,b));
- *lightness=(double) ((min+max)/2.0);
- delta=max-min;
- if (delta == 0.0)
+ max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
+ QuantumScale*blue));
+ min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
+ QuantumScale*blue));
+ c=max-min;
+ *lightness=(max+min)/2.0;
+ if (c <= 0.0)
{
*hue=0.0;
*saturation=0.0;
return;
}
- if (*lightness < 0.5)
- *saturation=(double) (delta/(min+max));
+ if (max == (QuantumScale*red))
+ {
+ *hue=(QuantumScale*green-QuantumScale*blue)/c;
+ if ((QuantumScale*green) < (QuantumScale*blue))
+ *hue+=6.0;
+ }
else
- *saturation=(double) (delta/(2.0-max-min));
- if (r == max)
- *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
+ 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;
+ if (*lightness <= 0.5)
+ *saturation=c/(2.0*(*lightness));
else
- if (g == max)
- *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
- delta;
+ *saturation=c/(2.0-2.0*(*lightness));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C o n v e r t R G B T o H S V %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertRGBToHSV() transforms a (red, green, blue) to a (hue, saturation,
+% value) triple.
+%
+% The format of the ConvertRGBToHSV method is:
+%
+% void ConvertRGBToHSV(const double red,const double green,
+% const double blue,double *hue,double *saturation,double *value)
+%
+% A description of each parameter follows:
+%
+% o red, green, blue: A Quantum value representing the red, green, and
+% blue component of a pixel..
+%
+% o hue, saturation, value: A pointer to a double value representing a
+% component of the HSV color space.
+%
+*/
+MagickPrivate void ConvertRGBToHSV(const double red,const double green,
+ const double blue,double *hue,double *saturation,double *value)
+{
+ double
+ c,
+ max,
+ min;
+
+ /*
+ Convert RGB to HSV colorspace.
+ */
+ assert(hue != (double *) NULL);
+ assert(saturation != (double *) NULL);
+ assert(value != (double *) NULL);
+ 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
- if (b == max)
- *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
- (delta/2.0)))/delta;
- if (*hue < 0.0)
- *hue+=1.0;
- if (*hue > 1.0)
- *hue-=1.0;
+ *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
+ *hue*=60.0/360.0;
+ *saturation=c/max;
}
\f
/*
MagickPrivate void ConvertRGBToHWB(const double red,const double green,
const double blue,double *hue,double *whiteness,double *blackness)
{
- long
- i;
-
- MagickRealType
+ double
+ b,
f,
+ g,
+ p,
+ r,
v,
w;
assert(hue != (double *) NULL);
assert(whiteness != (double *) NULL);
assert(blackness != (double *) NULL);
- w=(MagickRealType) MagickMin((double) red,MagickMin((double) green,(double)
- blue));
- v=(MagickRealType) MagickMax((double) red,MagickMax((double) green,(double)
- blue));
+ r=red;
+ g=green;
+ b=blue;
+ w=MagickMin(r,MagickMin(g,b));
+ v=MagickMax(r,MagickMax(g,b));
*blackness=1.0-QuantumScale*v;
*whiteness=QuantumScale*w;
if (v == w)
{
- *hue=0.0;
+ *hue=(-1.0);
return;
}
- f=((MagickRealType) red == w) ? green-(MagickRealType) blue :
- (((MagickRealType) green == w) ? blue-(MagickRealType) red : red-
- (MagickRealType) green);
- i=((MagickRealType) red == w) ? 3 : (((MagickRealType) green == w) ? 5 : 1);
- *hue=((double) i-f/(v-1.0*w))/6.0;
+ f=(r == w) ? g-b : ((g == w) ? b-r : r-g);
+ p=(r == w) ? 3.0 : ((g == w) ? 5.0 : 1.0);
+ *hue=(p-f/(v-1.0*w))/6.0;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C o n v e r t R G B T o L C H a b %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertRGBToLCHab() transforms a (red, green, blue) to a (luma, chroma,
+% hue) triple.
+%
+% The format of the ConvertRGBToLCHab method is:
+%
+% void ConvertRGBToLCHab(const double red,const double green,
+% const double blue,double *luma,double *chroma,double *hue)
+%
+% A description of each parameter follows:
+%
+% o red, green, blue: A Quantum value representing the red, green, and
+% blue component of a pixel.
+%
+% o luma, chroma, hue: A pointer to a double value representing a
+% component of the LCH color space.
+%
+*/
+
+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+0.5;
+ if (*hue < 0.0)
+ *hue+=1.0;
+}
+
+MagickPrivate void ConvertRGBToLCHab(const double red,const double green,
+ const double blue,double *luma,double *chroma,double *hue)
+{
+ double
+ X,
+ Y,
+ Z;
+
+ /*
+ Convert RGB to LCHab colorspace.
+ */
+ assert(luma != (double *) NULL);
+ assert(chroma != (double *) NULL);
+ assert(hue != (double *) NULL);
+ ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+ ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C o n v e r t R G B T o L C H u v %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ConvertRGBToLCHuv() transforms a (red, green, blue) to a (luma, chroma,
+% hue) triple.
+%
+% The format of the ConvertRGBToLCHuv method is:
+%
+% void ConvertRGBToLCHuv(const double red,const double green,
+% const double blue,double *luma,double *chroma,double *hue)
+%
+% A description of each parameter follows:
+%
+% o red, green, blue: A Quantum value representing the red, green, and
+% blue component of a pixel.
+%
+% o luma, chroma, hue: A pointer to a double value representing a
+% component of the LCHuv color space.
+%
+*/
+
+static inline void ConvertXYZToLCHuv(const double X,const double Y,
+ const double Z,double *luma,double *chroma,double *hue)
+{
+ double
+ u,
+ v;
+
+ ConvertXYZToLuv(X,Y,Z,luma,&u,&v);
+ *chroma=hypot(354.0*u-134.0,262.0*v-140.0)/255.0+0.5;
+ *hue=180.0*atan2(262.0*v-140.0,354.0*u-134.0)/MagickPI/360.0+0.5;
+ if (*hue < 0.0)
+ *hue+=1.0;
+}
+
+MagickPrivate void ConvertRGBToLCHuv(const double red,const double green,
+ const double blue,double *luma,double *chroma,double *hue)
+{
+ double
+ X,
+ Y,
+ Z;
+
+ /*
+ Convert RGB to LCHuv colorspace.
+ */
+ assert(luma != (double *) NULL);
+ assert(chroma != (double *) NULL);
+ assert(hue != (double *) NULL);
+ ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+ ConvertXYZToLCHuv(X,Y,Z,luma,chroma,hue);
}
\f
/*
%
% A description of each parameter follows:
%
-% o expansion: Method ExpandAffine returns the affine's expansion factor.
+% o expansion: ExpandAffine returns the affine's expansion factor.
%
% o affine: A pointer the affine transform of type AffineMatrix.
%
% The format of the GenerateDifferentialNoise method is:
%
% double GenerateDifferentialNoise(RandomInfo *random_info,
-% const Quantum pixel,const NoiseType noise_type,
-% const MagickRealType attenuate)
+% const Quantum pixel,const NoiseType noise_type,const double attenuate)
%
% A description of each parameter follows:
%
%
*/
MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
- const Quantum pixel,const NoiseType noise_type,const MagickRealType attenuate)
+ const Quantum pixel,const NoiseType noise_type,const double attenuate)
{
-#define NoiseEpsilon (attenuate*1.0e-5)
-#define SigmaUniform (attenuate*4.0)
-#define SigmaGaussian (attenuate*4.0)
-#define SigmaImpulse (attenuate*0.10)
-#define SigmaLaplacian (attenuate*10.0)
-#define SigmaMultiplicativeGaussian (attenuate*1.0)
-#define SigmaPoisson (attenuate*0.05)
-#define TauGaussian (attenuate*20.0)
+#define SigmaUniform (attenuate*0.015625)
+#define SigmaGaussian (attenuate*0.015625)
+#define SigmaImpulse (attenuate*0.1)
+#define SigmaLaplacian (attenuate*0.0390625)
+#define SigmaMultiplicativeGaussian (attenuate*0.5)
+#define SigmaPoisson (attenuate*12.5)
+#define SigmaRandom (attenuate)
+#define TauGaussian (attenuate*0.078125)
double
alpha,
case UniformNoise:
default:
{
- noise=(double) pixel+ScaleCharToQuantum((unsigned char)
- (SigmaUniform*(alpha)));
+ noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
break;
}
case GaussianNoise:
gamma=sqrt(-2.0*log(alpha));
sigma=gamma*cos((double) (2.0*MagickPI*beta));
tau=gamma*sin((double) (2.0*MagickPI*beta));
- noise=(double) pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
- TauGaussian*tau;
- break;
- }
- case MultiplicativeGaussianNoise:
- {
- if (alpha <= NoiseEpsilon)
- sigma=(double) QuantumRange;
- else
- sigma=sqrt(-2.0*log(alpha));
- beta=GetPseudoRandomValue(random_info);
- noise=(double) pixel+pixel*SigmaMultiplicativeGaussian*sigma/2.0*
- cos((double) (2.0*MagickPI*beta));
+ noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
+ QuantumRange*TauGaussian*tau);
break;
}
case ImpulseNoise:
{
if (alpha < (SigmaImpulse/2.0))
noise=0.0;
- else
- if (alpha >= (1.0-(SigmaImpulse/2.0)))
- noise=(double) QuantumRange;
- else
- noise=(double) pixel;
+ else
+ if (alpha >= (1.0-(SigmaImpulse/2.0)))
+ noise=(double) QuantumRange;
+ else
+ noise=(double) pixel;
break;
}
case LaplacianNoise:
{
if (alpha <= 0.5)
{
- if (alpha <= NoiseEpsilon)
- noise=(double) pixel-(double) QuantumRange;
+ if (alpha <= MagickEpsilon)
+ noise=(double) (pixel-QuantumRange);
else
- noise=(double) pixel+ScaleCharToQuantum((unsigned char)
- (SigmaLaplacian*log((2.0*alpha))+0.5));
+ noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
+ 0.5);
break;
}
beta=1.0-alpha;
- if (beta <= (0.5*NoiseEpsilon))
+ if (beta <= (0.5*MagickEpsilon))
noise=(double) (pixel+QuantumRange);
else
- noise=(double) pixel-ScaleCharToQuantum((unsigned char)
- (SigmaLaplacian*log((2.0*beta))+0.5));
+ noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
+ break;
+ }
+ case MultiplicativeGaussianNoise:
+ {
+ sigma=1.0;
+ if (alpha > MagickEpsilon)
+ sigma=sqrt(-2.0*log(alpha));
+ beta=GetPseudoRandomValue(random_info);
+ noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
+ cos((double) (2.0*MagickPI*beta))/2.0);
break;
}
case PoissonNoise:
register ssize_t
i;
- poisson=exp(-SigmaPoisson*ScaleQuantumToChar(pixel));
+ poisson=exp(-SigmaPoisson*QuantumScale*pixel);
for (i=0; alpha > poisson; i++)
{
beta=GetPseudoRandomValue(random_info);
alpha*=beta;
}
- noise=(double) ScaleCharToQuantum((unsigned char) (i/SigmaPoisson));
+ noise=(double) (QuantumRange*i/SigmaPoisson);
break;
}
case RandomNoise:
{
- noise=(double) QuantumRange*alpha;
+ noise=(double) (QuantumRange*SigmaRandom*alpha);
break;
}
}
%
% A description of each parameter follows:
%
-% o width: Method GetOptimalKernelWidth returns the optimal width of
-% a convolution kernel.
+% o width: GetOptimalKernelWidth returns the optimal width of a
+% convolution kernel.
%
% o radius: the radius of the Gaussian, in pixels, not counting the center
% pixel.
gamma=fabs(sigma);
if (gamma <= MagickEpsilon)
return(3UL);
- alpha=1.0/(2.0*gamma*gamma);
- beta=(double) (1.0/(MagickSQ2PI*gamma));
+ alpha=PerceptibleReciprocal(2.0*gamma*gamma);
+ beta=(double) PerceptibleReciprocal((double) MagickSQ2PI*gamma);
for (width=5; ; )
{
normalize=0.0;
- j=(ssize_t) width/2;
+ j=(ssize_t) (width-1)/2;
for (i=(-j); i <= j; i++)
normalize+=exp(-((double) (i*i))*alpha)*beta;
value=exp(-((double) (j*j))*alpha)*beta/normalize;
gamma=fabs(sigma);
if (gamma <= MagickEpsilon)
return(3UL);
- alpha=1.0/(2.0*gamma*gamma);
- beta=(double) (1.0/(Magick2PI*gamma*gamma));
+ alpha=PerceptibleReciprocal(2.0*gamma*gamma);
+ beta=(double) PerceptibleReciprocal((double) Magick2PI*gamma*gamma);
for (width=5; ; )
{
normalize=0.0;
- j=(ssize_t) width/2;
+ j=(ssize_t) (width-1)/2;
for (v=(-j); v <= j; v++)
for (u=(-j); u <= j; u++)
normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;