2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Graphic Gems - Graphic Support Methods %
20 % Copyright 1999-2012 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/pixel-private.h"
54 #include "MagickCore/quantum.h"
55 #include "MagickCore/quantum-private.h"
56 #include "MagickCore/random_.h"
57 #include "MagickCore/resize.h"
58 #include "MagickCore/transform.h"
59 #include "MagickCore/signature-private.h"
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66 % C o n v e r t H C L T o R G B %
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 % ConvertHCLToRGB() transforms a (hue, chroma, luma) to a (red, green,
75 % The format of the ConvertHCLToRGBImage method is:
77 % void ConvertHCLToRGB(const double hue,const double chroma,
78 % const double luma,double *red,double *green,double *blue)
80 % A description of each parameter follows:
82 % o hue, chroma, luma: A double value representing a
83 % component of the HCL color space.
85 % o red, green, blue: A pointer to a pixel component of type Quantum.
88 MagickPrivate void ConvertHCLToRGB(const double hue,const double chroma,
89 const double luma,double *red,double *green,double *blue)
102 Convert HCL to RGB colorspace.
104 assert(red != (double *) NULL);
105 assert(green != (double *) NULL);
106 assert(blue != (double *) NULL);
109 x=c*(1.0-fabs(fmod(h,2.0)-1.0));
113 if ((0.0 <= h) && (h < 1.0))
119 if ((1.0 <= h) && (h < 2.0))
125 if ((2.0 <= h) && (h < 3.0))
131 if ((3.0 <= h) && (h < 4.0))
137 if ((4.0 <= h) && (h < 5.0))
143 if ((5.0 <= h) && (h < 6.0))
148 m=luma-(0.298839*r+0.586811*g+0.114350*b);
150 Choose saturation strategy to clip it into the RGB cube; hue and luma are
151 preserved and chroma may be changed.
162 z=(1.0-luma)/(m+c-luma);
165 *red=QuantumRange*(z*r+m);
166 *green=QuantumRange*(z*g+m);
167 *blue=QuantumRange*(z*b+m);
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175 % C o n v e r t H S B T o R G B %
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181 % ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
182 % green, blue) triple.
184 % The format of the ConvertHSBToRGBImage method is:
186 % void ConvertHSBToRGB(const double hue,const double saturation,
187 % const double brightness,double *red,double *green,double *blue)
189 % A description of each parameter follows:
191 % o hue, saturation, brightness: A double value representing a
192 % component of the HSB color space.
194 % o red, green, blue: A pointer to a pixel component of type Quantum.
197 MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
198 const double brightness,double *red,double *green,double *blue)
208 Convert HSB to RGB colorspace.
210 assert(red != (double *) NULL);
211 assert(green != (double *) NULL);
212 assert(blue != (double *) NULL);
213 if (saturation == 0.0)
215 *red=QuantumRange*brightness;
220 h=6.0*(hue-floor(hue));
221 f=h-floor((double) h);
222 p=brightness*(1.0-saturation);
223 q=brightness*(1.0-saturation*f);
224 t=brightness*(1.0-(saturation*(1.0-f)));
230 *red=QuantumRange*brightness;
231 *green=QuantumRange*t;
232 *blue=QuantumRange*p;
238 *green=QuantumRange*brightness;
239 *blue=QuantumRange*p;
245 *green=QuantumRange*brightness;
246 *blue=QuantumRange*t;
252 *green=QuantumRange*q;
253 *blue=QuantumRange*brightness;
259 *green=QuantumRange*p;
260 *blue=QuantumRange*brightness;
265 *red=QuantumRange*brightness;
266 *green=QuantumRange*p;
267 *blue=QuantumRange*q;
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278 % C o n v e r t H S L T o R G B %
282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284 % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
285 % green, blue) triple.
287 % The format of the ConvertHSLToRGBImage method is:
289 % void ConvertHSLToRGB(const double hue,const double saturation,
290 % const double lightness,double *red,double *green,double *blue)
292 % A description of each parameter follows:
294 % o hue, saturation, lightness: A double value representing a
295 % component of the HSL color space.
297 % o red, green, blue: A pointer to a pixel component of type Quantum.
301 static inline double ConvertHueToRGB(double m1,double m2,double hue)
308 return(m1+6.0*(m2-m1)*hue);
312 return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
316 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
317 const double lightness,double *red,double *green,double *blue)
327 Convert HSL to RGB colorspace.
329 assert(red != (double *) NULL);
330 assert(green != (double *) NULL);
331 assert(blue != (double *) NULL);
334 *red=QuantumRange*lightness;
340 m2=lightness*(saturation+1.0);
342 m2=(lightness+saturation)-(lightness*saturation);
344 r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
345 g=ConvertHueToRGB(m1,m2,hue);
346 b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
348 *green=QuantumRange*g;
349 *blue=QuantumRange*b;
353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357 % C o n v e r t H W B T o R G B %
361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363 % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
366 % The format of the ConvertHWBToRGBImage method is:
368 % void ConvertHWBToRGB(const double hue,const double whiteness,
369 % const double blackness,double *red,double *green,double *blue)
371 % A description of each parameter follows:
373 % o hue, whiteness, blackness: A double value representing a
374 % component of the HWB color space.
376 % o red, green, blue: A pointer to a pixel component of type Quantum.
379 MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
380 const double blackness,double *red,double *green,double *blue)
394 Convert HWB to RGB colorspace.
396 assert(red != (double *) NULL);
397 assert(green != (double *) NULL);
398 assert(blue != (double *) NULL);
403 *green=QuantumRange*v;
404 *blue=QuantumRange*v;
407 i=(ssize_t) floor(6.0*hue);
411 n=whiteness+f*(v-whiteness); /* linear interpolation */
416 case 0: r=v; g=n; b=whiteness; break;
417 case 1: r=n; g=v; b=whiteness; break;
418 case 2: r=whiteness; g=v; b=n; break;
419 case 3: r=whiteness; g=n; b=v; break;
420 case 4: r=n; g=whiteness; b=v; break;
421 case 5: r=v; g=whiteness; b=n; break;
424 *green=QuantumRange*g;
425 *blue=QuantumRange*b;
429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433 % C o n v e r t R G B T o H C L %
437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439 % ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
442 % The format of the ConvertRGBToHCL method is:
444 % void ConvertRGBToHCL(const double red,const double green,
445 % const double blue,double *hue,double *chroma,double *luma)
447 % A description of each parameter follows:
449 % o red, green, blue: A Quantum value representing the red, green, and
450 % blue component of a pixel.
452 % o hue, chroma, luma: A pointer to a double value representing a
453 % component of the HCL color space.
457 static inline double MagickMax(const double x,const double y)
464 static inline double MagickMin(const double x,const double y)
471 MagickPrivate void ConvertRGBToHCL(const double red,const double green,
472 const double blue,double *hue,double *chroma,double *luma)
483 Convert RGB to HCL colorspace.
485 assert(hue != (double *) NULL);
486 assert(chroma != (double *) NULL);
487 assert(luma != (double *) NULL);
491 max=MagickMax(r,MagickMax(g,b));
492 c=max-(double) MagickMin(r,MagickMin(g,b));
498 h=fmod((g-b)/c+6.0,6.0);
506 *chroma=QuantumScale*c;
507 *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
515 % C o n v e r t R G B T o H S B %
519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
521 % ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
522 % brightness) triple.
524 % The format of the ConvertRGBToHSB method is:
526 % void ConvertRGBToHSB(const double red,const double green,
527 % const double blue,double *hue,double *saturation,double *brightness)
529 % A description of each parameter follows:
531 % o red, green, blue: A Quantum value representing the red, green, and
532 % blue component of a pixel..
534 % o hue, saturation, brightness: A pointer to a double value representing a
535 % component of the HSB color space.
538 MagickPrivate void ConvertRGBToHSB(const double red,const double green,
539 const double blue,double *hue,double *saturation,double *brightness)
550 Convert RGB to HSB colorspace.
552 assert(hue != (double *) NULL);
553 assert(saturation != (double *) NULL);
554 assert(brightness != (double *) NULL);
570 *saturation=delta/max;
571 *brightness=QuantumScale*max;
578 *hue=2.0+(b-r)/delta;
580 *hue=4.0+(r-g)/delta;
587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591 % C o n v e r t R G B T o H S L %
595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597 % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
600 % The format of the ConvertRGBToHSL method is:
602 % void ConvertRGBToHSL(const double red,const double green,
603 % const double blue,double *hue,double *saturation,double *lightness)
605 % A description of each parameter follows:
607 % o red, green, blue: A Quantum value representing the red, green, and
608 % blue component of a pixel..
610 % o hue, saturation, lightness: A pointer to a double value representing a
611 % component of the HSL color space.
614 MagickExport void ConvertRGBToHSL(const double red,const double green,
615 const double blue,double *hue,double *saturation,double *lightness)
626 Convert RGB to HSL colorspace.
628 assert(hue != (double *) NULL);
629 assert(saturation != (double *) NULL);
630 assert(lightness != (double *) NULL);
632 g=QuantumScale*green;
634 max=MagickMax(r,MagickMax(g,b));
635 min=MagickMin(r,MagickMin(g,b));
636 *lightness=(double) ((min+max)/2.0);
644 if (*lightness < 0.5)
645 *saturation=(double) (delta/(min+max));
647 *saturation=(double) (delta/(2.0-max-min));
649 *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
652 *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
656 *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669 % C o n v e r t R G B T o H W B %
673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675 % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
678 % The format of the ConvertRGBToHWB method is:
680 % void ConvertRGBToHWB(const double red,const double green,
681 % const double blue,double *hue,double *whiteness,double *blackness)
683 % A description of each parameter follows:
685 % o red, green, blue: A Quantum value representing the red, green, and
686 % blue component of a pixel.
688 % o hue, whiteness, blackness: A pointer to a double value representing a
689 % component of the HWB color space.
692 MagickPrivate void ConvertRGBToHWB(const double red,const double green,
693 const double blue,double *hue,double *whiteness,double *blackness)
705 Convert RGB to HWB colorspace.
707 assert(hue != (double *) NULL);
708 assert(whiteness != (double *) NULL);
709 assert(blackness != (double *) NULL);
713 w=MagickMin(r,MagickMin(g,b));
714 v=MagickMax(r,MagickMax(g,b));
715 *blackness=1.0-QuantumScale*v;
716 *whiteness=QuantumScale*w;
722 f=(r == w) ? g-b : ((g == w) ? b-r : r-g);
723 p=(r == w) ? 3.0 : ((g == w) ? 5.0 : 1.0);
724 *hue=(p-f/(v-1.0*w))/6.0;
728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
732 % E x p a n d A f f i n e %
736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
738 % ExpandAffine() computes the affine's expansion factor, i.e. the square root
739 % of the factor by which the affine transform affects area. In an affine
740 % transform composed of scaling, rotation, shearing, and translation, returns
741 % the amount of scaling.
743 % The format of the ExpandAffine method is:
745 % double ExpandAffine(const AffineMatrix *affine)
747 % A description of each parameter follows:
749 % o expansion: Method ExpandAffine returns the affine's expansion factor.
751 % o affine: A pointer the affine transform of type AffineMatrix.
754 MagickExport double ExpandAffine(const AffineMatrix *affine)
756 assert(affine != (const AffineMatrix *) NULL);
757 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
765 % 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 %
769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
771 % GenerateDifferentialNoise() generates differentual noise.
773 % The format of the GenerateDifferentialNoise method is:
775 % double GenerateDifferentialNoise(RandomInfo *random_info,
776 % const Quantum pixel,const NoiseType noise_type,const double attenuate)
778 % A description of each parameter follows:
780 % o random_info: the random info.
782 % o pixel: noise is relative to this pixel value.
784 % o noise_type: the type of noise.
786 % o attenuate: attenuate the noise.
789 MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
790 const Quantum pixel,const NoiseType noise_type,const double attenuate)
792 #define SigmaUniform (attenuate*0.015625)
793 #define SigmaGaussian (attenuate*0.015625)
794 #define SigmaImpulse (attenuate*0.1)
795 #define SigmaLaplacian (attenuate*0.0390625)
796 #define SigmaMultiplicativeGaussian (attenuate*0.5)
797 #define SigmaPoisson (attenuate*12.5)
798 #define SigmaRandom (attenuate)
799 #define TauGaussian (attenuate*0.078125)
807 alpha=GetPseudoRandomValue(random_info);
813 noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
824 beta=GetPseudoRandomValue(random_info);
825 gamma=sqrt(-2.0*log(alpha));
826 sigma=gamma*cos((double) (2.0*MagickPI*beta));
827 tau=gamma*sin((double) (2.0*MagickPI*beta));
828 noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
829 QuantumRange*TauGaussian*tau);
834 if (alpha < (SigmaImpulse/2.0))
837 if (alpha >= (1.0-(SigmaImpulse/2.0)))
838 noise=(double) QuantumRange;
840 noise=(double) pixel;
847 if (alpha <= MagickEpsilon)
848 noise=(double) (pixel-QuantumRange);
850 noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
855 if (beta <= (0.5*MagickEpsilon))
856 noise=(double) (pixel+QuantumRange);
858 noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
861 case MultiplicativeGaussianNoise:
864 if (alpha > MagickEpsilon)
865 sigma=sqrt(-2.0*log(alpha));
866 beta=GetPseudoRandomValue(random_info);
867 noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
868 cos((double) (2.0*MagickPI*beta))/2.0);
879 poisson=exp(-SigmaPoisson*QuantumScale*pixel);
880 for (i=0; alpha > poisson; i++)
882 beta=GetPseudoRandomValue(random_info);
885 noise=(double) (QuantumRange*i/SigmaPoisson);
890 noise=(double) (QuantumRange*SigmaRandom*alpha);
898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902 % G e t O p t i m a l K e r n e l W i d t h %
906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908 % GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
909 % filter. Start with the minimum value of 3 pixels and walk out until we drop
910 % below the threshold of one pixel numerical accuracy.
912 % The format of the GetOptimalKernelWidth method is:
914 % size_t GetOptimalKernelWidth(const double radius,
915 % const double sigma)
917 % A description of each parameter follows:
919 % o width: Method GetOptimalKernelWidth returns the optimal width of
920 % a convolution kernel.
922 % o radius: the radius of the Gaussian, in pixels, not counting the center
925 % o sigma: the standard deviation of the Gaussian, in pixels.
928 MagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
947 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
948 if (radius > MagickEpsilon)
949 return((size_t) (2.0*ceil(radius)+1.0));
951 if (gamma <= MagickEpsilon)
953 alpha=MagickEpsilonReciprocal(2.0*gamma*gamma);
954 beta=(double) MagickEpsilonReciprocal((double) MagickSQ2PI*gamma);
959 for (i=(-j); i <= j; i++)
960 normalize+=exp(-((double) (i*i))*alpha)*beta;
961 value=exp(-((double) (j*j))*alpha)*beta/normalize;
962 if ((value < QuantumScale) || (value < MagickEpsilon))
966 return((size_t) (width-2));
969 MagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
987 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
988 if (radius > MagickEpsilon)
989 return((size_t) (2.0*ceil(radius)+1.0));
991 if (gamma <= MagickEpsilon)
993 alpha=MagickEpsilonReciprocal(2.0*gamma*gamma);
994 beta=(double) MagickEpsilonReciprocal((double) Magick2PI*gamma*gamma);
999 for (v=(-j); v <= j; v++)
1000 for (u=(-j); u <= j; u++)
1001 normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
1002 value=exp(-((double) (j*j))*alpha)*beta/normalize;
1003 if ((value < QuantumScale) || (value < MagickEpsilon))
1007 return((size_t) (width-2));
1010 MagickPrivate size_t GetOptimalKernelWidth(const double radius,
1013 return(GetOptimalKernelWidth1D(radius,sigma));