This source file includes following definitions.
- ConvertHCLToRGB
- ConvertHCLpToRGB
- ConvertHSBToRGB
- ConvertHSIToRGB
- ConvertHSLToRGB
- ConvertHSVToRGB
- ConvertHWBToRGB
- ConvertLCHabToXYZ
- ConvertLCHabToRGB
- ConvertLCHuvToXYZ
- ConvertLCHuvToRGB
- ConvertRGBToHCL
- ConvertRGBToHCLp
- ConvertRGBToHSB
- ConvertRGBToHSI
- ConvertRGBToHSL
- ConvertRGBToHSV
- ConvertRGBToHWB
- ConvertXYZToLCHab
- ConvertRGBToLCHab
- ConvertXYZToLCHuv
- ConvertRGBToLCHuv
- ExpandAffine
- GenerateDifferentialNoise
- GetOptimalKernelWidth1D
- GetOptimalKernelWidth2D
- GetOptimalKernelWidth
#include "magick/studio.h"
#include "magick/color-private.h"
#include "magick/draw.h"
#include "magick/gem.h"
#include "magick/gem-private.h"
#include "magick/image.h"
#include "magick/image-private.h"
#include "magick/log.h"
#include "magick/memory_.h"
#include "magick/pixel-private.h"
#include "magick/quantum.h"
#include "magick/random_.h"
#include "magick/resize.h"
#include "magick/transform.h"
#include "magick/signature-private.h"
MagickExport void ConvertHCLToRGB(const double hue,const double chroma,
const double luma,Quantum *red,Quantum *green,Quantum *blue)
{
double
b,
c,
g,
h,
m,
r,
x;
assert(red != (Quantum *) NULL);
assert(green != (Quantum *) NULL);
assert(blue != (Quantum *) 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=ClampToQuantum(QuantumRange*(r+m));
*green=ClampToQuantum(QuantumRange*(g+m));
*blue=ClampToQuantum(QuantumRange*(b+m));
}
MagickExport void ConvertHCLpToRGB(const double hue,const double chroma,
const double luma,Quantum *red,Quantum *green,Quantum *blue)
{
double
b,
c,
g,
h,
m,
r,
x,
z;
assert(red != (Quantum *) NULL);
assert(green != (Quantum *) NULL);
assert(blue != (Quantum *) 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=ClampToQuantum(QuantumRange*(z*r+m));
*green=ClampToQuantum(QuantumRange*(z*g+m));
*blue=ClampToQuantum(QuantumRange*(z*b+m));
}
MagickExport void ConvertHSBToRGB(const double hue,const double saturation,
const double brightness,Quantum *red,Quantum *green,Quantum *blue)
{
double
f,
h,
p,
q,
t;
assert(red != (Quantum *) NULL);
assert(green != (Quantum *) NULL);
assert(blue != (Quantum *) NULL);
if (saturation == 0.0)
{
*red=ClampToQuantum(QuantumRange*brightness);
*green=(*red);
*blue=(*red);
return;
}
h=6.0*(hue-floor(hue));
f=h-floor((double) h);
p=brightness*(1.0-saturation);
q=brightness*(1.0-saturation*f);
t=brightness*(1.0-(saturation*(1.0-f)));
switch ((int) h)
{
case 0:
default:
{
*red=ClampToQuantum(QuantumRange*brightness);
*green=ClampToQuantum(QuantumRange*t);
*blue=ClampToQuantum(QuantumRange*p);
break;
}
case 1:
{
*red=ClampToQuantum(QuantumRange*q);
*green=ClampToQuantum(QuantumRange*brightness);
*blue=ClampToQuantum(QuantumRange*p);
break;
}
case 2:
{
*red=ClampToQuantum(QuantumRange*p);
*green=ClampToQuantum(QuantumRange*brightness);
*blue=ClampToQuantum(QuantumRange*t);
break;
}
case 3:
{
*red=ClampToQuantum(QuantumRange*p);
*green=ClampToQuantum(QuantumRange*q);
*blue=ClampToQuantum(QuantumRange*brightness);
break;
}
case 4:
{
*red=ClampToQuantum(QuantumRange*t);
*green=ClampToQuantum(QuantumRange*p);
*blue=ClampToQuantum(QuantumRange*brightness);
break;
}
case 5:
{
*red=ClampToQuantum(QuantumRange*brightness);
*green=ClampToQuantum(QuantumRange*p);
*blue=ClampToQuantum(QuantumRange*q);
break;
}
}
}
MagickExport void ConvertHSIToRGB(const double hue,const double saturation,
const double intensity,Quantum *red,Quantum *green,Quantum *blue)
{
double
b,
g,
h,
r;
assert(red != (Quantum *) NULL);
assert(green != (Quantum *) NULL);
assert(blue != (Quantum *) 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=ClampToQuantum(QuantumRange*r);
*green=ClampToQuantum(QuantumRange*g);
*blue=ClampToQuantum(QuantumRange*b);
}
MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
const double lightness,Quantum *red,Quantum *green,Quantum *blue)
{
double
b,
c,
g,
h,
min,
r,
x;
assert(red != (Quantum *) NULL);
assert(green != (Quantum *) NULL);
assert(blue != (Quantum *) NULL);
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:
{
r=min+c;
g=min+x;
b=min;
break;
}
case 1:
{
r=min+x;
g=min+c;
b=min;
break;
}
case 2:
{
r=min;
g=min+c;
b=min+x;
break;
}
case 3:
{
r=min;
g=min+x;
b=min+c;
break;
}
case 4:
{
r=min+x;
g=min;
b=min+c;
break;
}
case 5:
{
r=min+c;
g=min;
b=min+x;
break;
}
default:
{
r=0.0;
g=0.0;
b=0.0;
}
}
*red=ClampToQuantum(QuantumRange*r);
*green=ClampToQuantum(QuantumRange*g);
*blue=ClampToQuantum(QuantumRange*b);
}
MagickExport void ConvertHSVToRGB(const double hue,const double saturation,
const double value,Quantum *red,Quantum *green,Quantum *blue)
{
double
b,
c,
g,
h,
min,
r,
x;
assert(red != (Quantum *) NULL);
assert(green != (Quantum *) NULL);
assert(blue != (Quantum *) 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:
{
r=min+c;
g=min+x;
b=min;
break;
}
case 1:
{
r=min+x;
g=min+c;
b=min;
break;
}
case 2:
{
r=min;
g=min+c;
b=min+x;
break;
}
case 3:
{
r=min;
g=min+x;
b=min+c;
break;
}
case 4:
{
r=min+x;
g=min;
b=min+c;
break;
}
case 5:
{
r=min+c;
g=min;
b=min+x;
break;
}
default:
{
r=0.0;
g=0.0;
b=0.0;
}
}
*red=ClampToQuantum(QuantumRange*r);
*green=ClampToQuantum(QuantumRange*g);
*blue=ClampToQuantum(QuantumRange*b);
}
MagickExport void ConvertHWBToRGB(const double hue,const double whiteness,
const double blackness,Quantum *red,Quantum *green,Quantum *blue)
{
double
b,
f,
g,
n,
r,
v;
register ssize_t
i;
assert(red != (Quantum *) NULL);
assert(green != (Quantum *) NULL);
assert(blue != (Quantum *) NULL);
v=1.0-blackness;
if (hue == -1.0)
{
*red=ClampToQuantum(QuantumRange*v);
*green=ClampToQuantum(QuantumRange*v);
*blue=ClampToQuantum(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);
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(QuantumRange*r);
*green=ClampToQuantum(QuantumRange*g);
*blue=ClampToQuantum(QuantumRange*b);
}
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);
}
MagickExport void ConvertLCHabToRGB(const double luma,const double chroma,
const double hue,Quantum *red,Quantum *green,Quantum *blue)
{
double
X,
Y,
Z;
assert(red != (Quantum *) NULL);
assert(green != (Quantum *) NULL);
assert(blue != (Quantum *) NULL);
ConvertLCHabToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z);
ConvertXYZToRGB(X,Y,Z,red,green,blue);
}
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);
}
MagickExport void ConvertLCHuvToRGB(const double luma,const double chroma,
const double hue,Quantum *red,Quantum *green,Quantum *blue)
{
double
X,
Y,
Z;
assert(red != (Quantum *) NULL);
assert(green != (Quantum *) NULL);
assert(blue != (Quantum *) NULL);
ConvertLCHuvToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z);
ConvertXYZToRGB(X,Y,Z,red,green,blue);
}
MagickExport void ConvertRGBToHCL(const Quantum red,const Quantum green,
const Quantum blue,double *hue,double *chroma,double *luma)
{
double
b,
c,
g,
h,
max,
r;
assert(hue != (double *) NULL);
assert(chroma != (double *) NULL);
assert(luma != (double *) NULL);
r=(double) red;
g=(double) green;
b=(double) 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 == (Quantum) max)
h=fmod((g-b)/c+6.0,6.0);
else
if (green == (Quantum) max)
h=((b-r)/c)+2.0;
else
if (blue == (Quantum) 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);
}
MagickExport void ConvertRGBToHCLp(const Quantum red,const Quantum green,
const Quantum blue,double *hue,double *chroma,double *luma)
{
double
b,
c,
g,
h,
max,
r;
assert(hue != (double *) NULL);
assert(chroma != (double *) NULL);
assert(luma != (double *) NULL);
r=(double) red;
g=(double) green;
b=(double) 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 == (Quantum) max)
h=fmod((g-b)/c+6.0,6.0);
else
if (green == (Quantum) max)
h=((b-r)/c)+2.0;
else
if (blue == (Quantum) 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);
}
MagickExport void ConvertRGBToHSB(const Quantum red,const Quantum green,
const Quantum blue,double *hue,double *saturation,double *brightness)
{
double
b,
delta,
g,
max,
min,
r;
assert(hue != (double *) NULL);
assert(saturation != (double *) NULL);
assert(brightness != (double *) NULL);
*hue=0.0;
*saturation=0.0;
*brightness=0.0;
r=(double) red;
g=(double) green;
b=(double) 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=delta/max;
*brightness=QuantumScale*max;
if (delta == 0.0)
return;
if (r == max)
*hue=(g-b)/delta;
else
if (g == max)
*hue=2.0+(b-r)/delta;
else
*hue=4.0+(r-g)/delta;
*hue/=6.0;
if (*hue < 0.0)
*hue+=1.0;
}
MagickExport void ConvertRGBToHSI(const Quantum red,const Quantum green,
const Quantum blue,double *hue,double *saturation,double *intensity)
{
double
alpha,
beta;
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;
}
MagickExport void ConvertRGBToHSL(const Quantum red,const Quantum green,
const Quantum blue,double *hue,double *saturation,double *lightness)
{
double
c,
max,
min;
assert(hue != (double *) NULL);
assert(saturation != (double *) NULL);
assert(lightness != (double *) NULL);
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 (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;
if (*lightness <= 0.5)
*saturation=c/(2.0*(*lightness));
else
*saturation=c/(2.0-2.0*(*lightness));
}
MagickExport void ConvertRGBToHSV(const Quantum red,const Quantum green,
const Quantum blue,double *hue,double *saturation,double *value)
{
double
c,
max,
min;
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
*hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
*hue*=60.0/360.0;
*saturation=c/max;
}
MagickExport void ConvertRGBToHWB(const Quantum red,const Quantum green,
const Quantum blue,double *hue,double *whiteness,double *blackness)
{
double
b,
f,
g,
p,
r,
v,
w;
assert(hue != (double *) NULL);
assert(whiteness != (double *) NULL);
assert(blackness != (double *) NULL);
r=(double) red;
g=(double) green;
b=(double) 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=(-1.0);
return;
}
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;
}
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;
}
MagickExport void ConvertRGBToLCHab(const Quantum red,const Quantum green,
const Quantum blue,double *luma,double *chroma,double *hue)
{
double
X,
Y,
Z;
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);
}
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;
if (*hue < 0.0)
*hue+=1.0;
}
MagickExport void ConvertRGBToLCHuv(const Quantum red,const Quantum green,
const Quantum blue,double *luma,double *chroma,double *hue)
{
double
X,
Y,
Z;
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);
}
MagickExport double ExpandAffine(const AffineMatrix *affine)
{
assert(affine != (const AffineMatrix *) NULL);
return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
}
MagickExport double GenerateDifferentialNoise(RandomInfo *random_info,
const Quantum pixel,const NoiseType noise_type,const MagickRealType attenuate)
{
#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,
beta,
noise,
sigma;
alpha=GetPseudoRandomValue(random_info);
switch (noise_type)
{
case UniformNoise:
default:
{
noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
break;
}
case GaussianNoise:
{
double
gamma,
tau;
if (alpha == 0.0)
alpha=1.0;
beta=GetPseudoRandomValue(random_info);
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+
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;
break;
}
case LaplacianNoise:
{
if (alpha <= 0.5)
{
if (alpha <= MagickEpsilon)
noise=(double) (pixel-QuantumRange);
else
noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
0.5);
break;
}
beta=1.0-alpha;
if (beta <= (0.5*MagickEpsilon))
noise=(double) (pixel+QuantumRange);
else
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:
{
double
poisson;
register ssize_t
i;
poisson=exp(-SigmaPoisson*QuantumScale*pixel);
for (i=0; alpha > poisson; i++)
{
beta=GetPseudoRandomValue(random_info);
alpha*=beta;
}
noise=(double) (QuantumRange*i/SigmaPoisson);
break;
}
case RandomNoise:
{
noise=(double) (QuantumRange*SigmaRandom*alpha);
break;
}
}
return(noise);
}
MagickExport size_t GetOptimalKernelWidth1D(const double radius,
const double sigma)
{
double
alpha,
beta,
gamma,
normalize,
value;
register ssize_t
i;
size_t
width;
ssize_t
j;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
if (radius > MagickEpsilon)
return((size_t) (2.0*ceil(radius)+1.0));
gamma=fabs(sigma);
if (gamma <= MagickEpsilon)
return(3UL);
alpha=PerceptibleReciprocal(2.0*gamma*gamma);
beta=(double) PerceptibleReciprocal((double) MagickSQ2PI*gamma);
for (width=5; ; )
{
normalize=0.0;
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;
if ((value < QuantumScale) || (value < MagickEpsilon))
break;
width+=2;
}
return((size_t) (width-2));
}
MagickExport size_t GetOptimalKernelWidth2D(const double radius,
const double sigma)
{
double
alpha,
beta,
gamma,
normalize,
value;
size_t
width;
ssize_t
j,
u,
v;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
if (radius > MagickEpsilon)
return((size_t) (2.0*ceil(radius)+1.0));
gamma=fabs(sigma);
if (gamma <= MagickEpsilon)
return(3UL);
alpha=PerceptibleReciprocal(2.0*gamma*gamma);
beta=(double) PerceptibleReciprocal((double) Magick2PI*gamma*gamma);
for (width=5; ; )
{
normalize=0.0;
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;
value=exp(-((double) (j*j))*alpha)*beta/normalize;
if ((value < QuantumScale) || (value < MagickEpsilon))
break;
width+=2;
}
return((size_t) (width-2));
}
MagickExport size_t GetOptimalKernelWidth(const double radius,
const double sigma)
{
return(GetOptimalKernelWidth1D(radius,sigma));
}