2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Graphic Gems - Graphic Support Methods %
20 % Copyright 1999-2009 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 "magick/studio.h"
44 #include "magick/color-private.h"
45 #include "magick/draw.h"
46 #include "magick/gem.h"
47 #include "magick/image.h"
48 #include "magick/image-private.h"
49 #include "magick/log.h"
50 #include "magick/memory_.h"
51 #include "magick/pixel-private.h"
52 #include "magick/quantum.h"
53 #include "magick/random_.h"
54 #include "magick/resize.h"
55 #include "magick/transform.h"
56 #include "magick/signature-private.h"
59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 % C o n v e r t H S B T o R G B %
67 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 % ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
70 % green, blue) triple.
72 % The format of the ConvertHSBToRGBImage method is:
74 % void ConvertHSBToRGB(const double hue,const double saturation,
75 % const double brightness,Quantum *red,Quantum *green,Quantum *blue)
77 % A description of each parameter follows:
79 % o hue, saturation, brightness: A double value representing a
80 % component of the HSB color space.
82 % o red, green, blue: A pointer to a pixel component of type Quantum.
85 MagickExport void ConvertHSBToRGB(const double hue,const double saturation,
86 const double brightness,Quantum *red,Quantum *green,Quantum *blue)
96 Convert HSB to RGB colorspace.
98 assert(red != (Quantum *) NULL);
99 assert(green != (Quantum *) NULL);
100 assert(blue != (Quantum *) NULL);
101 if (saturation == 0.0)
103 *red=RoundToQuantum((MagickRealType) QuantumRange*brightness);
108 h=6.0*(hue-floor(hue));
109 f=h-floor((double) h);
110 p=brightness*(1.0-saturation);
111 q=brightness*(1.0-saturation*f);
112 t=brightness*(1.0-(saturation*(1.0-f)));
118 *red=RoundToQuantum((MagickRealType) QuantumRange*brightness);
119 *green=RoundToQuantum((MagickRealType) QuantumRange*t);
120 *blue=RoundToQuantum((MagickRealType) QuantumRange*p);
125 *red=RoundToQuantum((MagickRealType) QuantumRange*q);
126 *green=RoundToQuantum((MagickRealType) QuantumRange*brightness);
127 *blue=RoundToQuantum((MagickRealType) QuantumRange*p);
132 *red=RoundToQuantum((MagickRealType) QuantumRange*p);
133 *green=RoundToQuantum((MagickRealType) QuantumRange*brightness);
134 *blue=RoundToQuantum((MagickRealType) QuantumRange*t);
139 *red=RoundToQuantum((MagickRealType) QuantumRange*p);
140 *green=RoundToQuantum((MagickRealType) QuantumRange*q);
141 *blue=RoundToQuantum((MagickRealType) QuantumRange*brightness);
146 *red=RoundToQuantum((MagickRealType) QuantumRange*t);
147 *green=RoundToQuantum((MagickRealType) QuantumRange*p);
148 *blue=RoundToQuantum((MagickRealType) QuantumRange*brightness);
153 *red=RoundToQuantum((MagickRealType) QuantumRange*brightness);
154 *green=RoundToQuantum((MagickRealType) QuantumRange*p);
155 *blue=RoundToQuantum((MagickRealType) QuantumRange*q);
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166 % C o n v e r t H S L T o R G B %
170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
173 % green, blue) triple.
175 % The format of the ConvertHSLToRGBImage method is:
177 % void ConvertHSLToRGB(const double hue,const double saturation,
178 % const double lightness,Quantum *red,Quantum *green,Quantum *blue)
180 % A description of each parameter follows:
182 % o hue, saturation, lightness: A double value representing a
183 % component of the HSL color space.
185 % o red, green, blue: A pointer to a pixel component of type Quantum.
189 static inline MagickRealType ConvertHueToRGB(MagickRealType m1,
190 MagickRealType m2,MagickRealType hue)
197 return(m1+6.0*(m2-m1)*hue);
201 return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
205 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
206 const double lightness,Quantum *red,Quantum *green,Quantum *blue)
216 Convert HSL to RGB colorspace.
218 assert(red != (Quantum *) NULL);
219 assert(green != (Quantum *) NULL);
220 assert(blue != (Quantum *) NULL);
223 *red=RoundToQuantum((MagickRealType) QuantumRange*lightness);
228 if (lightness <= 0.5)
229 m2=lightness*(saturation+1.0);
231 m2=(lightness+saturation)-(lightness*saturation);
233 r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
234 g=ConvertHueToRGB(m1,m2,hue);
235 b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
236 *red=RoundToQuantum((MagickRealType) QuantumRange*r);
237 *green=RoundToQuantum((MagickRealType) QuantumRange*g);
238 *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 % C o n v e r t H W B T o R G B %
250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
255 % The format of the ConvertHWBToRGBImage method is:
257 % void ConvertHWBToRGB(const double hue,const double whiteness,
258 % const double blackness,Quantum *red,Quantum *green,Quantum *blue)
260 % A description of each parameter follows:
262 % o hue, whiteness, blackness: A double value representing a
263 % component of the HWB color space.
265 % o red, green, blue: A pointer to a pixel component of type Quantum.
268 MagickExport void ConvertHWBToRGB(const double hue,const double whiteness,
269 const double blackness,Quantum *red,Quantum *green,Quantum *blue)
283 Convert HWB to RGB colorspace.
285 assert(red != (Quantum *) NULL);
286 assert(green != (Quantum *) NULL);
287 assert(blue != (Quantum *) NULL);
291 *red=RoundToQuantum((MagickRealType) QuantumRange*v);
292 *green=RoundToQuantum((MagickRealType) QuantumRange*v);
293 *blue=RoundToQuantum((MagickRealType) QuantumRange*v);
296 i=(long) floor(6.0*hue);
300 n=whiteness+f*(v-whiteness); /* linear interpolation */
305 case 0: r=v; g=n; b=whiteness; break;
306 case 1: r=n; g=v; b=whiteness; break;
307 case 2: r=whiteness; g=v; b=n; break;
308 case 3: r=whiteness; g=n; b=v; break;
309 case 4: r=n; g=whiteness; b=v; break;
310 case 5: r=v; g=whiteness; b=n; break;
312 *red=RoundToQuantum((MagickRealType) QuantumRange*r);
313 *green=RoundToQuantum((MagickRealType) QuantumRange*g);
314 *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322 % C o n v e r t R G B T o H S B %
326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328 % ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
329 % brightness) triple.
331 % The format of the ConvertRGBToHSB method is:
333 % void ConvertRGBToHSB(const Quantum red,const Quantum green,
334 % const Quantum blue,double *hue,double *saturation,double *brightness)
336 % A description of each parameter follows:
338 % o red, green, blue: A Quantum value representing the red, green, and
339 % blue component of a pixel..
341 % o hue, saturation, brightness: A pointer to a double value representing a
342 % component of the HSB color space.
345 MagickExport void ConvertRGBToHSB(const Quantum red,const Quantum green,
346 const Quantum blue,double *hue,double *saturation,double *brightness)
354 Convert RGB to HSB colorspace.
356 assert(hue != (double *) NULL);
357 assert(saturation != (double *) NULL);
358 assert(brightness != (double *) NULL);
362 min=(MagickRealType) (red < green ? red : green);
363 if ((MagickRealType) blue < min)
364 min=(MagickRealType) blue;
365 max=(MagickRealType) (red > green ? red : green);
366 if ((MagickRealType) blue > max)
367 max=(MagickRealType) blue;
371 *saturation=(double) (delta/max);
372 *brightness=(double) (QuantumScale*max);
375 if ((MagickRealType) red == max)
376 *hue=(double) ((green-(MagickRealType) blue)/delta);
378 if ((MagickRealType) green == max)
379 *hue=(double) (2.0+(blue-(MagickRealType) red)/delta);
381 *hue=(double) (4.0+(red-(MagickRealType) green)/delta);
388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
392 % C o n v e r t R G B T o H S L %
396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
401 % The format of the ConvertRGBToHSL method is:
403 % void ConvertRGBToHSL(const Quantum red,const Quantum green,
404 % const Quantum blue,double *hue,double *saturation,double *lightness)
406 % A description of each parameter follows:
408 % o red, green, blue: A Quantum value representing the red, green, and
409 % blue component of a pixel..
411 % o hue, saturation, lightness: A pointer to a double value representing a
412 % component of the HSL color space.
416 static inline double MagickMax(const double x,const double y)
423 static inline double MagickMin(const double x,const double y)
430 MagickExport void ConvertRGBToHSL(const Quantum red,const Quantum green,
431 const Quantum blue,double *hue,double *saturation,double *lightness)
442 Convert RGB to HSL colorspace.
444 assert(hue != (double *) NULL);
445 assert(saturation != (double *) NULL);
446 assert(lightness != (double *) NULL);
448 g=QuantumScale*green;
450 max=MagickMax(r,MagickMax(g,b));
451 min=MagickMin(r,MagickMin(g,b));
452 *lightness=(double) ((min+max)/2.0);
460 if (*lightness < 0.5)
461 *saturation=(double) (delta/(min+max));
463 *saturation=(double) (delta/(2.0-max-min));
465 *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
468 *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
472 *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 % C o n v e r t R G B T o H W B %
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
491 % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
494 % The format of the ConvertRGBToHWB method is:
496 % void ConvertRGBToHWB(const Quantum red,const Quantum green,
497 % const Quantum blue,double *hue,double *whiteness,double *blackness)
499 % A description of each parameter follows:
501 % o red, green, blue: A Quantum value representing the red, green, and
502 % blue component of a pixel.
504 % o hue, whiteness, blackness: A pointer to a double value representing a
505 % component of the HWB color space.
508 MagickExport void ConvertRGBToHWB(const Quantum red,const Quantum green,
509 const Quantum blue,double *hue,double *whiteness,double *blackness)
520 Convert RGB to HWB colorspace.
522 assert(hue != (double *) NULL);
523 assert(whiteness != (double *) NULL);
524 assert(blackness != (double *) NULL);
525 w=(MagickRealType) MagickMin((double) red,MagickMin((double) green,(double)
527 v=(MagickRealType) MagickMax((double) red,MagickMax((double) green,(double)
529 *blackness=1.0-QuantumScale*v;
530 *whiteness=QuantumScale*w;
536 f=((MagickRealType) red == w) ? green-(MagickRealType) blue :
537 (((MagickRealType) green == w) ? blue-(MagickRealType) red : red-
538 (MagickRealType) green);
539 i=((MagickRealType) red == w) ? 3 : (((MagickRealType) green == w) ? 5 : 1);
540 *hue=((double) i-f/(v-1.0*w))/6.0;
544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
548 % E x p a n d A f f i n e %
552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554 % ExpandAffine() computes the affine's expansion factor, i.e. the square root
555 % of the factor by which the affine transform affects area. In an affine
556 % transform composed of scaling, rotation, shearing, and translation, returns
557 % the amount of scaling.
559 % The format of the ExpandAffine method is:
561 % double ExpandAffine(const AffineMatrix *affine)
563 % A description of each parameter follows:
565 % o expansion: Method ExpandAffine returns the affine's expansion factor.
567 % o affine: A pointer the affine transform of type AffineMatrix.
570 MagickExport double ExpandAffine(const AffineMatrix *affine)
572 assert(affine != (const AffineMatrix *) NULL);
573 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
581 % 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 %
585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
587 % GenerateDifferentialNoise()
589 % The format of the GenerateDifferentialNoise method is:
591 % double GenerateDifferentialNoise(RandomInfo *random_info,
592 % const Quantum pixel,const NoiseType noise_type,
593 % const MagickRealType attenuate)
595 % A description of each parameter follows:
597 % o random_info: the random info.
599 % o pixel: noise is relative to this pixel value.
601 % o noise_type: the type of noise.
603 % o attenuate: attenuate the noise.
606 MagickExport double GenerateDifferentialNoise(RandomInfo *random_info,
607 const Quantum pixel,const NoiseType noise_type,const MagickRealType attenuate)
609 #define NoiseEpsilon (attenuate*1.0e-5)
610 #define SigmaUniform ScaleCharToQuantum((unsigned char) (attenuate*4.0+0.5))
611 #define SigmaGaussian ScaleCharToQuantum((unsigned char) (attenuate*4.0+0.5))
612 #define SigmaImpulse (attenuate*0.10)
613 #define SigmaLaplacian ScaleCharToQuantum((unsigned char) (attenuate*10.0+0.5))
614 #define SigmaMultiplicativeGaussian \
615 ScaleCharToQuantum((unsigned char) (attenuate*1.0+0.5))
616 #define SigmaPoisson (attenuate*0.05)
617 #define TauGaussian ScaleCharToQuantum((unsigned char) (attenuate*20.0+0.5))
625 alpha=GetPseudoRandomValue(random_info);
633 noise=(MagickRealType) pixel+SigmaUniform*(alpha-0.5);
641 beta=GetPseudoRandomValue(random_info);
642 sigma=sqrt(-2.0*log((double) alpha))*cos((double) (2.0*MagickPI*beta));
643 tau=sqrt(-2.0*log((double) alpha))*sin((double) (2.0*MagickPI*beta));
644 noise=(MagickRealType) pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
648 case MultiplicativeGaussianNoise:
650 if (alpha <= NoiseEpsilon)
651 sigma=(MagickRealType) QuantumRange;
653 sigma=sqrt(-2.0*log((double) alpha));
654 beta=GetPseudoRandomValue(random_info);
655 noise=(MagickRealType) pixel+pixel*SigmaMultiplicativeGaussian*sigma/2.0*
656 cos((double) (2.0*MagickPI*beta));
661 if (alpha < (SigmaImpulse/2.0))
664 if (alpha >= (1.0-(SigmaImpulse/2.0)))
665 noise=(MagickRealType) QuantumRange;
667 noise=(MagickRealType) pixel;
674 if (alpha <= NoiseEpsilon)
675 noise=(MagickRealType) pixel-(MagickRealType) QuantumRange;
677 noise=(MagickRealType) pixel+ScaleCharToQuantum((unsigned char)
678 (SigmaLaplacian*log((double) (2.0*alpha))+0.5));
682 if (beta <= (0.5*NoiseEpsilon))
683 noise=(MagickRealType) (pixel+QuantumRange);
685 noise=(MagickRealType) pixel-ScaleCharToQuantum((unsigned char)
686 (SigmaLaplacian*log((double) (2.0*beta))+0.5));
697 poisson=exp(-SigmaPoisson*(double) ScaleQuantumToChar(pixel));
698 for (i=0; alpha > poisson; i++)
700 beta=GetPseudoRandomValue(random_info);
703 noise=(MagickRealType) ScaleCharToQuantum((unsigned char)
709 noise=(MagickRealType) QuantumRange*GetPseudoRandomValue(random_info);
717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721 % G e t O p t i m a l K e r n e l W i d t h %
725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
727 % GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
728 % filter. Start with the minimum value of 3 pixels and walk out until we drop
729 % below the threshold of one pixel numerical accuracy.
731 % The format of the GetOptimalKernelWidth method is:
733 % unsigned long GetOptimalKernelWidth(const double radius,
734 % const double sigma)
736 % A description of each parameter follows:
738 % o width: Method GetOptimalKernelWidth returns the optimal width of
739 % a convolution kernel.
741 % o radius: the radius of the Gaussian, in pixels, not counting the center
744 % o sigma: the standard deviation of the Gaussian, in pixels.
747 MagickExport unsigned long GetOptimalKernelWidth1D(const double radius,
760 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
762 return((unsigned long) (2.0*ceil(radius)+1.0));
763 if (fabs(sigma) <= MagickEpsilon)
768 for (u=(-width/2); u <= (width/2); u++)
769 normalize+=exp(-((double) u*u)/(2.0*sigma*sigma))/(MagickSQ2PI*sigma);
771 value=exp(-((double) u*u)/(2.0*sigma*sigma))/(MagickSQ2PI*sigma)/normalize;
772 if ((long) (QuantumRange*value) <= 0L)
776 return((unsigned long) (width-2));
779 MagickExport unsigned long GetOptimalKernelWidth2D(const double radius,
795 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
797 return((unsigned long) (2.0*ceil(radius)+1.0));
798 if (fabs(sigma) <= MagickEpsilon)
803 for (v=(-width/2); v <= (width/2); v++)
805 for (u=(-width/2); u <= (width/2); u++)
807 alpha=exp(-((double) u*u+v*v)/(2.0*sigma*sigma));
808 normalize+=alpha/(2.0*MagickPI*sigma*sigma);
812 value=exp(-((double) v*v)/(2.0*sigma*sigma))/normalize;
813 if ((long) (QuantumRange*value) <= 0L)
817 return((unsigned long) (width-2));
820 MagickExport unsigned long GetOptimalKernelWidth(const double radius,
823 return(GetOptimalKernelWidth1D(radius,sigma));