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 S B T o R G B %
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 % ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
73 % green, blue) triple.
75 % The format of the ConvertHSBToRGBImage method is:
77 % void ConvertHSBToRGB(const double hue,const double saturation,
78 % const double brightness,double *red,double *green,double *blue)
80 % A description of each parameter follows:
82 % o hue, saturation, brightness: A double value representing a
83 % component of the HSB color space.
85 % o red, green, blue: A pointer to a pixel component of type Quantum.
88 MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
89 const double brightness,double *red,double *green,double *blue)
99 Convert HSB to RGB colorspace.
101 assert(red != (double *) NULL);
102 assert(green != (double *) NULL);
103 assert(blue != (double *) NULL);
104 if (saturation == 0.0)
106 *red=QuantumRange*brightness;
111 h=6.0*(hue-floor(hue));
112 f=h-floor((double) h);
113 p=brightness*(1.0-saturation);
114 q=brightness*(1.0-saturation*f);
115 t=brightness*(1.0-(saturation*(1.0-f)));
121 *red=QuantumRange*brightness;
122 *green=QuantumRange*t;
123 *blue=QuantumRange*p;
129 *green=QuantumRange*brightness;
130 *blue=QuantumRange*p;
136 *green=QuantumRange*brightness;
137 *blue=QuantumRange*t;
143 *green=QuantumRange*q;
144 *blue=QuantumRange*brightness;
150 *green=QuantumRange*p;
151 *blue=QuantumRange*brightness;
156 *red=QuantumRange*brightness;
157 *green=QuantumRange*p;
158 *blue=QuantumRange*q;
165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169 % C o n v e r t H S L T o R G B %
173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175 % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
176 % green, blue) triple.
178 % The format of the ConvertHSLToRGBImage method is:
180 % void ConvertHSLToRGB(const double hue,const double saturation,
181 % const double lightness,double *red,double *green,double *blue)
183 % A description of each parameter follows:
185 % o hue, saturation, lightness: A double value representing a
186 % component of the HSL color space.
188 % o red, green, blue: A pointer to a pixel component of type Quantum.
192 static inline double ConvertHueToRGB(double m1,double m2,double 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=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);
239 *green=QuantumRange*g;
240 *blue=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);
294 *green=QuantumRange*v;
295 *blue=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;
315 *green=QuantumRange*g;
316 *blue=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)
359 Convert RGB to HSB colorspace.
361 assert(hue != (double *) NULL);
362 assert(saturation != (double *) NULL);
363 assert(brightness != (double *) NULL);
379 *saturation=delta/max;
380 *brightness=QuantumScale*max;
387 *hue=2.0+(b-r)/delta;
389 *hue=4.0+(r-g)/delta;
396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 % C o n v e r t R G B T o H S L %
404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406 % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
409 % The format of the ConvertRGBToHSL method is:
411 % void ConvertRGBToHSL(const double red,const double green,
412 % const double blue,double *hue,double *saturation,double *lightness)
414 % A description of each parameter follows:
416 % o red, green, blue: A Quantum value representing the red, green, and
417 % blue component of a pixel..
419 % o hue, saturation, lightness: A pointer to a double value representing a
420 % component of the HSL color space.
424 static inline double MagickMax(const double x,const double y)
431 static inline double MagickMin(const double x,const double y)
438 MagickExport void ConvertRGBToHSL(const double red,const double green,
439 const double blue,double *hue,double *saturation,double *lightness)
450 Convert RGB to HSL colorspace.
452 assert(hue != (double *) NULL);
453 assert(saturation != (double *) NULL);
454 assert(lightness != (double *) NULL);
456 g=QuantumScale*green;
458 max=MagickMax(r,MagickMax(g,b));
459 min=MagickMin(r,MagickMin(g,b));
460 *lightness=(double) ((min+max)/2.0);
468 if (*lightness < 0.5)
469 *saturation=(double) (delta/(min+max));
471 *saturation=(double) (delta/(2.0-max-min));
473 *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
476 *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
480 *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493 % C o n v e r t R G B T o H W B %
497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
499 % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
502 % The format of the ConvertRGBToHWB method is:
504 % void ConvertRGBToHWB(const double red,const double green,
505 % const double blue,double *hue,double *whiteness,double *blackness)
507 % A description of each parameter follows:
509 % o red, green, blue: A Quantum value representing the red, green, and
510 % blue component of a pixel.
512 % o hue, whiteness, blackness: A pointer to a double value representing a
513 % component of the HWB color space.
516 MagickPrivate void ConvertRGBToHWB(const double red,const double green,
517 const double blue,double *hue,double *whiteness,double *blackness)
529 Convert RGB to HWB colorspace.
531 assert(hue != (double *) NULL);
532 assert(whiteness != (double *) NULL);
533 assert(blackness != (double *) NULL);
537 w=MagickMin(r,MagickMin(g,b));
538 v=MagickMax(r,MagickMax(g,b));
539 *blackness=1.0-QuantumScale*v;
540 *whiteness=QuantumScale*w;
546 f=(r == w) ? g-b : ((g == w) ? b-r : r-g);
547 p=(r == w) ? 3.0 : ((g == w) ? 5.0 : 1.0);
548 *hue=(p-f/(v-1.0*w))/6.0;
552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
556 % E x p a n d A f f i n e %
560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 % ExpandAffine() computes the affine's expansion factor, i.e. the square root
563 % of the factor by which the affine transform affects area. In an affine
564 % transform composed of scaling, rotation, shearing, and translation, returns
565 % the amount of scaling.
567 % The format of the ExpandAffine method is:
569 % double ExpandAffine(const AffineMatrix *affine)
571 % A description of each parameter follows:
573 % o expansion: Method ExpandAffine returns the affine's expansion factor.
575 % o affine: A pointer the affine transform of type AffineMatrix.
578 MagickExport double ExpandAffine(const AffineMatrix *affine)
580 assert(affine != (const AffineMatrix *) NULL);
581 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589 % 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 %
593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595 % GenerateDifferentialNoise() generates differentual noise.
597 % The format of the GenerateDifferentialNoise method is:
599 % double GenerateDifferentialNoise(RandomInfo *random_info,
600 % const Quantum pixel,const NoiseType noise_type,const double attenuate)
602 % A description of each parameter follows:
604 % o random_info: the random info.
606 % o pixel: noise is relative to this pixel value.
608 % o noise_type: the type of noise.
610 % o attenuate: attenuate the noise.
613 MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
614 const Quantum pixel,const NoiseType noise_type,const double attenuate)
616 #define SigmaUniform (attenuate*0.015625)
617 #define SigmaGaussian (attenuate*0.015625)
618 #define SigmaImpulse (attenuate*0.1)
619 #define SigmaLaplacian (attenuate*0.0390625)
620 #define SigmaMultiplicativeGaussian (attenuate*0.5)
621 #define SigmaPoisson (attenuate*12.5)
622 #define SigmaRandom (attenuate)
623 #define TauGaussian (attenuate*0.078125)
631 alpha=GetPseudoRandomValue(random_info);
637 noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
648 beta=GetPseudoRandomValue(random_info);
649 gamma=sqrt(-2.0*log(alpha));
650 sigma=gamma*cos((double) (2.0*MagickPI*beta));
651 tau=gamma*sin((double) (2.0*MagickPI*beta));
652 noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
653 QuantumRange*TauGaussian*tau);
658 if (alpha < (SigmaImpulse/2.0))
661 if (alpha >= (1.0-(SigmaImpulse/2.0)))
662 noise=(double) QuantumRange;
664 noise=(double) pixel;
671 if (alpha <= MagickEpsilon)
672 noise=(double) (pixel-QuantumRange);
674 noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
679 if (beta <= (0.5*MagickEpsilon))
680 noise=(double) (pixel+QuantumRange);
682 noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
685 case MultiplicativeGaussianNoise:
688 if (alpha > MagickEpsilon)
689 sigma=sqrt(-2.0*log(alpha));
690 beta=GetPseudoRandomValue(random_info);
691 noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
692 cos((double) (2.0*MagickPI*beta))/2.0);
703 poisson=exp(-SigmaPoisson*QuantumScale*pixel);
704 for (i=0; alpha > poisson; i++)
706 beta=GetPseudoRandomValue(random_info);
709 noise=(double) (QuantumRange*i/SigmaPoisson);
714 noise=(double) (QuantumRange*SigmaRandom*alpha);
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
726 % G e t O p t i m a l K e r n e l W i d t h %
730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
732 % GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
733 % filter. Start with the minimum value of 3 pixels and walk out until we drop
734 % below the threshold of one pixel numerical accuracy.
736 % The format of the GetOptimalKernelWidth method is:
738 % size_t GetOptimalKernelWidth(const double radius,
739 % const double sigma)
741 % A description of each parameter follows:
743 % o width: Method GetOptimalKernelWidth returns the optimal width of
744 % a convolution kernel.
746 % o radius: the radius of the Gaussian, in pixels, not counting the center
749 % o sigma: the standard deviation of the Gaussian, in pixels.
752 MagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
771 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
772 if (radius > MagickEpsilon)
773 return((size_t) (2.0*ceil(radius)+1.0));
775 if (gamma <= MagickEpsilon)
777 alpha=MagickEpsilonReciprocal(2.0*gamma*gamma);
778 beta=(double) MagickEpsilonReciprocal((MagickRealType) MagickSQ2PI*gamma);
783 for (i=(-j); i <= j; i++)
784 normalize+=exp(-((double) (i*i))*alpha)*beta;
785 value=exp(-((double) (j*j))*alpha)*beta/normalize;
786 if ((value < QuantumScale) || (value < MagickEpsilon))
790 return((size_t) (width-2));
793 MagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
811 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
812 if (radius > MagickEpsilon)
813 return((size_t) (2.0*ceil(radius)+1.0));
815 if (gamma <= MagickEpsilon)
817 alpha=MagickEpsilonReciprocal(2.0*gamma*gamma);
818 beta=(double) MagickEpsilonReciprocal((MagickRealType) Magick2PI*gamma*gamma);
823 for (v=(-j); v <= j; v++)
824 for (u=(-j); u <= j; u++)
825 normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
826 value=exp(-((double) (j*j))*alpha)*beta/normalize;
827 if ((value < QuantumScale) || (value < MagickEpsilon))
831 return((size_t) (width-2));
834 MagickPrivate size_t GetOptimalKernelWidth(const double radius,
837 return(GetOptimalKernelWidth1D(radius,sigma));