2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Graphic Gems - Graphic Support Methods %
20 % Copyright 1999-2010 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=ClampToQuantum((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)));
120 *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
121 *green=ClampToQuantum((MagickRealType) QuantumRange*t);
122 *blue=ClampToQuantum((MagickRealType) QuantumRange*p);
127 *red=ClampToQuantum((MagickRealType) QuantumRange*q);
128 *green=ClampToQuantum((MagickRealType) QuantumRange*brightness);
129 *blue=ClampToQuantum((MagickRealType) QuantumRange*p);
134 *red=ClampToQuantum((MagickRealType) QuantumRange*p);
135 *green=ClampToQuantum((MagickRealType) QuantumRange*brightness);
136 *blue=ClampToQuantum((MagickRealType) QuantumRange*t);
141 *red=ClampToQuantum((MagickRealType) QuantumRange*p);
142 *green=ClampToQuantum((MagickRealType) QuantumRange*q);
143 *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
148 *red=ClampToQuantum((MagickRealType) QuantumRange*t);
149 *green=ClampToQuantum((MagickRealType) QuantumRange*p);
150 *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
155 *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
156 *green=ClampToQuantum((MagickRealType) QuantumRange*p);
157 *blue=ClampToQuantum((MagickRealType) QuantumRange*q);
164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 % C o n v e r t H S L T o R G B %
172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
175 % green, blue) triple.
177 % The format of the ConvertHSLToRGBImage method is:
179 % void ConvertHSLToRGB(const double hue,const double saturation,
180 % const double lightness,Quantum *red,Quantum *green,Quantum *blue)
182 % A description of each parameter follows:
184 % o hue, saturation, lightness: A double value representing a
185 % component of the HSL color space.
187 % o red, green, blue: A pointer to a pixel component of type Quantum.
191 static inline MagickRealType ConvertHueToRGB(MagickRealType m1,
192 MagickRealType m2,MagickRealType 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,Quantum *red,Quantum *green,Quantum *blue)
218 Convert HSL to RGB colorspace.
220 assert(red != (Quantum *) NULL);
221 assert(green != (Quantum *) NULL);
222 assert(blue != (Quantum *) NULL);
225 *red=ClampToQuantum((MagickRealType) QuantumRange*lightness);
231 m2=lightness*(saturation+1.0);
233 m2=(lightness+saturation)-(lightness*saturation);
237 r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
238 g=ConvertHueToRGB(m1,m2,hue);
239 b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
240 *red=ClampToQuantum((MagickRealType) QuantumRange*r);
241 *green=ClampToQuantum((MagickRealType) QuantumRange*g);
242 *blue=ClampToQuantum((MagickRealType) QuantumRange*b);
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 % C o n v e r t H W B T o R G B %
254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
259 % The format of the ConvertHWBToRGBImage method is:
261 % void ConvertHWBToRGB(const double hue,const double whiteness,
262 % const double blackness,Quantum *red,Quantum *green,Quantum *blue)
264 % A description of each parameter follows:
266 % o hue, whiteness, blackness: A double value representing a
267 % component of the HWB color space.
269 % o red, green, blue: A pointer to a pixel component of type Quantum.
272 MagickExport void ConvertHWBToRGB(const double hue,const double whiteness,
273 const double blackness,Quantum *red,Quantum *green,Quantum *blue)
287 Convert HWB to RGB colorspace.
289 assert(red != (Quantum *) NULL);
290 assert(green != (Quantum *) NULL);
291 assert(blue != (Quantum *) NULL);
295 *red=ClampToQuantum((MagickRealType) QuantumRange*v);
296 *green=ClampToQuantum((MagickRealType) QuantumRange*v);
297 *blue=ClampToQuantum((MagickRealType) QuantumRange*v);
300 i=(long) floor(6.0*hue);
304 n=whiteness+f*(v-whiteness); /* linear interpolation */
309 case 0: r=v; g=n; b=whiteness; break;
310 case 1: r=n; g=v; b=whiteness; break;
311 case 2: r=whiteness; g=v; b=n; break;
312 case 3: r=whiteness; g=n; b=v; break;
313 case 4: r=n; g=whiteness; b=v; break;
314 case 5: r=v; g=whiteness; b=n; break;
316 *red=ClampToQuantum((MagickRealType) QuantumRange*r);
317 *green=ClampToQuantum((MagickRealType) QuantumRange*g);
318 *blue=ClampToQuantum((MagickRealType) QuantumRange*b);
322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 % C o n v e r t R G B T o H S B %
330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332 % ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
333 % brightness) triple.
335 % The format of the ConvertRGBToHSB method is:
337 % void ConvertRGBToHSB(const Quantum red,const Quantum green,
338 % const Quantum blue,double *hue,double *saturation,double *brightness)
340 % A description of each parameter follows:
342 % o red, green, blue: A Quantum value representing the red, green, and
343 % blue component of a pixel..
345 % o hue, saturation, brightness: A pointer to a double value representing a
346 % component of the HSB color space.
349 MagickExport void ConvertRGBToHSB(const Quantum red,const Quantum green,
350 const Quantum blue,double *hue,double *saturation,double *brightness)
358 Convert RGB to HSB colorspace.
360 assert(hue != (double *) NULL);
361 assert(saturation != (double *) NULL);
362 assert(brightness != (double *) NULL);
366 min=(MagickRealType) (red < green ? red : green);
367 if ((MagickRealType) blue < min)
368 min=(MagickRealType) blue;
369 max=(MagickRealType) (red > green ? red : green);
370 if ((MagickRealType) blue > max)
371 max=(MagickRealType) blue;
375 *saturation=(double) (delta/max);
376 *brightness=(double) (QuantumScale*max);
379 if ((MagickRealType) red == max)
380 *hue=(double) ((green-(MagickRealType) blue)/delta);
382 if ((MagickRealType) green == max)
383 *hue=(double) (2.0+(blue-(MagickRealType) red)/delta);
385 *hue=(double) (4.0+(red-(MagickRealType) green)/delta);
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 % C o n v e r t R G B T o H S L %
402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404 % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
407 % The format of the ConvertRGBToHSL method is:
409 % void ConvertRGBToHSL(const Quantum red,const Quantum green,
410 % const Quantum blue,double *hue,double *saturation,double *lightness)
412 % A description of each parameter follows:
414 % o red, green, blue: A Quantum value representing the red, green, and
415 % blue component of a pixel..
417 % o hue, saturation, lightness: A pointer to a double value representing a
418 % component of the HSL color space.
422 static inline double MagickMax(const double x,const double y)
429 static inline double MagickMin(const double x,const double y)
436 MagickExport void ConvertRGBToHSL(const Quantum red,const Quantum green,
437 const Quantum blue,double *hue,double *saturation,double *lightness)
448 Convert RGB to HSL colorspace.
450 assert(hue != (double *) NULL);
451 assert(saturation != (double *) NULL);
452 assert(lightness != (double *) NULL);
454 g=QuantumScale*green;
456 max=MagickMax(r,MagickMax(g,b));
457 min=MagickMin(r,MagickMin(g,b));
458 *lightness=(double) ((min+max)/2.0);
466 if (*lightness < 0.5)
467 *saturation=(double) (delta/(min+max));
469 *saturation=(double) (delta/(2.0-max-min));
471 *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
474 *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
478 *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
491 % C o n v e r t R G B T o H W B %
495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
497 % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
500 % The format of the ConvertRGBToHWB method is:
502 % void ConvertRGBToHWB(const Quantum red,const Quantum green,
503 % const Quantum blue,double *hue,double *whiteness,double *blackness)
505 % A description of each parameter follows:
507 % o red, green, blue: A Quantum value representing the red, green, and
508 % blue component of a pixel.
510 % o hue, whiteness, blackness: A pointer to a double value representing a
511 % component of the HWB color space.
514 MagickExport void ConvertRGBToHWB(const Quantum red,const Quantum green,
515 const Quantum blue,double *hue,double *whiteness,double *blackness)
526 Convert RGB to HWB colorspace.
528 assert(hue != (double *) NULL);
529 assert(whiteness != (double *) NULL);
530 assert(blackness != (double *) NULL);
531 w=(MagickRealType) MagickMin((double) red,MagickMin((double) green,(double)
533 v=(MagickRealType) MagickMax((double) red,MagickMax((double) green,(double)
535 *blackness=1.0-QuantumScale*v;
536 *whiteness=QuantumScale*w;
542 f=((MagickRealType) red == w) ? green-(MagickRealType) blue :
543 (((MagickRealType) green == w) ? blue-(MagickRealType) red : red-
544 (MagickRealType) green);
545 i=((MagickRealType) red == w) ? 3 : (((MagickRealType) green == w) ? 5 : 1);
546 *hue=((double) i-f/(v-1.0*w))/6.0;
550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554 % E x p a n d A f f i n e %
558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
560 % ExpandAffine() computes the affine's expansion factor, i.e. the square root
561 % of the factor by which the affine transform affects area. In an affine
562 % transform composed of scaling, rotation, shearing, and translation, returns
563 % the amount of scaling.
565 % The format of the ExpandAffine method is:
567 % double ExpandAffine(const AffineMatrix *affine)
569 % A description of each parameter follows:
571 % o expansion: Method ExpandAffine returns the affine's expansion factor.
573 % o affine: A pointer the affine transform of type AffineMatrix.
576 MagickExport double ExpandAffine(const AffineMatrix *affine)
578 assert(affine != (const AffineMatrix *) NULL);
579 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
587 % 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 %
591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593 % GenerateDifferentialNoise() generates differentual noise.
595 % The format of the GenerateDifferentialNoise method is:
597 % double GenerateDifferentialNoise(RandomInfo *random_info,
598 % const Quantum pixel,const NoiseType noise_type,
599 % const MagickRealType attenuate)
601 % A description of each parameter follows:
603 % o random_info: the random info.
605 % o pixel: noise is relative to this pixel value.
607 % o noise_type: the type of noise.
609 % o attenuate: attenuate the noise.
612 MagickExport double GenerateDifferentialNoise(RandomInfo *random_info,
613 const Quantum pixel,const NoiseType noise_type,const MagickRealType attenuate)
615 #define NoiseEpsilon (attenuate*1.0e-5)
616 #define SigmaUniform (attenuate*4.0)
617 #define SigmaGaussian (attenuate*4.0)
618 #define SigmaImpulse (attenuate*0.10)
619 #define SigmaLaplacian (attenuate*10.0)
620 #define SigmaMultiplicativeGaussian (attenuate*1.0)
621 #define SigmaPoisson (attenuate*0.05)
622 #define TauGaussian (attenuate*20.0)
630 alpha=GetPseudoRandomValue(random_info);
636 noise=(double) pixel+ScaleCharToQuantum((unsigned char)
637 (SigmaUniform*(alpha)));
648 beta=GetPseudoRandomValue(random_info);
649 gamma=sqrt(-2.0*log(alpha));
650 sigma=gamma*cos(2.0*MagickPI*beta);
651 tau=gamma*sin(2.0*MagickPI*beta);
652 noise=(double) pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
656 case MultiplicativeGaussianNoise:
658 if (alpha <= NoiseEpsilon)
659 sigma=(double) QuantumRange;
661 sigma=sqrt(-2.0*log(alpha));
662 beta=GetPseudoRandomValue(random_info);
663 noise=(double) pixel+pixel*SigmaMultiplicativeGaussian*sigma/2.0*
664 cos((2.0*MagickPI*beta));
669 if (alpha < (SigmaImpulse/2.0))
672 if (alpha >= (1.0-(SigmaImpulse/2.0)))
673 noise=(double) QuantumRange;
675 noise=(double) pixel;
682 if (alpha <= NoiseEpsilon)
683 noise=(double) pixel-(double) QuantumRange;
685 noise=(double) pixel+ScaleCharToQuantum((unsigned char)
686 (SigmaLaplacian*log((2.0*alpha))+0.5));
690 if (beta <= (0.5*NoiseEpsilon))
691 noise=(double) (pixel+QuantumRange);
693 noise=(double) pixel-ScaleCharToQuantum((unsigned char)
694 (SigmaLaplacian*log((2.0*beta))+0.5));
705 poisson=exp(-SigmaPoisson*ScaleQuantumToChar(pixel));
706 for (i=0; alpha > poisson; i++)
708 beta=GetPseudoRandomValue(random_info);
711 noise=(double) ScaleCharToQuantum((unsigned char) (i/SigmaPoisson));
716 noise=(double) QuantumRange*alpha;
724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
728 % G e t O p t i m a l K e r n e l W i d t h %
732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
734 % GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
735 % filter. Start with the minimum value of 3 pixels and walk out until we drop
736 % below the threshold of one pixel numerical accuracy.
738 % The format of the GetOptimalKernelWidth method is:
740 % unsigned long GetOptimalKernelWidth(const double radius,
741 % const double sigma)
743 % A description of each parameter follows:
745 % o width: Method GetOptimalKernelWidth returns the optimal width of
746 % a convolution kernel.
748 % o radius: the radius of the Gaussian, in pixels, not counting the center
751 % o sigma: the standard deviation of the Gaussian, in pixels.
754 MagickExport unsigned long GetOptimalKernelWidth1D(const double radius,
757 #define MagickSigma (fabs(sigma) <= MagickEpsilon ? 1.0 : sigma)
772 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
773 if (radius > MagickEpsilon)
774 return((unsigned long) (2.0*ceil(radius)+1.0));
775 if (fabs(sigma) <= MagickEpsilon)
781 for (i=(-j); i <= j; i++)
782 normalize+=exp(-((double) i*i)/(2.0*MagickSigma*MagickSigma))/
783 (MagickSQ2PI*MagickSigma);
784 value=exp(-((double) j*j)/(2.0*MagickSigma*MagickSigma))/
785 (MagickSQ2PI*MagickSigma)/normalize;
786 if ((value < QuantumScale) || (value < MagickEpsilon))
790 return((unsigned long) (width-2));
793 MagickExport unsigned long GetOptimalKernelWidth2D(const double radius,
808 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
809 if (radius > MagickEpsilon)
810 return((unsigned long) (2.0*ceil(radius)+1.0));
811 if (fabs(sigma) <= MagickEpsilon)
817 for (v=(-j); v <= j; v++)
819 for (u=(-j); u <= j; u++)
820 normalize+=exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
821 (2.0*MagickPI*MagickSigma*MagickSigma);
823 value=exp(-((double) j*j)/(2.0*MagickSigma*MagickSigma))/normalize;
824 if ((value < QuantumScale) || (value < MagickEpsilon))
828 return((unsigned long) (width-2));
831 MagickExport unsigned long GetOptimalKernelWidth(const double radius,
834 return(GetOptimalKernelWidth1D(radius,sigma));