2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Graphic Gems - Graphic Support Methods %
20 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/color-private.h"
45 #include "MagickCore/draw.h"
46 #include "MagickCore/gem.h"
47 #include "MagickCore/gem-private.h"
48 #include "MagickCore/image.h"
49 #include "MagickCore/image-private.h"
50 #include "MagickCore/log.h"
51 #include "MagickCore/memory_.h"
52 #include "MagickCore/pixel-accessor.h"
53 #include "MagickCore/quantum.h"
54 #include "MagickCore/quantum-private.h"
55 #include "MagickCore/random_.h"
56 #include "MagickCore/resize.h"
57 #include "MagickCore/transform.h"
58 #include "MagickCore/signature-private.h"
61 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65 % C o n v e r t H S B T o R G B %
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 % ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
72 % green, blue) triple.
74 % The format of the ConvertHSBToRGBImage method is:
76 % void ConvertHSBToRGB(const double hue,const double saturation,
77 % const double brightness,double *red,double *green,double *blue)
79 % A description of each parameter follows:
81 % o hue, saturation, brightness: A double value representing a
82 % component of the HSB color space.
84 % o red, green, blue: A pointer to a pixel component of type Quantum.
87 MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
88 const double brightness,double *red,double *green,double *blue)
98 Convert HSB to RGB colorspace.
100 assert(red != (double *) NULL);
101 assert(green != (double *) NULL);
102 assert(blue != (double *) NULL);
103 if (saturation == 0.0)
105 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness);
110 h=6.0*(hue-floor(hue));
111 f=h-floor((double) h);
112 p=brightness*(1.0-saturation);
113 q=brightness*(1.0-saturation*f);
114 t=brightness*(1.0-(saturation*(1.0-f)));
120 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness);
121 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*t);
122 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*p);
127 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*q);
128 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness);
129 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*p);
134 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*p);
135 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness);
136 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*t);
141 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*p);
142 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*q);
143 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness);
148 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*t);
149 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*p);
150 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness);
155 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness);
156 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*p);
157 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*q);
164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 % C o n v e r t H S L T o R G B %
172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
175 % green, blue) triple.
177 % The format of the ConvertHSLToRGBImage method is:
179 % void ConvertHSLToRGB(const double hue,const double saturation,
180 % const double lightness,double *red,double *green,double *blue)
182 % A description of each parameter follows:
184 % o hue, saturation, lightness: A double value representing a
185 % component of the HSL color space.
187 % o red, green, blue: A pointer to a pixel component of type Quantum.
191 static inline MagickRealType ConvertHueToRGB(MagickRealType m1,
192 MagickRealType m2,MagickRealType hue)
199 return(m1+6.0*(m2-m1)*hue);
203 return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
207 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
208 const double lightness,double *red,double *green,double *blue)
218 Convert HSL to RGB colorspace.
220 assert(red != (double *) NULL);
221 assert(green != (double *) NULL);
222 assert(blue != (double *) NULL);
225 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*lightness);
231 m2=lightness*(saturation+1.0);
233 m2=(lightness+saturation)-(lightness*saturation);
235 r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
236 g=ConvertHueToRGB(m1,m2,hue);
237 b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
238 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*r);
239 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*g);
240 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*b);
244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248 % C o n v e r t H W B T o R G B %
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254 % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
257 % The format of the ConvertHWBToRGBImage method is:
259 % void ConvertHWBToRGB(const double hue,const double whiteness,
260 % const double blackness,double *red,double *green,double *blue)
262 % A description of each parameter follows:
264 % o hue, whiteness, blackness: A double value representing a
265 % component of the HWB color space.
267 % o red, green, blue: A pointer to a pixel component of type Quantum.
270 MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
271 const double blackness,double *red,double *green,double *blue)
285 Convert HWB to RGB colorspace.
287 assert(red != (double *) NULL);
288 assert(green != (double *) NULL);
289 assert(blue != (double *) NULL);
293 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*v);
294 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*v);
295 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*v);
298 i=(ssize_t) floor(6.0*hue);
302 n=whiteness+f*(v-whiteness); /* linear interpolation */
307 case 0: r=v; g=n; b=whiteness; break;
308 case 1: r=n; g=v; b=whiteness; break;
309 case 2: r=whiteness; g=v; b=n; break;
310 case 3: r=whiteness; g=n; b=v; break;
311 case 4: r=n; g=whiteness; b=v; break;
312 case 5: r=v; g=whiteness; b=n; break;
314 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*r);
315 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*g);
316 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*b);
320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324 % C o n v e r t R G B T o H S B %
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330 % ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
331 % brightness) triple.
333 % The format of the ConvertRGBToHSB method is:
335 % void ConvertRGBToHSB(const double red,const double green,
336 % const double blue,double *hue,double *saturation,double *brightness)
338 % A description of each parameter follows:
340 % o red, green, blue: A Quantum value representing the red, green, and
341 % blue component of a pixel..
343 % o hue, saturation, brightness: A pointer to a double value representing a
344 % component of the HSB color space.
347 MagickPrivate void ConvertRGBToHSB(const double red,const double green,
348 const double blue,double *hue,double *saturation,double *brightness)
356 Convert RGB to HSB colorspace.
358 assert(hue != (double *) NULL);
359 assert(saturation != (double *) NULL);
360 assert(brightness != (double *) NULL);
364 min=(MagickRealType) (red < green ? red : green);
365 if ((MagickRealType) blue < min)
366 min=(MagickRealType) blue;
367 max=(MagickRealType) (red > green ? red : green);
368 if ((MagickRealType) blue > max)
369 max=(MagickRealType) blue;
373 *saturation=(double) (delta/max);
374 *brightness=(double) (QuantumScale*max);
377 if ((MagickRealType) red == max)
378 *hue=(double) ((green-(MagickRealType) blue)/delta);
380 if ((MagickRealType) green == max)
381 *hue=(double) (2.0+(blue-(MagickRealType) red)/delta);
383 *hue=(double) (4.0+(red-(MagickRealType) green)/delta);
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394 % C o n v e r t R G B T o H S L %
398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
403 % The format of the ConvertRGBToHSL method is:
405 % void ConvertRGBToHSL(const double red,const double green,
406 % const double blue,double *hue,double *saturation,double *lightness)
408 % A description of each parameter follows:
410 % o red, green, blue: A Quantum value representing the red, green, and
411 % blue component of a pixel..
413 % o hue, saturation, lightness: A pointer to a double value representing a
414 % component of the HSL color space.
418 static inline double MagickMax(const double x,const double y)
425 static inline double MagickMin(const double x,const double y)
432 MagickExport void ConvertRGBToHSL(const double red,const double green,
433 const double blue,double *hue,double *saturation,double *lightness)
444 Convert RGB to HSL colorspace.
446 assert(hue != (double *) NULL);
447 assert(saturation != (double *) NULL);
448 assert(lightness != (double *) NULL);
450 g=QuantumScale*green;
452 max=MagickMax(r,MagickMax(g,b));
453 min=MagickMin(r,MagickMin(g,b));
454 *lightness=(double) ((min+max)/2.0);
462 if (*lightness < 0.5)
463 *saturation=(double) (delta/(min+max));
465 *saturation=(double) (delta/(2.0-max-min));
467 *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
470 *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
474 *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
487 % C o n v e r t R G B T o H W B %
491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493 % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
496 % The format of the ConvertRGBToHWB method is:
498 % void ConvertRGBToHWB(const double red,const double green,
499 % const double blue,double *hue,double *whiteness,double *blackness)
501 % A description of each parameter follows:
503 % o red, green, blue: A Quantum value representing the red, green, and
504 % blue component of a pixel.
506 % o hue, whiteness, blackness: A pointer to a double value representing a
507 % component of the HWB color space.
510 MagickPrivate void ConvertRGBToHWB(const double red,const double green,
511 const double blue,double *hue,double *whiteness,double *blackness)
522 Convert RGB to HWB colorspace.
524 assert(hue != (double *) NULL);
525 assert(whiteness != (double *) NULL);
526 assert(blackness != (double *) NULL);
527 w=(MagickRealType) MagickMin((double) red,MagickMin((double) green,(double)
529 v=(MagickRealType) MagickMax((double) red,MagickMax((double) green,(double)
531 *blackness=1.0-QuantumScale*v;
532 *whiteness=QuantumScale*w;
538 f=((MagickRealType) red == w) ? green-(MagickRealType) blue :
539 (((MagickRealType) green == w) ? blue-(MagickRealType) red : red-
540 (MagickRealType) green);
541 i=((MagickRealType) red == w) ? 3 : (((MagickRealType) green == w) ? 5 : 1);
542 *hue=((double) i-f/(v-1.0*w))/6.0;
546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
550 % E x p a n d A f f i n e %
554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
556 % ExpandAffine() computes the affine's expansion factor, i.e. the square root
557 % of the factor by which the affine transform affects area. In an affine
558 % transform composed of scaling, rotation, shearing, and translation, returns
559 % the amount of scaling.
561 % The format of the ExpandAffine method is:
563 % double ExpandAffine(const AffineMatrix *affine)
565 % A description of each parameter follows:
567 % o expansion: Method ExpandAffine returns the affine's expansion factor.
569 % o affine: A pointer the affine transform of type AffineMatrix.
572 MagickExport double ExpandAffine(const AffineMatrix *affine)
574 assert(affine != (const AffineMatrix *) NULL);
575 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583 % 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 %
587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589 % GenerateDifferentialNoise() generates differentual noise.
591 % The format of the GenerateDifferentialNoise method is:
593 % double GenerateDifferentialNoise(RandomInfo *random_info,
594 % const Quantum pixel,const NoiseType noise_type,const double attenuate)
596 % A description of each parameter follows:
598 % o random_info: the random info.
600 % o pixel: noise is relative to this pixel value.
602 % o noise_type: the type of noise.
604 % o attenuate: attenuate the noise.
607 MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
608 const Quantum pixel,const NoiseType noise_type,const double attenuate)
610 #define SigmaUniform (attenuate*0.015625)
611 #define SigmaGaussian (attenuate*0.015625)
612 #define SigmaImpulse (attenuate*0.1)
613 #define SigmaLaplacian (attenuate*0.0390625)
614 #define SigmaMultiplicativeGaussian (attenuate*0.5)
615 #define SigmaPoisson (attenuate*12.5)
616 #define TauGaussian (attenuate*0.078125)
624 alpha=GetPseudoRandomValue(random_info);
630 noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
641 beta=GetPseudoRandomValue(random_info);
642 gamma=sqrt(-2.0*log(alpha));
643 sigma=gamma*cos((double) (2.0*MagickPI*beta));
644 tau=gamma*sin((double) (2.0*MagickPI*beta));
645 noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
646 QuantumRange*TauGaussian*tau);
651 if (alpha < (SigmaImpulse/2.0))
654 if (alpha >= (1.0-(SigmaImpulse/2.0)))
655 noise=(double) QuantumRange;
657 noise=(double) pixel;
664 if (alpha <= MagickEpsilon)
665 noise=(double) (pixel-QuantumRange);
667 noise=(double) (pixel+QuantumRange*SigmaLaplacian*
672 if (beta <= (0.5*MagickEpsilon))
673 noise=(double) (pixel+QuantumRange);
675 noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
678 case MultiplicativeGaussianNoise:
681 if (alpha > MagickEpsilon)
682 sigma=sqrt(-2.0*log(alpha));
683 beta=GetPseudoRandomValue(random_info);
684 noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
685 cos((double) (2.0*MagickPI*beta))/2.0);
696 poisson=exp(-SigmaPoisson*QuantumScale*pixel);
697 for (i=0; alpha > poisson; i++)
699 beta=GetPseudoRandomValue(random_info);
702 noise=(double) (QuantumRange*i/SigmaPoisson);
707 noise=(double) (QuantumRange*alpha);
715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719 % G e t O p t i m a l K e r n e l W i d t h %
723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
725 % GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
726 % filter. Start with the minimum value of 3 pixels and walk out until we drop
727 % below the threshold of one pixel numerical accuracy.
729 % The format of the GetOptimalKernelWidth method is:
731 % size_t GetOptimalKernelWidth(const double radius,
732 % const double sigma)
734 % A description of each parameter follows:
736 % o width: Method GetOptimalKernelWidth returns the optimal width of
737 % a convolution kernel.
739 % o radius: the radius of the Gaussian, in pixels, not counting the center
742 % o sigma: the standard deviation of the Gaussian, in pixels.
745 MagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
764 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
765 if (radius > MagickEpsilon)
766 return((size_t) (2.0*ceil(radius)+1.0));
768 if (gamma <= MagickEpsilon)
770 alpha=1.0/(2.0*gamma*gamma);
771 beta=(double) (1.0/(MagickSQ2PI*gamma));
776 for (i=(-j); i <= j; i++)
777 normalize+=exp(-((double) (i*i))*alpha)*beta;
778 value=exp(-((double) (j*j))*alpha)*beta/normalize;
779 if ((value < QuantumScale) || (value < MagickEpsilon))
783 return((size_t) (width-2));
786 MagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
804 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
805 if (radius > MagickEpsilon)
806 return((size_t) (2.0*ceil(radius)+1.0));
808 if (gamma <= MagickEpsilon)
810 alpha=1.0/(2.0*gamma*gamma);
811 beta=(double) (1.0/(Magick2PI*gamma*gamma));
816 for (v=(-j); v <= j; v++)
817 for (u=(-j); u <= j; u++)
818 normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
819 value=exp(-((double) (j*j))*alpha)*beta/normalize;
820 if ((value < QuantumScale) || (value < MagickEpsilon))
824 return((size_t) (width-2));
827 MagickPrivate size_t GetOptimalKernelWidth(const double radius,
830 return(GetOptimalKernelWidth1D(radius,sigma));