2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Graphic Gems - Graphic Support Methods %
20 % Copyright 1999-2013 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)
101 Convert HCL to RGB colorspace.
103 assert(red != (double *) NULL);
104 assert(green != (double *) NULL);
105 assert(blue != (double *) NULL);
108 x=c*(1.0-fabs(fmod(h,2.0)-1.0));
112 if ((0.0 <= h) && (h < 1.0))
118 if ((1.0 <= h) && (h < 2.0))
124 if ((2.0 <= h) && (h < 3.0))
130 if ((3.0 <= h) && (h < 4.0))
136 if ((4.0 <= h) && (h < 5.0))
142 if ((5.0 <= h) && (h < 6.0))
147 m=luma-(0.298839f*r+0.586811f*g+0.114350f*b);
148 *red=QuantumRange*(r+m);
149 *green=QuantumRange*(g+m);
150 *blue=QuantumRange*(b+m);
154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 % C o n v e r t H S B T o R G B %
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 % ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
165 % green, blue) triple.
167 % The format of the ConvertHSBToRGBImage method is:
169 % void ConvertHSBToRGB(const double hue,const double saturation,
170 % const double brightness,double *red,double *green,double *blue)
172 % A description of each parameter follows:
174 % o hue, saturation, brightness: A double value representing a
175 % component of the HSB color space.
177 % o red, green, blue: A pointer to a pixel component of type Quantum.
180 MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
181 const double brightness,double *red,double *green,double *blue)
191 Convert HSB to RGB colorspace.
193 assert(red != (double *) NULL);
194 assert(green != (double *) NULL);
195 assert(blue != (double *) NULL);
196 if (saturation == 0.0)
198 *red=QuantumRange*brightness;
203 h=6.0*(hue-floor(hue));
204 f=h-floor((double) h);
205 p=brightness*(1.0-saturation);
206 q=brightness*(1.0-saturation*f);
207 t=brightness*(1.0-(saturation*(1.0-f)));
213 *red=QuantumRange*brightness;
214 *green=QuantumRange*t;
215 *blue=QuantumRange*p;
221 *green=QuantumRange*brightness;
222 *blue=QuantumRange*p;
228 *green=QuantumRange*brightness;
229 *blue=QuantumRange*t;
235 *green=QuantumRange*q;
236 *blue=QuantumRange*brightness;
242 *green=QuantumRange*p;
243 *blue=QuantumRange*brightness;
248 *red=QuantumRange*brightness;
249 *green=QuantumRange*p;
250 *blue=QuantumRange*q;
257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 % C o n v e r t H S L T o R G B %
265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
268 % green, blue) triple.
270 % The format of the ConvertHSLToRGBImage method is:
272 % void ConvertHSLToRGB(const double hue,const double saturation,
273 % const double lightness,double *red,double *green,double *blue)
275 % A description of each parameter follows:
277 % o hue, saturation, lightness: A double value representing a
278 % component of the HSL color space.
280 % o red, green, blue: A pointer to a pixel component of type Quantum.
284 static inline double ConvertHueToRGB(double m1,double m2,double hue)
291 return(m1+6.0*(m2-m1)*hue);
295 return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
299 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
300 const double lightness,double *red,double *green,double *blue)
310 Convert HSL to RGB colorspace.
312 assert(red != (double *) NULL);
313 assert(green != (double *) NULL);
314 assert(blue != (double *) NULL);
317 *red=QuantumRange*lightness;
323 m2=lightness*(saturation+1.0);
325 m2=(lightness+saturation)-(lightness*saturation);
327 r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
328 g=ConvertHueToRGB(m1,m2,hue);
329 b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
331 *green=QuantumRange*g;
332 *blue=QuantumRange*b;
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 % C o n v e r t H W B T o R G B %
344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
349 % The format of the ConvertHWBToRGBImage method is:
351 % void ConvertHWBToRGB(const double hue,const double whiteness,
352 % const double blackness,double *red,double *green,double *blue)
354 % A description of each parameter follows:
356 % o hue, whiteness, blackness: A double value representing a
357 % component of the HWB color space.
359 % o red, green, blue: A pointer to a pixel component of type Quantum.
362 MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
363 const double blackness,double *red,double *green,double *blue)
377 Convert HWB to RGB colorspace.
379 assert(red != (double *) NULL);
380 assert(green != (double *) NULL);
381 assert(blue != (double *) NULL);
386 *green=QuantumRange*v;
387 *blue=QuantumRange*v;
390 i=(ssize_t) floor(6.0*hue);
394 n=whiteness+f*(v-whiteness); /* linear interpolation */
399 case 0: r=v; g=n; b=whiteness; break;
400 case 1: r=n; g=v; b=whiteness; break;
401 case 2: r=whiteness; g=v; b=n; break;
402 case 3: r=whiteness; g=n; b=v; break;
403 case 4: r=n; g=whiteness; b=v; break;
404 case 5: r=v; g=whiteness; b=n; break;
407 *green=QuantumRange*g;
408 *blue=QuantumRange*b;
412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
416 % C o n v e r t R G B T o H C L %
420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422 % ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
425 % The format of the ConvertRGBToHCL method is:
427 % void ConvertRGBToHCL(const double red,const double green,
428 % const double blue,double *hue,double *chroma,double *luma)
430 % A description of each parameter follows:
432 % o red, green, blue: A Quantum value representing the red, green, and
433 % blue component of a pixel.
435 % o hue, chroma, luma: A pointer to a double value representing a
436 % component of the HCL color space.
440 static inline double MagickMax(const double x,const double y)
447 static inline double MagickMin(const double x,const double y)
454 MagickPrivate void ConvertRGBToHCL(const double red,const double green,
455 const double blue,double *hue,double *chroma,double *luma)
466 Convert RGB to HCL colorspace.
468 assert(hue != (double *) NULL);
469 assert(chroma != (double *) NULL);
470 assert(luma != (double *) NULL);
474 max=MagickMax(r,MagickMax(g,b));
475 c=max-(double) MagickMin(r,MagickMin(g,b));
481 h=fmod((g-b)/c+6.0,6.0);
489 *chroma=QuantumScale*c;
490 *luma=QuantumScale*(0.298839f*r+0.586811f*g+0.114350f*b);
494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
498 % C o n v e r t R G B T o H S B %
502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504 % ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
505 % brightness) triple.
507 % The format of the ConvertRGBToHSB method is:
509 % void ConvertRGBToHSB(const double red,const double green,
510 % const double blue,double *hue,double *saturation,double *brightness)
512 % A description of each parameter follows:
514 % o red, green, blue: A Quantum value representing the red, green, and
515 % blue component of a pixel..
517 % o hue, saturation, brightness: A pointer to a double value representing a
518 % component of the HSB color space.
521 MagickPrivate void ConvertRGBToHSB(const double red,const double green,
522 const double blue,double *hue,double *saturation,double *brightness)
533 Convert RGB to HSB colorspace.
535 assert(hue != (double *) NULL);
536 assert(saturation != (double *) NULL);
537 assert(brightness != (double *) NULL);
553 *saturation=delta/max;
554 *brightness=QuantumScale*max;
561 *hue=2.0+(b-r)/delta;
563 *hue=4.0+(r-g)/delta;
570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
574 % C o n v e r t R G B T o H S L %
578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580 % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
583 % The format of the ConvertRGBToHSL method is:
585 % void ConvertRGBToHSL(const double red,const double green,
586 % const double blue,double *hue,double *saturation,double *lightness)
588 % A description of each parameter follows:
590 % o red, green, blue: A Quantum value representing the red, green, and
591 % blue component of a pixel..
593 % o hue, saturation, lightness: A pointer to a double value representing a
594 % component of the HSL color space.
597 MagickExport void ConvertRGBToHSL(const double red,const double green,
598 const double blue,double *hue,double *saturation,double *lightness)
609 Convert RGB to HSL colorspace.
611 assert(hue != (double *) NULL);
612 assert(saturation != (double *) NULL);
613 assert(lightness != (double *) NULL);
615 g=QuantumScale*green;
617 max=MagickMax(r,MagickMax(g,b));
618 min=MagickMin(r,MagickMin(g,b));
619 *lightness=(double) ((min+max)/2.0);
627 if (*lightness < 0.5)
628 *saturation=(double) (delta/(min+max));
630 *saturation=(double) (delta/(2.0-max-min));
632 *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
635 *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
639 *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652 % C o n v e r t R G B T o H W B %
656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
658 % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
661 % The format of the ConvertRGBToHWB method is:
663 % void ConvertRGBToHWB(const double red,const double green,
664 % const double blue,double *hue,double *whiteness,double *blackness)
666 % A description of each parameter follows:
668 % o red, green, blue: A Quantum value representing the red, green, and
669 % blue component of a pixel.
671 % o hue, whiteness, blackness: A pointer to a double value representing a
672 % component of the HWB color space.
675 MagickPrivate void ConvertRGBToHWB(const double red,const double green,
676 const double blue,double *hue,double *whiteness,double *blackness)
688 Convert RGB to HWB colorspace.
690 assert(hue != (double *) NULL);
691 assert(whiteness != (double *) NULL);
692 assert(blackness != (double *) NULL);
696 w=MagickMin(r,MagickMin(g,b));
697 v=MagickMax(r,MagickMax(g,b));
698 *blackness=1.0-QuantumScale*v;
699 *whiteness=QuantumScale*w;
705 f=(r == w) ? g-b : ((g == w) ? b-r : r-g);
706 p=(r == w) ? 3.0 : ((g == w) ? 5.0 : 1.0);
707 *hue=(p-f/(v-1.0*w))/6.0;
711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715 % E x p a n d A f f i n e %
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721 % ExpandAffine() computes the affine's expansion factor, i.e. the square root
722 % of the factor by which the affine transform affects area. In an affine
723 % transform composed of scaling, rotation, shearing, and translation, returns
724 % the amount of scaling.
726 % The format of the ExpandAffine method is:
728 % double ExpandAffine(const AffineMatrix *affine)
730 % A description of each parameter follows:
732 % o expansion: Method ExpandAffine returns the affine's expansion factor.
734 % o affine: A pointer the affine transform of type AffineMatrix.
737 MagickExport double ExpandAffine(const AffineMatrix *affine)
739 assert(affine != (const AffineMatrix *) NULL);
740 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
744 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748 % 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 %
752 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754 % GenerateDifferentialNoise() generates differentual noise.
756 % The format of the GenerateDifferentialNoise method is:
758 % double GenerateDifferentialNoise(RandomInfo *random_info,
759 % const Quantum pixel,const NoiseType noise_type,const double attenuate)
761 % A description of each parameter follows:
763 % o random_info: the random info.
765 % o pixel: noise is relative to this pixel value.
767 % o noise_type: the type of noise.
769 % o attenuate: attenuate the noise.
772 MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
773 const Quantum pixel,const NoiseType noise_type,const double attenuate)
775 #define SigmaUniform (attenuate*0.015625)
776 #define SigmaGaussian (attenuate*0.015625)
777 #define SigmaImpulse (attenuate*0.1)
778 #define SigmaLaplacian (attenuate*0.0390625)
779 #define SigmaMultiplicativeGaussian (attenuate*0.5)
780 #define SigmaPoisson (attenuate*12.5)
781 #define SigmaRandom (attenuate)
782 #define TauGaussian (attenuate*0.078125)
790 alpha=GetPseudoRandomValue(random_info);
796 noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
807 beta=GetPseudoRandomValue(random_info);
808 gamma=sqrt(-2.0*log(alpha));
809 sigma=gamma*cos((double) (2.0*MagickPI*beta));
810 tau=gamma*sin((double) (2.0*MagickPI*beta));
811 noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
812 QuantumRange*TauGaussian*tau);
817 if (alpha < (SigmaImpulse/2.0))
820 if (alpha >= (1.0-(SigmaImpulse/2.0)))
821 noise=(double) QuantumRange;
823 noise=(double) pixel;
830 if (alpha <= MagickEpsilon)
831 noise=(double) (pixel-QuantumRange);
833 noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
838 if (beta <= (0.5*MagickEpsilon))
839 noise=(double) (pixel+QuantumRange);
841 noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
844 case MultiplicativeGaussianNoise:
847 if (alpha > MagickEpsilon)
848 sigma=sqrt(-2.0*log(alpha));
849 beta=GetPseudoRandomValue(random_info);
850 noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
851 cos((double) (2.0*MagickPI*beta))/2.0);
862 poisson=exp(-SigmaPoisson*QuantumScale*pixel);
863 for (i=0; alpha > poisson; i++)
865 beta=GetPseudoRandomValue(random_info);
868 noise=(double) (QuantumRange*i/SigmaPoisson);
873 noise=(double) (QuantumRange*SigmaRandom*alpha);
881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
885 % G e t O p t i m a l K e r n e l W i d t h %
889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891 % GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
892 % filter. Start with the minimum value of 3 pixels and walk out until we drop
893 % below the threshold of one pixel numerical accuracy.
895 % The format of the GetOptimalKernelWidth method is:
897 % size_t GetOptimalKernelWidth(const double radius,
898 % const double sigma)
900 % A description of each parameter follows:
902 % o width: Method GetOptimalKernelWidth returns the optimal width of
903 % a convolution kernel.
905 % o radius: the radius of the Gaussian, in pixels, not counting the center
908 % o sigma: the standard deviation of the Gaussian, in pixels.
911 MagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
930 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
931 if (radius > MagickEpsilon)
932 return((size_t) (2.0*ceil(radius)+1.0));
934 if (gamma <= MagickEpsilon)
936 alpha=PerceptibleReciprocal(2.0*gamma*gamma);
937 beta=(double) PerceptibleReciprocal((double) MagickSQ2PI*gamma);
941 j=(ssize_t) (width-1)/2;
942 for (i=(-j); i <= j; i++)
943 normalize+=exp(-((double) (i*i))*alpha)*beta;
944 value=exp(-((double) (j*j))*alpha)*beta/normalize;
945 if ((value < QuantumScale) || (value < MagickEpsilon))
949 return((size_t) (width-2));
952 MagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
970 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
971 if (radius > MagickEpsilon)
972 return((size_t) (2.0*ceil(radius)+1.0));
974 if (gamma <= MagickEpsilon)
976 alpha=PerceptibleReciprocal(2.0*gamma*gamma);
977 beta=(double) PerceptibleReciprocal((double) Magick2PI*gamma*gamma);
981 j=(ssize_t) (width-1)/2;
982 for (v=(-j); v <= j; v++)
983 for (u=(-j); u <= j; u++)
984 normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
985 value=exp(-((double) (j*j))*alpha)*beta/normalize;
986 if ((value < QuantumScale) || (value < MagickEpsilon))
990 return((size_t) (width-2));
993 MagickPrivate size_t GetOptimalKernelWidth(const double radius,
996 return(GetOptimalKernelWidth1D(radius,sigma));