]> granicus.if.org Git - imagemagick/blob - magick/gem.c
(no commit message)
[imagemagick] / magick / gem.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                              GGGG  EEEEE  M   M                             %
7 %                             G      E      MM MM                             %
8 %                             G GG   EEE    M M M                             %
9 %                             G   G  E      M   M                             %
10 %                              GGGG  EEEEE  M   M                             %
11 %                                                                             %
12 %                                                                             %
13 %                    Graphic Gems - Graphic Support Methods                   %
14 %                                                                             %
15 %                               Software Design                               %
16 %                                 John Cristy                                 %
17 %                                 August 1996                                 %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
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.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 %
38 */
39 \f
40 /*
41   Include declarations.
42 */
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"
57 \f
58 /*
59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60 %                                                                             %
61 %                                                                             %
62 %                                                                             %
63 %   C o n v e r t H S B T o R G B                                             %
64 %                                                                             %
65 %                                                                             %
66 %                                                                             %
67 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
68 %
69 %  ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
70 %  green, blue) triple.
71 %
72 %  The format of the ConvertHSBToRGBImage method is:
73 %
74 %      void ConvertHSBToRGB(const double hue,const double saturation,
75 %        const double brightness,Quantum *red,Quantum *green,Quantum *blue)
76 %
77 %  A description of each parameter follows:
78 %
79 %    o hue, saturation, brightness: A double value representing a
80 %      component of the HSB color space.
81 %
82 %    o red, green, blue: A pointer to a pixel component of type Quantum.
83 %
84 */
85 MagickExport void ConvertHSBToRGB(const double hue,const double saturation,
86   const double brightness,Quantum *red,Quantum *green,Quantum *blue)
87 {
88   MagickRealType
89     f,
90     h,
91     p,
92     q,
93     t;
94
95   /*
96     Convert HSB to RGB colorspace.
97   */
98   assert(red != (Quantum *) NULL);
99   assert(green != (Quantum *) NULL);
100   assert(blue != (Quantum *) NULL);
101   if (saturation == 0.0)
102     {
103       *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
104       *green=(*red);
105       *blue=(*red);
106       return;
107     }
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)));
113   if (p < 0.0)
114     return;
115   switch ((int) h)
116   {
117     case 0:
118     default:
119     {
120       *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
121       *green=ClampToQuantum((MagickRealType) QuantumRange*t);
122       *blue=ClampToQuantum((MagickRealType) QuantumRange*p);
123       break;
124     }
125     case 1:
126     {
127       *red=ClampToQuantum((MagickRealType) QuantumRange*q);
128       *green=ClampToQuantum((MagickRealType) QuantumRange*brightness);
129       *blue=ClampToQuantum((MagickRealType) QuantumRange*p);
130       break;
131     }
132     case 2:
133     {
134       *red=ClampToQuantum((MagickRealType) QuantumRange*p);
135       *green=ClampToQuantum((MagickRealType) QuantumRange*brightness);
136       *blue=ClampToQuantum((MagickRealType) QuantumRange*t);
137       break;
138     }
139     case 3:
140     {
141       *red=ClampToQuantum((MagickRealType) QuantumRange*p);
142       *green=ClampToQuantum((MagickRealType) QuantumRange*q);
143       *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
144       break;
145     }
146     case 4:
147     {
148       *red=ClampToQuantum((MagickRealType) QuantumRange*t);
149       *green=ClampToQuantum((MagickRealType) QuantumRange*p);
150       *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
151       break;
152     }
153     case 5:
154     {
155       *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
156       *green=ClampToQuantum((MagickRealType) QuantumRange*p);
157       *blue=ClampToQuantum((MagickRealType) QuantumRange*q);
158       break;
159     }
160   }
161 }
162 \f
163 /*
164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
165 %                                                                             %
166 %                                                                             %
167 %                                                                             %
168 %   C o n v e r t H S L T o R G B                                             %
169 %                                                                             %
170 %                                                                             %
171 %                                                                             %
172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 %
174 %  ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
175 %  green, blue) triple.
176 %
177 %  The format of the ConvertHSLToRGBImage method is:
178 %
179 %      void ConvertHSLToRGB(const double hue,const double saturation,
180 %        const double lightness,Quantum *red,Quantum *green,Quantum *blue)
181 %
182 %  A description of each parameter follows:
183 %
184 %    o hue, saturation, lightness: A double value representing a
185 %      component of the HSL color space.
186 %
187 %    o red, green, blue: A pointer to a pixel component of type Quantum.
188 %
189 */
190
191 static inline MagickRealType ConvertHueToRGB(MagickRealType m1,
192   MagickRealType m2,MagickRealType hue)
193 {
194   if (hue < 0.0)
195     hue+=1.0;
196   if (hue > 1.0)
197     hue-=1.0;
198   if ((6.0*hue) < 1.0)
199     return(m1+6.0*(m2-m1)*hue);
200   if ((2.0*hue) < 1.0)
201     return(m2);
202   if ((3.0*hue) < 2.0)
203     return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
204   return(m1);
205 }
206
207 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
208   const double lightness,Quantum *red,Quantum *green,Quantum *blue)
209 {
210   MagickRealType
211     b,
212     g,
213     r,
214     m1,
215     m2;
216
217   /*
218     Convert HSL to RGB colorspace.
219   */
220   assert(red != (Quantum *) NULL);
221   assert(green != (Quantum *) NULL);
222   assert(blue != (Quantum *) NULL);
223   if (saturation == 0)
224     {
225       *red=ClampToQuantum((MagickRealType) QuantumRange*lightness);
226       *green=(*red);
227       *blue=(*red);
228       return;
229     }
230   if (lightness < 0.5)
231     m2=lightness*(saturation+1.0);
232   else
233     m2=(lightness+saturation)-(lightness*saturation);
234   m1=2.0*lightness-m2;
235   if (m1 <= 0.0)
236     return;
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);
243 }
244 \f
245 /*
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 %                                                                             %
248 %                                                                             %
249 %                                                                             %
250 %   C o n v e r t H W B T o R G B                                             %
251 %                                                                             %
252 %                                                                             %
253 %                                                                             %
254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
255 %
256 %  ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
257 %  blue) triple.
258 %
259 %  The format of the ConvertHWBToRGBImage method is:
260 %
261 %      void ConvertHWBToRGB(const double hue,const double whiteness,
262 %        const double blackness,Quantum *red,Quantum *green,Quantum *blue)
263 %
264 %  A description of each parameter follows:
265 %
266 %    o hue, whiteness, blackness: A double value representing a
267 %      component of the HWB color space.
268 %
269 %    o red, green, blue: A pointer to a pixel component of type Quantum.
270 %
271 */
272 MagickExport void ConvertHWBToRGB(const double hue,const double whiteness,
273   const double blackness,Quantum *red,Quantum *green,Quantum *blue)
274 {
275   MagickRealType
276     b,
277     f,
278     g,
279     n,
280     r,
281     v;
282
283   register long
284     i;
285
286   /*
287     Convert HWB to RGB colorspace.
288   */
289   assert(red != (Quantum *) NULL);
290   assert(green != (Quantum *) NULL);
291   assert(blue != (Quantum *) NULL);
292   v=1.0-blackness;
293   if (hue == 0.0)
294     {
295       *red=ClampToQuantum((MagickRealType) QuantumRange*v);
296       *green=ClampToQuantum((MagickRealType) QuantumRange*v);
297       *blue=ClampToQuantum((MagickRealType) QuantumRange*v);
298       return;
299     }
300   i=(long) floor(6.0*hue);
301   f=6.0*hue-i;
302   if ((i & 0x01) != 0)
303     f=1.0-f;
304   n=whiteness+f*(v-whiteness);  /* linear interpolation */
305   switch (i)
306   {
307     default:
308     case 6:
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;
315   }
316   *red=ClampToQuantum((MagickRealType) QuantumRange*r);
317   *green=ClampToQuantum((MagickRealType) QuantumRange*g);
318   *blue=ClampToQuantum((MagickRealType) QuantumRange*b);
319 }
320 \f
321 /*
322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323 %                                                                             %
324 %                                                                             %
325 %                                                                             %
326 %   C o n v e r t R G B T o H S B                                             %
327 %                                                                             %
328 %                                                                             %
329 %                                                                             %
330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331 %
332 %  ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
333 %  brightness) triple.
334 %
335 %  The format of the ConvertRGBToHSB method is:
336 %
337 %      void ConvertRGBToHSB(const Quantum red,const Quantum green,
338 %        const Quantum blue,double *hue,double *saturation,double *brightness)
339 %
340 %  A description of each parameter follows:
341 %
342 %    o red, green, blue: A Quantum value representing the red, green, and
343 %      blue component of a pixel..
344 %
345 %    o hue, saturation, brightness: A pointer to a double value representing a
346 %      component of the HSB color space.
347 %
348 */
349 MagickExport void ConvertRGBToHSB(const Quantum red,const Quantum green,
350   const Quantum blue,double *hue,double *saturation,double *brightness)
351 {
352   MagickRealType
353     delta,
354     max,
355     min;
356
357   /*
358     Convert RGB to HSB colorspace.
359   */
360   assert(hue != (double *) NULL);
361   assert(saturation != (double *) NULL);
362   assert(brightness != (double *) NULL);
363   *hue=0.0;
364   *saturation=0.0;
365   *brightness=0.0;
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;
372   if (max == 0.0)
373     return;
374   delta=max-min;
375   *saturation=(double) (delta/max);
376   *brightness=(double) (QuantumScale*max);
377   if (delta == 0.0)
378     return;
379   if ((MagickRealType) red == max)
380     *hue=(double) ((green-(MagickRealType) blue)/delta);
381   else
382     if ((MagickRealType) green == max)
383       *hue=(double) (2.0+(blue-(MagickRealType) red)/delta);
384     else
385       *hue=(double) (4.0+(red-(MagickRealType) green)/delta);
386   *hue/=6.0;
387   if (*hue < 0.0)
388     *hue+=1.0;
389   if (*hue > 1.0)
390     *hue-=1.0;
391 }
392 \f
393 /*
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 %                                                                             %
396 %                                                                             %
397 %                                                                             %
398 %   C o n v e r t R G B T o H S L                                             %
399 %                                                                             %
400 %                                                                             %
401 %                                                                             %
402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
403 %
404 %  ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
405 %  lightness) triple.
406 %
407 %  The format of the ConvertRGBToHSL method is:
408 %
409 %      void ConvertRGBToHSL(const Quantum red,const Quantum green,
410 %        const Quantum blue,double *hue,double *saturation,double *lightness)
411 %
412 %  A description of each parameter follows:
413 %
414 %    o red, green, blue: A Quantum value representing the red, green, and
415 %      blue component of a pixel..
416 %
417 %    o hue, saturation, lightness: A pointer to a double value representing a
418 %      component of the HSL color space.
419 %
420 */
421
422 static inline double MagickMax(const double x,const double y)
423 {
424   if (x > y)
425     return(x);
426   return(y);
427 }
428
429 static inline double MagickMin(const double x,const double y)
430 {
431   if (x < y)
432     return(x);
433   return(y);
434 }
435
436 MagickExport void ConvertRGBToHSL(const Quantum red,const Quantum green,
437   const Quantum blue,double *hue,double *saturation,double *lightness)
438 {
439   MagickRealType
440     b,
441     delta,
442     g,
443     max,
444     min,
445     r;
446
447   /*
448     Convert RGB to HSL colorspace.
449   */
450   assert(hue != (double *) NULL);
451   assert(saturation != (double *) NULL);
452   assert(lightness != (double *) NULL);
453   r=QuantumScale*red;
454   g=QuantumScale*green;
455   b=QuantumScale*blue;
456   max=MagickMax(r,MagickMax(g,b));
457   min=MagickMin(r,MagickMin(g,b));
458   *lightness=(double) ((min+max)/2.0);
459   delta=max-min;
460   if (delta == 0.0)
461     {
462       *hue=0.0;
463       *saturation=0.0;
464       return;
465     }
466   if (*lightness < 0.5)
467     *saturation=(double) (delta/(min+max));
468   else
469     *saturation=(double) (delta/(2.0-max-min));
470   if (r == max)
471     *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
472   else
473     if (g == max)
474       *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
475         delta;
476     else
477       if (b == max)
478         *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
479           (delta/2.0)))/delta;
480   if (*hue < 0.0)
481     *hue+=1.0;
482   if (*hue > 1.0)
483     *hue-=1.0;
484 }
485 \f
486 /*
487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
488 %                                                                             %
489 %                                                                             %
490 %                                                                             %
491 %   C o n v e r t R G B T o H W B                                             %
492 %                                                                             %
493 %                                                                             %
494 %                                                                             %
495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
496 %
497 %  ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
498 %  blackness) triple.
499 %
500 %  The format of the ConvertRGBToHWB method is:
501 %
502 %      void ConvertRGBToHWB(const Quantum red,const Quantum green,
503 %        const Quantum blue,double *hue,double *whiteness,double *blackness)
504 %
505 %  A description of each parameter follows:
506 %
507 %    o red, green, blue: A Quantum value representing the red, green, and
508 %      blue component of a pixel.
509 %
510 %    o hue, whiteness, blackness: A pointer to a double value representing a
511 %      component of the HWB color space.
512 %
513 */
514 MagickExport void ConvertRGBToHWB(const Quantum red,const Quantum green,
515   const Quantum blue,double *hue,double *whiteness,double *blackness)
516 {
517   MagickRealType
518     f,
519     v,
520     w;
521
522   register long
523     i;
524
525   /*
526     Convert RGB to HWB colorspace.
527   */
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)
532     blue));
533   v=(MagickRealType) MagickMax((double) red,MagickMax((double) green,(double)
534     blue));
535   *blackness=1.0-QuantumScale*v;
536   *whiteness=QuantumScale*w;
537   if (v == w)
538     {
539       *hue=0.0;
540       return;
541     }
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;
547 }
548 \f
549 /*
550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551 %                                                                             %
552 %                                                                             %
553 %                                                                             %
554 %   E x p a n d A f f i n e                                                   %
555 %                                                                             %
556 %                                                                             %
557 %                                                                             %
558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559 %
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.
564 %
565 %  The format of the ExpandAffine method is:
566 %
567 %      double ExpandAffine(const AffineMatrix *affine)
568 %
569 %  A description of each parameter follows:
570 %
571 %    o expansion: Method ExpandAffine returns the affine's expansion factor.
572 %
573 %    o affine: A pointer the affine transform of type AffineMatrix.
574 %
575 */
576 MagickExport double ExpandAffine(const AffineMatrix *affine)
577 {
578   assert(affine != (const AffineMatrix *) NULL);
579   return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
580 }
581 \f
582 /*
583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
584 %                                                                             %
585 %                                                                             %
586 %                                                                             %
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                         %
588 %                                                                             %
589 %                                                                             %
590 %                                                                             %
591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592 %
593 %  GenerateDifferentialNoise() generates differentual noise.
594 %
595 %  The format of the GenerateDifferentialNoise method is:
596 %
597 %      double GenerateDifferentialNoise(RandomInfo *random_info,
598 %        const Quantum pixel,const NoiseType noise_type,
599 %        const MagickRealType attenuate)
600 %
601 %  A description of each parameter follows:
602 %
603 %    o random_info: the random info.
604 %
605 %    o pixel: noise is relative to this pixel value.
606 %
607 %    o noise_type: the type of noise.
608 %
609 %    o attenuate:  attenuate the noise.
610 %
611 */
612 MagickExport double GenerateDifferentialNoise(RandomInfo *random_info,
613   const Quantum pixel,const NoiseType noise_type,const MagickRealType attenuate)
614 {
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)
623
624   double
625     alpha,
626     beta,
627     noise,
628     sigma;
629
630   alpha=GetPseudoRandomValue(random_info);
631   switch (noise_type)
632   {
633     case UniformNoise:
634     default:
635     {
636       noise=(double) pixel+ScaleCharToQuantum((unsigned char)
637         (SigmaUniform*(alpha)));
638       break;
639     }
640     case GaussianNoise:
641     {
642       double
643         gamma,
644         tau;
645
646       if (alpha == 0.0)
647         alpha=1.0;
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+
653         TauGaussian*tau;
654       break;
655     }
656     case MultiplicativeGaussianNoise:
657     {
658       if (alpha <= NoiseEpsilon)
659         sigma=(double) QuantumRange;
660       else
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));
665       break;
666     }
667     case ImpulseNoise:
668     {
669       if (alpha < (SigmaImpulse/2.0))
670         noise=0.0;
671        else
672          if (alpha >= (1.0-(SigmaImpulse/2.0)))
673            noise=(double) QuantumRange;
674          else
675            noise=(double) pixel;
676       break;
677     }
678     case LaplacianNoise:
679     {
680       if (alpha <= 0.5)
681         {
682           if (alpha <= NoiseEpsilon)
683             noise=(double) pixel-(double) QuantumRange;
684           else
685             noise=(double) pixel+ScaleCharToQuantum((unsigned char)
686               (SigmaLaplacian*log((2.0*alpha))+0.5));
687           break;
688         }
689       beta=1.0-alpha;
690       if (beta <= (0.5*NoiseEpsilon))
691         noise=(double) (pixel+QuantumRange);
692       else
693         noise=(double) pixel-ScaleCharToQuantum((unsigned char)
694           (SigmaLaplacian*log((2.0*beta))+0.5));
695       break;
696     }
697     case PoissonNoise:
698     {
699       double
700         poisson;
701
702       register long
703         i;
704
705       poisson=exp(-SigmaPoisson*ScaleQuantumToChar(pixel));
706       for (i=0; alpha > poisson; i++)
707       {
708         beta=GetPseudoRandomValue(random_info);
709         alpha*=beta;
710       }
711       noise=(double) ScaleCharToQuantum((unsigned char) (i/SigmaPoisson));
712       break;
713     }
714     case RandomNoise:
715     {
716       noise=(double) QuantumRange*alpha;
717       break;
718     }
719   }
720   return(noise);
721 }
722 \f
723 /*
724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
725 %                                                                             %
726 %                                                                             %
727 %                                                                             %
728 %   G e t O p t i m a l K e r n e l W i d t h                                 %
729 %                                                                             %
730 %                                                                             %
731 %                                                                             %
732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
733 %
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.
737 %
738 %  The format of the GetOptimalKernelWidth method is:
739 %
740 %      unsigned long GetOptimalKernelWidth(const double radius,
741 %        const double sigma)
742 %
743 %  A description of each parameter follows:
744 %
745 %    o width: Method GetOptimalKernelWidth returns the optimal width of
746 %      a convolution kernel.
747 %
748 %    o radius: the radius of the Gaussian, in pixels, not counting the center
749 %      pixel.
750 %
751 %    o sigma: the standard deviation of the Gaussian, in pixels.
752 %
753 */
754 MagickExport unsigned long GetOptimalKernelWidth1D(const double radius,
755   const double sigma)
756 {
757 #define MagickSigma  (fabs(sigma) <= MagickEpsilon ? 1.0 : sigma)
758
759   MagickRealType
760     normalize,
761     value;
762
763   long
764     j;
765
766   register long
767     i;
768
769   unsigned long
770     width;
771
772   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
773   if (radius > MagickEpsilon)
774     return((unsigned long) (2.0*ceil(radius)+1.0));
775   if (fabs(sigma) <= MagickEpsilon)
776     return(1UL);
777   for (width=5; ; )
778   {
779     normalize=0.0;
780     j=(long) width/2;
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))
787       break;
788     width+=2;
789   }
790   return((unsigned long) (width-2));
791 }
792
793 MagickExport unsigned long GetOptimalKernelWidth2D(const double radius,
794   const double sigma)
795 {
796   double
797     normalize,
798     value;
799
800   long
801     j,
802     u,
803     v;
804
805   unsigned long
806     width;
807
808   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
809   if (radius > MagickEpsilon)
810     return((unsigned long) (2.0*ceil(radius)+1.0));
811   if (fabs(sigma) <= MagickEpsilon)
812     return(1UL);
813   for (width=5; ; )
814   {
815     normalize=0.0;
816     j=(long) width/2;
817     for (v=(-j); v <= j; v++)
818     {
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);
822     }
823     value=exp(-((double) j*j)/(2.0*MagickSigma*MagickSigma))/normalize;
824     if ((value < QuantumScale) || (value < MagickEpsilon))
825       break;
826     width+=2;
827   }
828   return((unsigned long) (width-2));
829 }
830
831 MagickExport unsigned long  GetOptimalKernelWidth(const double radius,
832   const double sigma)
833 {
834   return(GetOptimalKernelWidth1D(radius,sigma));
835 }