| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % GGGG EEEEE M M % |
| % G E MM MM % |
| % G GG EEE M M M % |
| % G G E M M % |
| % GGGG EEEEE M M % |
| % % |
| % % |
| % Graphic Gems - Graphic Support Methods % |
| % % |
| % Software Design % |
| % John Cristy % |
| % August 1996 % |
| % % |
| % % |
| % 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 % |
| % obtain a copy of the License at % |
| % % |
| % http://www.imagemagick.org/script/license.php % |
| % % |
| % Unless required by applicable law or agreed to in writing, software % |
| % distributed under the License is distributed on an "AS IS" BASIS, % |
| % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
| % See the License for the specific language governing permissions and % |
| % limitations under the License. % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % |
| % |
| */ |
| |
| /* |
| Include declarations. |
| */ |
| #include "MagickCore/studio.h" |
| #include "MagickCore/color-private.h" |
| #include "MagickCore/draw.h" |
| #include "MagickCore/gem.h" |
| #include "MagickCore/gem-private.h" |
| #include "MagickCore/image.h" |
| #include "MagickCore/image-private.h" |
| #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" |
| #include "MagickCore/resize.h" |
| #include "MagickCore/transform.h" |
| #include "MagickCore/signature-private.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.298839f*r+0.586811f*g+0.114350f*b); |
| *red=QuantumRange*(r+m); |
| *green=QuantumRange*(g+m); |
| *blue=QuantumRange*(b+m); |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % C o n v e r t H S B T o R G B % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red, |
| % green, blue) triple. |
| % |
| % The format of the ConvertHSBToRGBImage method is: |
| % |
| % void ConvertHSBToRGB(const double hue,const double saturation, |
| % const double brightness,double *red,double *green,double *blue) |
| % |
| % A description of each parameter follows: |
| % |
| % o hue, saturation, brightness: A double value representing a |
| % component of the HSB color space. |
| % |
| % o red, green, blue: A pointer to a pixel component of type Quantum. |
| % |
| */ |
| MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation, |
| const double brightness,double *red,double *green,double *blue) |
| { |
| double |
| f, |
| h, |
| p, |
| q, |
| t; |
| |
| /* |
| Convert HSB to RGB colorspace. |
| */ |
| assert(red != (double *) NULL); |
| assert(green != (double *) NULL); |
| assert(blue != (double *) NULL); |
| if (saturation == 0.0) |
| { |
| *red=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=QuantumRange*brightness; |
| *green=QuantumRange*t; |
| *blue=QuantumRange*p; |
| break; |
| } |
| case 1: |
| { |
| *red=QuantumRange*q; |
| *green=QuantumRange*brightness; |
| *blue=QuantumRange*p; |
| break; |
| } |
| case 2: |
| { |
| *red=QuantumRange*p; |
| *green=QuantumRange*brightness; |
| *blue=QuantumRange*t; |
| break; |
| } |
| case 3: |
| { |
| *red=QuantumRange*p; |
| *green=QuantumRange*q; |
| *blue=QuantumRange*brightness; |
| break; |
| } |
| case 4: |
| { |
| *red=QuantumRange*t; |
| *green=QuantumRange*p; |
| *blue=QuantumRange*brightness; |
| break; |
| } |
| case 5: |
| { |
| *red=QuantumRange*brightness; |
| *green=QuantumRange*p; |
| *blue=QuantumRange*q; |
| break; |
| } |
| } |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % C o n v e r t H S L T o R G B % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red, |
| % green, blue) triple. |
| % |
| % The format of the ConvertHSLToRGBImage method is: |
| % |
| % void ConvertHSLToRGB(const double hue,const double saturation, |
| % const double lightness,double *red,double *green,double *blue) |
| % |
| % A description of each parameter follows: |
| % |
| % o hue, saturation, lightness: A double value representing a |
| % component of the HSL color space. |
| % |
| % o red, green, blue: A pointer to a pixel component of type Quantum. |
| % |
| */ |
| |
| static inline double ConvertHueToRGB(double m1,double m2,double 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) |
| { |
| double |
| b, |
| g, |
| r, |
| m1, |
| m2; |
| |
| /* |
| Convert HSL to RGB colorspace. |
| */ |
| assert(red != (double *) NULL); |
| assert(green != (double *) NULL); |
| assert(blue != (double *) NULL); |
| if (saturation == 0) |
| { |
| *red=QuantumRange*lightness; |
| *green=(*red); |
| *blue=(*red); |
| return; |
| } |
| 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=QuantumRange*r; |
| *green=QuantumRange*g; |
| *blue=QuantumRange*b; |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % C o n v e r t H W B T o R G B % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green, |
| % blue) triple. |
| % |
| % The format of the ConvertHWBToRGBImage method is: |
| % |
| % void ConvertHWBToRGB(const double hue,const double whiteness, |
| % const double blackness,double *red,double *green,double *blue) |
| % |
| % A description of each parameter follows: |
| % |
| % 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. |
| % |
| */ |
| 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; |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % 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.298839f*r+0.586811f*g+0.114350f*b); |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % C o n v e r t R G B T o H S B % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation, |
| % brightness) triple. |
| % |
| % The format of the ConvertRGBToHSB method is: |
| % |
| % void ConvertRGBToHSB(const double red,const double green, |
| % const double blue,double *hue,double *saturation,double *brightness) |
| % |
| % 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, brightness: A pointer to a double value representing a |
| % component of the HSB color space. |
| % |
| */ |
| MagickPrivate void ConvertRGBToHSB(const double red,const double green, |
| const double blue,double *hue,double *saturation,double *brightness) |
| { |
| double |
| b, |
| delta, |
| g, |
| max, |
| min, |
| r; |
| |
| /* |
| Convert RGB to HSB colorspace. |
| */ |
| assert(hue != (double *) NULL); |
| assert(saturation != (double *) NULL); |
| assert(brightness != (double *) NULL); |
| *hue=0.0; |
| *saturation=0.0; |
| *brightness=0.0; |
| 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=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; |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % C o n v e r t R G B T o H S L % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation, |
| % lightness) triple. |
| % |
| % The format of the ConvertRGBToHSL method is: |
| % |
| % void ConvertRGBToHSL(const double red,const double green, |
| % const double blue,double *hue,double *saturation,double *lightness) |
| % |
| % 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, lightness: A pointer to a double value representing a |
| % component of the HSL color space. |
| % |
| */ |
| MagickExport void ConvertRGBToHSL(const double red,const double green, |
| const double blue,double *hue,double *saturation,double *lightness) |
| { |
| double |
| b, |
| delta, |
| g, |
| max, |
| min, |
| r; |
| |
| /* |
| 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) |
| { |
| *hue=0.0; |
| *saturation=0.0; |
| return; |
| } |
| if (*lightness < 0.5) |
| *saturation=(double) (delta/(min+max)); |
| 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; |
| else |
| if (g == max) |
| *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/ |
| delta; |
| 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; |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % C o n v e r t R G B T o H W B % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness, |
| % blackness) triple. |
| % |
| % The format of the ConvertRGBToHWB method is: |
| % |
| % void ConvertRGBToHWB(const double red,const double green, |
| % const double blue,double *hue,double *whiteness,double *blackness) |
| % |
| % 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, whiteness, blackness: A pointer to a double value representing a |
| % component of the HWB color space. |
| % |
| */ |
| MagickPrivate void ConvertRGBToHWB(const double red,const double green, |
| const double blue,double *hue,double *whiteness,double *blackness) |
| { |
| double |
| b, |
| f, |
| g, |
| p, |
| r, |
| v, |
| w; |
| |
| /* |
| Convert RGB to HWB colorspace. |
| */ |
| assert(hue != (double *) NULL); |
| assert(whiteness != (double *) NULL); |
| assert(blackness != (double *) NULL); |
| 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=(-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; |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % E x p a n d A f f i n e % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % ExpandAffine() computes the affine's expansion factor, i.e. the square root |
| % of the factor by which the affine transform affects area. In an affine |
| % transform composed of scaling, rotation, shearing, and translation, returns |
| % the amount of scaling. |
| % |
| % The format of the ExpandAffine method is: |
| % |
| % double ExpandAffine(const AffineMatrix *affine) |
| % |
| % A description of each parameter follows: |
| % |
| % o expansion: Method ExpandAffine returns the affine's expansion factor. |
| % |
| % o affine: A pointer the affine transform of type AffineMatrix. |
| % |
| */ |
| MagickExport double ExpandAffine(const AffineMatrix *affine) |
| { |
| assert(affine != (const AffineMatrix *) NULL); |
| return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry))); |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % G e n e r a t e D i f f e r e n t i a l N o i s e % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % GenerateDifferentialNoise() generates differentual noise. |
| % |
| % The format of the GenerateDifferentialNoise method is: |
| % |
| % double GenerateDifferentialNoise(RandomInfo *random_info, |
| % const Quantum pixel,const NoiseType noise_type,const double attenuate) |
| % |
| % A description of each parameter follows: |
| % |
| % o random_info: the random info. |
| % |
| % o pixel: noise is relative to this pixel value. |
| % |
| % o noise_type: the type of noise. |
| % |
| % o attenuate: attenuate the noise. |
| % |
| */ |
| MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info, |
| const Quantum pixel,const NoiseType noise_type,const double 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); |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % G e t O p t i m a l K e r n e l W i d t h % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % GetOptimalKernelWidth() computes the optimal kernel radius for a convolution |
| % filter. Start with the minimum value of 3 pixels and walk out until we drop |
| % below the threshold of one pixel numerical accuracy. |
| % |
| % The format of the GetOptimalKernelWidth method is: |
| % |
| % size_t GetOptimalKernelWidth(const double radius, |
| % const double sigma) |
| % |
| % A description of each parameter follows: |
| % |
| % o width: Method GetOptimalKernelWidth returns the optimal width of |
| % a convolution kernel. |
| % |
| % o radius: the radius of the Gaussian, in pixels, not counting the center |
| % pixel. |
| % |
| % o sigma: the standard deviation of the Gaussian, in pixels. |
| % |
| */ |
| MagickPrivate 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)); |
| } |
| |
| MagickPrivate 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)); |
| } |
| |
| MagickPrivate size_t GetOptimalKernelWidth(const double radius, |
| const double sigma) |
| { |
| return(GetOptimalKernelWidth1D(radius,sigma)); |
| } |