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/image.h"
48 #include "MagickCore/image-private.h"
49 #include "MagickCore/log.h"
50 #include "MagickCore/memory_.h"
51 #include "MagickCore/pixel-accessor.h"
52 #include "MagickCore/quantum.h"
53 #include "MagickCore/quantum-private.h"
54 #include "MagickCore/random_.h"
55 #include "MagickCore/resize.h"
56 #include "MagickCore/transform.h"
57 #include "MagickCore/signature-private.h"
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
64 % C o n v e r t H S B T o R G B %
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 % ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
71 % green, blue) triple.
73 % The format of the ConvertHSBToRGBImage method is:
75 % void ConvertHSBToRGB(const double hue,const double saturation,
76 % const double brightness,Quantum *red,Quantum *green,Quantum *blue)
78 % A description of each parameter follows:
80 % o hue, saturation, brightness: A double value representing a
81 % component of the HSB color space.
83 % o red, green, blue: A pointer to a pixel component of type Quantum.
86 MagickExport void ConvertHSBToRGB(const double hue,const double saturation,
87 const double brightness,Quantum *red,Quantum *green,Quantum *blue)
97 Convert HSB to RGB colorspace.
99 assert(red != (Quantum *) NULL);
100 assert(green != (Quantum *) NULL);
101 assert(blue != (Quantum *) NULL);
102 if (saturation == 0.0)
104 *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
109 h=6.0*(hue-floor(hue));
110 f=h-floor((double) h);
111 p=brightness*(1.0-saturation);
112 q=brightness*(1.0-saturation*f);
113 t=brightness*(1.0-(saturation*(1.0-f)));
119 *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
120 *green=ClampToQuantum((MagickRealType) QuantumRange*t);
121 *blue=ClampToQuantum((MagickRealType) QuantumRange*p);
126 *red=ClampToQuantum((MagickRealType) QuantumRange*q);
127 *green=ClampToQuantum((MagickRealType) QuantumRange*brightness);
128 *blue=ClampToQuantum((MagickRealType) QuantumRange*p);
133 *red=ClampToQuantum((MagickRealType) QuantumRange*p);
134 *green=ClampToQuantum((MagickRealType) QuantumRange*brightness);
135 *blue=ClampToQuantum((MagickRealType) QuantumRange*t);
140 *red=ClampToQuantum((MagickRealType) QuantumRange*p);
141 *green=ClampToQuantum((MagickRealType) QuantumRange*q);
142 *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
147 *red=ClampToQuantum((MagickRealType) QuantumRange*t);
148 *green=ClampToQuantum((MagickRealType) QuantumRange*p);
149 *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
154 *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
155 *green=ClampToQuantum((MagickRealType) QuantumRange*p);
156 *blue=ClampToQuantum((MagickRealType) QuantumRange*q);
163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167 % C o n v e r t H S L T o R G B %
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
174 % green, blue) triple.
176 % The format of the ConvertHSLToRGBImage method is:
178 % void ConvertHSLToRGB(const double hue,const double saturation,
179 % const double lightness,Quantum *red,Quantum *green,Quantum *blue)
181 % A description of each parameter follows:
183 % o hue, saturation, lightness: A double value representing a
184 % component of the HSL color space.
186 % o red, green, blue: A pointer to a pixel component of type Quantum.
190 static inline MagickRealType ConvertHueToRGB(MagickRealType m1,
191 MagickRealType m2,MagickRealType hue)
198 return(m1+6.0*(m2-m1)*hue);
202 return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
206 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
207 const double lightness,Quantum *red,Quantum *green,Quantum *blue)
217 Convert HSL to RGB colorspace.
219 assert(red != (Quantum *) NULL);
220 assert(green != (Quantum *) NULL);
221 assert(blue != (Quantum *) NULL);
224 *red=ClampToQuantum((MagickRealType) QuantumRange*lightness);
230 m2=lightness*(saturation+1.0);
232 m2=(lightness+saturation)-(lightness*saturation);
234 r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
235 g=ConvertHueToRGB(m1,m2,hue);
236 b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
237 *red=ClampToQuantum((MagickRealType) QuantumRange*r);
238 *green=ClampToQuantum((MagickRealType) QuantumRange*g);
239 *blue=ClampToQuantum((MagickRealType) QuantumRange*b);
243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 % C o n v e r t H W B T o R G B %
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
256 % The format of the ConvertHWBToRGBImage method is:
258 % void ConvertHWBToRGB(const double hue,const double whiteness,
259 % const double blackness,Quantum *red,Quantum *green,Quantum *blue)
261 % A description of each parameter follows:
263 % o hue, whiteness, blackness: A double value representing a
264 % component of the HWB color space.
266 % o red, green, blue: A pointer to a pixel component of type Quantum.
269 MagickExport void ConvertHWBToRGB(const double hue,const double whiteness,
270 const double blackness,Quantum *red,Quantum *green,Quantum *blue)
284 Convert HWB to RGB colorspace.
286 assert(red != (Quantum *) NULL);
287 assert(green != (Quantum *) NULL);
288 assert(blue != (Quantum *) NULL);
292 *red=ClampToQuantum((MagickRealType) QuantumRange*v);
293 *green=ClampToQuantum((MagickRealType) QuantumRange*v);
294 *blue=ClampToQuantum((MagickRealType) QuantumRange*v);
297 i=(ssize_t) floor(6.0*hue);
301 n=whiteness+f*(v-whiteness); /* linear interpolation */
306 case 0: r=v; g=n; b=whiteness; break;
307 case 1: r=n; g=v; b=whiteness; break;
308 case 2: r=whiteness; g=v; b=n; break;
309 case 3: r=whiteness; g=n; b=v; break;
310 case 4: r=n; g=whiteness; b=v; break;
311 case 5: r=v; g=whiteness; b=n; break;
313 *red=ClampToQuantum((MagickRealType) QuantumRange*r);
314 *green=ClampToQuantum((MagickRealType) QuantumRange*g);
315 *blue=ClampToQuantum((MagickRealType) QuantumRange*b);
319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323 % C o n v e r t R G B T o H S B %
327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 % ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
330 % brightness) triple.
332 % The format of the ConvertRGBToHSB method is:
334 % void ConvertRGBToHSB(const Quantum red,const Quantum green,
335 % const Quantum blue,double *hue,double *saturation,double *brightness)
337 % A description of each parameter follows:
339 % o red, green, blue: A Quantum value representing the red, green, and
340 % blue component of a pixel..
342 % o hue, saturation, brightness: A pointer to a double value representing a
343 % component of the HSB color space.
346 MagickExport void ConvertRGBToHSB(const Quantum red,const Quantum green,
347 const Quantum blue,double *hue,double *saturation,double *brightness)
355 Convert RGB to HSB colorspace.
357 assert(hue != (double *) NULL);
358 assert(saturation != (double *) NULL);
359 assert(brightness != (double *) NULL);
363 min=(MagickRealType) (red < green ? red : green);
364 if ((MagickRealType) blue < min)
365 min=(MagickRealType) blue;
366 max=(MagickRealType) (red > green ? red : green);
367 if ((MagickRealType) blue > max)
368 max=(MagickRealType) blue;
372 *saturation=(double) (delta/max);
373 *brightness=(double) (QuantumScale*max);
376 if ((MagickRealType) red == max)
377 *hue=(double) ((green-(MagickRealType) blue)/delta);
379 if ((MagickRealType) green == max)
380 *hue=(double) (2.0+(blue-(MagickRealType) red)/delta);
382 *hue=(double) (4.0+(red-(MagickRealType) green)/delta);
389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393 % C o n v e r t R G B T o H S L %
397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
402 % The format of the ConvertRGBToHSL method is:
404 % void ConvertRGBToHSL(const Quantum red,const Quantum green,
405 % const Quantum blue,double *hue,double *saturation,double *lightness)
407 % A description of each parameter follows:
409 % o red, green, blue: A Quantum value representing the red, green, and
410 % blue component of a pixel..
412 % o hue, saturation, lightness: A pointer to a double value representing a
413 % component of the HSL color space.
417 static inline double MagickMax(const double x,const double y)
424 static inline double MagickMin(const double x,const double y)
431 MagickExport void ConvertRGBToHSL(const Quantum red,const Quantum green,
432 const Quantum blue,double *hue,double *saturation,double *lightness)
443 Convert RGB to HSL colorspace.
445 assert(hue != (double *) NULL);
446 assert(saturation != (double *) NULL);
447 assert(lightness != (double *) NULL);
449 g=QuantumScale*green;
451 max=MagickMax(r,MagickMax(g,b));
452 min=MagickMin(r,MagickMin(g,b));
453 *lightness=(double) ((min+max)/2.0);
461 if (*lightness < 0.5)
462 *saturation=(double) (delta/(min+max));
464 *saturation=(double) (delta/(2.0-max-min));
466 *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
469 *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
473 *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486 % C o n v e r t R G B T o H W B %
490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
492 % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
495 % The format of the ConvertRGBToHWB method is:
497 % void ConvertRGBToHWB(const Quantum red,const Quantum green,
498 % const Quantum blue,double *hue,double *whiteness,double *blackness)
500 % A description of each parameter follows:
502 % o red, green, blue: A Quantum value representing the red, green, and
503 % blue component of a pixel.
505 % o hue, whiteness, blackness: A pointer to a double value representing a
506 % component of the HWB color space.
509 MagickExport void ConvertRGBToHWB(const Quantum red,const Quantum green,
510 const Quantum blue,double *hue,double *whiteness,double *blackness)
521 Convert RGB to HWB colorspace.
523 assert(hue != (double *) NULL);
524 assert(whiteness != (double *) NULL);
525 assert(blackness != (double *) NULL);
526 w=(MagickRealType) MagickMin((double) red,MagickMin((double) green,(double)
528 v=(MagickRealType) MagickMax((double) red,MagickMax((double) green,(double)
530 *blackness=1.0-QuantumScale*v;
531 *whiteness=QuantumScale*w;
537 f=((MagickRealType) red == w) ? green-(MagickRealType) blue :
538 (((MagickRealType) green == w) ? blue-(MagickRealType) red : red-
539 (MagickRealType) green);
540 i=((MagickRealType) red == w) ? 3 : (((MagickRealType) green == w) ? 5 : 1);
541 *hue=((double) i-f/(v-1.0*w))/6.0;
545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
549 % E x p a n d A f f i n e %
553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
555 % ExpandAffine() computes the affine's expansion factor, i.e. the square root
556 % of the factor by which the affine transform affects area. In an affine
557 % transform composed of scaling, rotation, shearing, and translation, returns
558 % the amount of scaling.
560 % The format of the ExpandAffine method is:
562 % double ExpandAffine(const AffineMatrix *affine)
564 % A description of each parameter follows:
566 % o expansion: Method ExpandAffine returns the affine's expansion factor.
568 % o affine: A pointer the affine transform of type AffineMatrix.
571 MagickExport double ExpandAffine(const AffineMatrix *affine)
573 assert(affine != (const AffineMatrix *) NULL);
574 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
582 % 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 %
586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588 % GenerateDifferentialNoise() generates differentual noise.
590 % The format of the GenerateDifferentialNoise method is:
592 % double GenerateDifferentialNoise(RandomInfo *random_info,
593 % const Quantum pixel,const NoiseType noise_type,
594 % const MagickRealType 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 MagickExport double GenerateDifferentialNoise(RandomInfo *random_info,
608 const Quantum pixel,const NoiseType noise_type,const MagickRealType attenuate)
610 #define NoiseEpsilon (attenuate*1.0e-5)
611 #define SigmaUniform (attenuate*4.0)
612 #define SigmaGaussian (attenuate*4.0)
613 #define SigmaImpulse (attenuate*0.10)
614 #define SigmaLaplacian (attenuate*10.0)
615 #define SigmaMultiplicativeGaussian (attenuate*1.0)
616 #define SigmaPoisson (attenuate*0.05)
617 #define TauGaussian (attenuate*20.0)
625 alpha=GetPseudoRandomValue(random_info);
631 noise=(double) pixel+ScaleCharToQuantum((unsigned char)
632 (SigmaUniform*(alpha)));
643 beta=GetPseudoRandomValue(random_info);
644 gamma=sqrt(-2.0*log(alpha));
645 sigma=gamma*cos((double) (2.0*MagickPI*beta));
646 tau=gamma*sin((double) (2.0*MagickPI*beta));
647 noise=(double) pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
651 case MultiplicativeGaussianNoise:
653 if (alpha <= NoiseEpsilon)
654 sigma=(double) QuantumRange;
656 sigma=sqrt(-2.0*log(alpha));
657 beta=GetPseudoRandomValue(random_info);
658 noise=(double) pixel+pixel*SigmaMultiplicativeGaussian*sigma/2.0*
659 cos((double) (2.0*MagickPI*beta));
664 if (alpha < (SigmaImpulse/2.0))
667 if (alpha >= (1.0-(SigmaImpulse/2.0)))
668 noise=(double) QuantumRange;
670 noise=(double) pixel;
677 if (alpha <= NoiseEpsilon)
678 noise=(double) pixel-(double) QuantumRange;
680 noise=(double) pixel+ScaleCharToQuantum((unsigned char)
681 (SigmaLaplacian*log((2.0*alpha))+0.5));
685 if (beta <= (0.5*NoiseEpsilon))
686 noise=(double) (pixel+QuantumRange);
688 noise=(double) pixel-ScaleCharToQuantum((unsigned char)
689 (SigmaLaplacian*log((2.0*beta))+0.5));
700 poisson=exp(-SigmaPoisson*ScaleQuantumToChar(pixel));
701 for (i=0; alpha > poisson; i++)
703 beta=GetPseudoRandomValue(random_info);
706 noise=(double) ScaleCharToQuantum((unsigned char) (i/SigmaPoisson));
711 noise=(double) QuantumRange*alpha;
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 % G e t O p t i m a l K e r n e l W i d t h %
727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729 % GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
730 % filter. Start with the minimum value of 3 pixels and walk out until we drop
731 % below the threshold of one pixel numerical accuracy.
733 % The format of the GetOptimalKernelWidth method is:
735 % size_t GetOptimalKernelWidth(const double radius,
736 % const double sigma)
738 % A description of each parameter follows:
740 % o width: Method GetOptimalKernelWidth returns the optimal width of
741 % a convolution kernel.
743 % o radius: the radius of the Gaussian, in pixels, not counting the center
746 % o sigma: the standard deviation of the Gaussian, in pixels.
749 MagickExport size_t GetOptimalKernelWidth1D(const double radius,
768 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
769 if (radius > MagickEpsilon)
770 return((size_t) (2.0*ceil(radius)+1.0));
772 if (gamma <= MagickEpsilon)
774 alpha=1.0/(2.0*gamma*gamma);
775 beta=(double) (1.0/(MagickSQ2PI*gamma));
780 for (i=(-j); i <= j; i++)
781 normalize+=exp(-((double) (i*i))*alpha)*beta;
782 value=exp(-((double) (j*j))*alpha)*beta/normalize;
783 if ((value < QuantumScale) || (value < MagickEpsilon))
787 return((size_t) (width-2));
790 MagickExport size_t GetOptimalKernelWidth2D(const double radius,
808 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
809 if (radius > MagickEpsilon)
810 return((size_t) (2.0*ceil(radius)+1.0));
812 if (gamma <= MagickEpsilon)
814 alpha=1.0/(2.0*gamma*gamma);
815 beta=(double) (1.0/(Magick2PI*gamma*gamma));
820 for (v=(-j); v <= j; v++)
821 for (u=(-j); u <= j; u++)
822 normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
823 value=exp(-((double) (j*j))*alpha)*beta/normalize;
824 if ((value < QuantumScale) || (value < MagickEpsilon))
828 return((size_t) (width-2));
831 MagickExport size_t GetOptimalKernelWidth(const double radius,
834 return(GetOptimalKernelWidth1D(radius,sigma));