]> granicus.if.org Git - imagemagick/blob - MagickCore/gem.c
(no commit message)
[imagemagick] / MagickCore / 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-2012 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 "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"
60 \f
61 /*
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 %                                                                             %
64 %                                                                             %
65 %                                                                             %
66 %   C o n v e r t H C L T o R G B                                             %
67 %                                                                             %
68 %                                                                             %
69 %                                                                             %
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 %
72 %  ConvertHCLToRGB() transforms a (hue, chroma, luma) to a (red, green,
73 %  blue) triple.
74 %
75 %  The format of the ConvertHCLToRGBImage method is:
76 %
77 %      void ConvertHCLToRGB(const double hue,const double chroma,
78 %        const double luma,double *red,double *green,double *blue)
79 %
80 %  A description of each parameter follows:
81 %
82 %    o hue, chroma, luma: A double value representing a
83 %      component of the HCL color space.
84 %
85 %    o red, green, blue: A pointer to a pixel component of type Quantum.
86 %
87 */
88 MagickPrivate void ConvertHCLToRGB(const double hue,const double chroma,
89   const double luma,double *red,double *green,double *blue)
90 {
91   double
92     b,
93     c,
94     g,
95     h,
96     m,
97     r,
98     x,
99     z;
100
101   /*
102     Convert HCL to RGB colorspace.
103   */
104   assert(red != (double *) NULL);
105   assert(green != (double *) NULL);
106   assert(blue != (double *) NULL);
107   h=6.0*hue;
108   c=chroma;
109   x=c*(1.0-fabs(fmod(h,2.0)-1.0));
110   r=0.0;
111   g=0.0;
112   b=0.0;
113   if ((0.0 <= h) && (h < 1.0))
114     {
115       r=c;
116       g=x;
117     }
118   else
119     if ((1.0 <= h) && (h < 2.0))
120       {
121         r=x;
122         g=c;
123       }
124     else
125       if ((2.0 <= h) && (h < 3.0))
126         {
127           g=c;
128           b=x;
129         }
130       else
131         if ((3.0 <= h) && (h < 4.0))
132           {
133             g=x;
134             b=c;
135           }
136         else
137           if ((4.0 <= h) && (h < 5.0))
138             {
139               r=x;
140               b=c;
141             }
142           else
143             if ((5.0 <= h) && (h < 6.0))
144               {
145                 r=c;
146                 b=x;
147               }
148   m=luma-(0.298839*r+0.586811*g+0.114350*b);
149   /*
150     Choose saturation strategy to clip it into the RGB cube; hue and luma are
151     preserved and chroma may be changed.
152   */
153   z=1.0;
154   if (m < 0.0)
155     {
156       z=luma/(luma-m);
157       m=0.0;
158     }
159   else
160     if ((m+c) > 1.0)
161       {
162         z=(1.0-luma)/(m+c-luma);
163         m=1.0-z*c;
164       }
165   *red=QuantumRange*(z*r+m);
166   *green=QuantumRange*(z*g+m);
167   *blue=QuantumRange*(z*b+m);
168 }
169 \f
170 /*
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 %                                                                             %
173 %                                                                             %
174 %                                                                             %
175 %   C o n v e r t H S B T o R G B                                             %
176 %                                                                             %
177 %                                                                             %
178 %                                                                             %
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 %
181 %  ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
182 %  green, blue) triple.
183 %
184 %  The format of the ConvertHSBToRGBImage method is:
185 %
186 %      void ConvertHSBToRGB(const double hue,const double saturation,
187 %        const double brightness,double *red,double *green,double *blue)
188 %
189 %  A description of each parameter follows:
190 %
191 %    o hue, saturation, brightness: A double value representing a
192 %      component of the HSB color space.
193 %
194 %    o red, green, blue: A pointer to a pixel component of type Quantum.
195 %
196 */
197 MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
198   const double brightness,double *red,double *green,double *blue)
199 {
200   double
201     f,
202     h,
203     p,
204     q,
205     t;
206
207   /*
208     Convert HSB to RGB colorspace.
209   */
210   assert(red != (double *) NULL);
211   assert(green != (double *) NULL);
212   assert(blue != (double *) NULL);
213   if (saturation == 0.0)
214     {
215       *red=QuantumRange*brightness;
216       *green=(*red);
217       *blue=(*red);
218       return;
219     }
220   h=6.0*(hue-floor(hue));
221   f=h-floor((double) h);
222   p=brightness*(1.0-saturation);
223   q=brightness*(1.0-saturation*f);
224   t=brightness*(1.0-(saturation*(1.0-f)));
225   switch ((int) h)
226   {
227     case 0:
228     default:
229     {
230       *red=QuantumRange*brightness;
231       *green=QuantumRange*t;
232       *blue=QuantumRange*p;
233       break;
234     }
235     case 1:
236     {
237       *red=QuantumRange*q;
238       *green=QuantumRange*brightness;
239       *blue=QuantumRange*p;
240       break;
241     }
242     case 2:
243     {
244       *red=QuantumRange*p;
245       *green=QuantumRange*brightness;
246       *blue=QuantumRange*t;
247       break;
248     }
249     case 3:
250     {
251       *red=QuantumRange*p;
252       *green=QuantumRange*q;
253       *blue=QuantumRange*brightness;
254       break;
255     }
256     case 4:
257     {
258       *red=QuantumRange*t;
259       *green=QuantumRange*p;
260       *blue=QuantumRange*brightness;
261       break;
262     }
263     case 5:
264     {
265       *red=QuantumRange*brightness;
266       *green=QuantumRange*p;
267       *blue=QuantumRange*q;
268       break;
269     }
270   }
271 }
272 \f
273 /*
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275 %                                                                             %
276 %                                                                             %
277 %                                                                             %
278 %   C o n v e r t H S L T o R G B                                             %
279 %                                                                             %
280 %                                                                             %
281 %                                                                             %
282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
283 %
284 %  ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
285 %  green, blue) triple.
286 %
287 %  The format of the ConvertHSLToRGBImage method is:
288 %
289 %      void ConvertHSLToRGB(const double hue,const double saturation,
290 %        const double lightness,double *red,double *green,double *blue)
291 %
292 %  A description of each parameter follows:
293 %
294 %    o hue, saturation, lightness: A double value representing a
295 %      component of the HSL color space.
296 %
297 %    o red, green, blue: A pointer to a pixel component of type Quantum.
298 %
299 */
300
301 static inline double ConvertHueToRGB(double m1,double m2,double hue)
302 {
303   if (hue < 0.0)
304     hue+=1.0;
305   if (hue > 1.0)
306     hue-=1.0;
307   if ((6.0*hue) < 1.0)
308     return(m1+6.0*(m2-m1)*hue);
309   if ((2.0*hue) < 1.0)
310     return(m2);
311   if ((3.0*hue) < 2.0)
312     return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
313   return(m1);
314 }
315
316 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
317   const double lightness,double *red,double *green,double *blue)
318 {
319   double
320     b,
321     g,
322     r,
323     m1,
324     m2;
325
326   /*
327     Convert HSL to RGB colorspace.
328   */
329   assert(red != (double *) NULL);
330   assert(green != (double *) NULL);
331   assert(blue != (double *) NULL);
332   if (saturation == 0)
333     {
334       *red=QuantumRange*lightness;
335       *green=(*red);
336       *blue=(*red);
337       return;
338     }
339   if (lightness < 0.5)
340     m2=lightness*(saturation+1.0);
341   else
342     m2=(lightness+saturation)-(lightness*saturation);
343   m1=2.0*lightness-m2;
344   r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
345   g=ConvertHueToRGB(m1,m2,hue);
346   b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
347   *red=QuantumRange*r;
348   *green=QuantumRange*g;
349   *blue=QuantumRange*b;
350 }
351 \f
352 /*
353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354 %                                                                             %
355 %                                                                             %
356 %                                                                             %
357 %   C o n v e r t H W B T o R G B                                             %
358 %                                                                             %
359 %                                                                             %
360 %                                                                             %
361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
362 %
363 %  ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
364 %  blue) triple.
365 %
366 %  The format of the ConvertHWBToRGBImage method is:
367 %
368 %      void ConvertHWBToRGB(const double hue,const double whiteness,
369 %        const double blackness,double *red,double *green,double *blue)
370 %
371 %  A description of each parameter follows:
372 %
373 %    o hue, whiteness, blackness: A double value representing a
374 %      component of the HWB color space.
375 %
376 %    o red, green, blue: A pointer to a pixel component of type Quantum.
377 %
378 */
379 MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
380   const double blackness,double *red,double *green,double *blue)
381 {
382   double
383     b,
384     f,
385     g,
386     n,
387     r,
388     v;
389
390   register ssize_t
391     i;
392
393   /*
394     Convert HWB to RGB colorspace.
395   */
396   assert(red != (double *) NULL);
397   assert(green != (double *) NULL);
398   assert(blue != (double *) NULL);
399   v=1.0-blackness;
400   if (hue == -1.0)
401     {
402       *red=QuantumRange*v;
403       *green=QuantumRange*v;
404       *blue=QuantumRange*v;
405       return;
406     }
407   i=(ssize_t) floor(6.0*hue);
408   f=6.0*hue-i;
409   if ((i & 0x01) != 0)
410     f=1.0-f;
411   n=whiteness+f*(v-whiteness);  /* linear interpolation */
412   switch (i)
413   {
414     default:
415     case 6:
416     case 0: r=v; g=n; b=whiteness; break;
417     case 1: r=n; g=v; b=whiteness; break;
418     case 2: r=whiteness; g=v; b=n; break;
419     case 3: r=whiteness; g=n; b=v; break;
420     case 4: r=n; g=whiteness; b=v; break;
421     case 5: r=v; g=whiteness; b=n; break;
422   }
423   *red=QuantumRange*r;
424   *green=QuantumRange*g;
425   *blue=QuantumRange*b;
426 }
427 \f
428 /*
429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430 %                                                                             %
431 %                                                                             %
432 %                                                                             %
433 %   C o n v e r t R G B T o H C L                                             %
434 %                                                                             %
435 %                                                                             %
436 %                                                                             %
437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 %
439 %  ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
440 %  luma) triple.
441 %
442 %  The format of the ConvertRGBToHCL method is:
443 %
444 %      void ConvertRGBToHCL(const double red,const double green,
445 %        const double blue,double *hue,double *chroma,double *luma)
446 %
447 %  A description of each parameter follows:
448 %
449 %    o red, green, blue: A Quantum value representing the red, green, and
450 %      blue component of a pixel.
451 %
452 %    o hue, chroma, luma: A pointer to a double value representing a
453 %      component of the HCL color space.
454 %
455 */
456
457 static inline double MagickMax(const double x,const double y)
458 {
459   if (x > y)
460     return(x);
461   return(y);
462 }
463
464 static inline double MagickMin(const double x,const double y)
465 {
466   if (x < y)
467     return(x);
468   return(y);
469 }
470
471 MagickPrivate void ConvertRGBToHCL(const double red,const double green,
472   const double blue,double *hue,double *chroma,double *luma)
473 {
474   double
475     b,
476     c,
477     g,
478     h,
479     max,
480     r;
481
482   /*
483     Convert RGB to HCL colorspace.
484   */
485   assert(hue != (double *) NULL);
486   assert(chroma != (double *) NULL);
487   assert(luma != (double *) NULL);
488   r=red;
489   g=green;
490   b=blue;
491   max=MagickMax(r,MagickMax(g,b));
492   c=max-(double) MagickMin(r,MagickMin(g,b));
493   h=0.0;
494   if (c == 0.0)
495     h=0.0;
496   else
497     if (red == max)
498       h=fmod((g-b)/c+6.0,6.0);
499     else
500       if (green == max)
501         h=((b-r)/c)+2.0;
502       else
503         if (blue == max)
504           h=((r-g)/c)+4.0;
505   *hue=(h/6.0);
506   *chroma=QuantumScale*c;
507   *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
508 }
509 \f
510 /*
511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512 %                                                                             %
513 %                                                                             %
514 %                                                                             %
515 %   C o n v e r t R G B T o H S B                                             %
516 %                                                                             %
517 %                                                                             %
518 %                                                                             %
519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520 %
521 %  ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
522 %  brightness) triple.
523 %
524 %  The format of the ConvertRGBToHSB method is:
525 %
526 %      void ConvertRGBToHSB(const double red,const double green,
527 %        const double blue,double *hue,double *saturation,double *brightness)
528 %
529 %  A description of each parameter follows:
530 %
531 %    o red, green, blue: A Quantum value representing the red, green, and
532 %      blue component of a pixel..
533 %
534 %    o hue, saturation, brightness: A pointer to a double value representing a
535 %      component of the HSB color space.
536 %
537 */
538 MagickPrivate void ConvertRGBToHSB(const double red,const double green,
539   const double blue,double *hue,double *saturation,double *brightness)
540 {
541   double
542     b,
543     delta,
544     g,
545     max,
546     min,
547     r;
548
549   /*
550     Convert RGB to HSB colorspace.
551   */
552   assert(hue != (double *) NULL);
553   assert(saturation != (double *) NULL);
554   assert(brightness != (double *) NULL);
555   *hue=0.0;
556   *saturation=0.0;
557   *brightness=0.0;
558   r=red;
559   g=green;
560   b=blue;
561   min=r < g ? r : g;
562   if (b < min)
563     min=b;
564   max=r > g ? r : g;
565   if (b > max)
566     max=b;
567   if (max == 0.0)
568     return;
569   delta=max-min;
570   *saturation=delta/max;
571   *brightness=QuantumScale*max;
572   if (delta == 0.0)
573     return;
574   if (r == max)
575     *hue=(g-b)/delta;
576   else
577     if (g == max)
578       *hue=2.0+(b-r)/delta;
579     else
580       *hue=4.0+(r-g)/delta;
581   *hue/=6.0;
582   if (*hue < 0.0)
583     *hue+=1.0;
584 }
585 \f
586 /*
587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588 %                                                                             %
589 %                                                                             %
590 %                                                                             %
591 %   C o n v e r t R G B T o H S L                                             %
592 %                                                                             %
593 %                                                                             %
594 %                                                                             %
595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
596 %
597 %  ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
598 %  lightness) triple.
599 %
600 %  The format of the ConvertRGBToHSL method is:
601 %
602 %      void ConvertRGBToHSL(const double red,const double green,
603 %        const double blue,double *hue,double *saturation,double *lightness)
604 %
605 %  A description of each parameter follows:
606 %
607 %    o red, green, blue: A Quantum value representing the red, green, and
608 %      blue component of a pixel..
609 %
610 %    o hue, saturation, lightness: A pointer to a double value representing a
611 %      component of the HSL color space.
612 %
613 */
614 MagickExport void ConvertRGBToHSL(const double red,const double green,
615   const double blue,double *hue,double *saturation,double *lightness)
616 {
617   double
618     b,
619     delta,
620     g,
621     max,
622     min,
623     r;
624
625   /*
626     Convert RGB to HSL colorspace.
627   */
628   assert(hue != (double *) NULL);
629   assert(saturation != (double *) NULL);
630   assert(lightness != (double *) NULL);
631   r=QuantumScale*red;
632   g=QuantumScale*green;
633   b=QuantumScale*blue;
634   max=MagickMax(r,MagickMax(g,b));
635   min=MagickMin(r,MagickMin(g,b));
636   *lightness=(double) ((min+max)/2.0);
637   delta=max-min;
638   if (delta == 0.0)
639     {
640       *hue=0.0;
641       *saturation=0.0;
642       return;
643     }
644   if (*lightness < 0.5)
645     *saturation=(double) (delta/(min+max));
646   else
647     *saturation=(double) (delta/(2.0-max-min));
648   if (r == max)
649     *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
650   else
651     if (g == max)
652       *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
653         delta;
654     else
655       if (b == max)
656         *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
657           (delta/2.0)))/delta;
658   if (*hue < 0.0)
659     *hue+=1.0;
660   if (*hue > 1.0)
661     *hue-=1.0;
662 }
663 \f
664 /*
665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
666 %                                                                             %
667 %                                                                             %
668 %                                                                             %
669 %   C o n v e r t R G B T o H W B                                             %
670 %                                                                             %
671 %                                                                             %
672 %                                                                             %
673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
674 %
675 %  ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
676 %  blackness) triple.
677 %
678 %  The format of the ConvertRGBToHWB method is:
679 %
680 %      void ConvertRGBToHWB(const double red,const double green,
681 %        const double blue,double *hue,double *whiteness,double *blackness)
682 %
683 %  A description of each parameter follows:
684 %
685 %    o red, green, blue: A Quantum value representing the red, green, and
686 %      blue component of a pixel.
687 %
688 %    o hue, whiteness, blackness: A pointer to a double value representing a
689 %      component of the HWB color space.
690 %
691 */
692 MagickPrivate void ConvertRGBToHWB(const double red,const double green,
693   const double blue,double *hue,double *whiteness,double *blackness)
694 {
695   double
696     b,
697     f,
698     g,
699     p,
700     r,
701     v,
702     w;
703
704   /*
705     Convert RGB to HWB colorspace.
706   */
707   assert(hue != (double *) NULL);
708   assert(whiteness != (double *) NULL);
709   assert(blackness != (double *) NULL);
710   r=red;
711   g=green;
712   b=blue;
713   w=MagickMin(r,MagickMin(g,b));
714   v=MagickMax(r,MagickMax(g,b));
715   *blackness=1.0-QuantumScale*v;
716   *whiteness=QuantumScale*w;
717   if (v == w)
718     {
719       *hue=(-1.0);
720       return;
721     }
722   f=(r == w) ? g-b : ((g == w) ? b-r : r-g);
723   p=(r == w) ? 3.0 : ((g == w) ? 5.0 : 1.0);
724   *hue=(p-f/(v-1.0*w))/6.0;
725 }
726 \f
727 /*
728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729 %                                                                             %
730 %                                                                             %
731 %                                                                             %
732 %   E x p a n d A f f i n e                                                   %
733 %                                                                             %
734 %                                                                             %
735 %                                                                             %
736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737 %
738 %  ExpandAffine() computes the affine's expansion factor, i.e. the square root
739 %  of the factor by which the affine transform affects area. In an affine
740 %  transform composed of scaling, rotation, shearing, and translation, returns
741 %  the amount of scaling.
742 %
743 %  The format of the ExpandAffine method is:
744 %
745 %      double ExpandAffine(const AffineMatrix *affine)
746 %
747 %  A description of each parameter follows:
748 %
749 %    o expansion: Method ExpandAffine returns the affine's expansion factor.
750 %
751 %    o affine: A pointer the affine transform of type AffineMatrix.
752 %
753 */
754 MagickExport double ExpandAffine(const AffineMatrix *affine)
755 {
756   assert(affine != (const AffineMatrix *) NULL);
757   return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
758 }
759 \f
760 /*
761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762 %                                                                             %
763 %                                                                             %
764 %                                                                             %
765 %   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                         %
766 %                                                                             %
767 %                                                                             %
768 %                                                                             %
769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
770 %
771 %  GenerateDifferentialNoise() generates differentual noise.
772 %
773 %  The format of the GenerateDifferentialNoise method is:
774 %
775 %      double GenerateDifferentialNoise(RandomInfo *random_info,
776 %        const Quantum pixel,const NoiseType noise_type,const double attenuate)
777 %
778 %  A description of each parameter follows:
779 %
780 %    o random_info: the random info.
781 %
782 %    o pixel: noise is relative to this pixel value.
783 %
784 %    o noise_type: the type of noise.
785 %
786 %    o attenuate:  attenuate the noise.
787 %
788 */
789 MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
790   const Quantum pixel,const NoiseType noise_type,const double attenuate)
791 {
792 #define SigmaUniform  (attenuate*0.015625)
793 #define SigmaGaussian  (attenuate*0.015625)
794 #define SigmaImpulse  (attenuate*0.1)
795 #define SigmaLaplacian (attenuate*0.0390625)
796 #define SigmaMultiplicativeGaussian  (attenuate*0.5)
797 #define SigmaPoisson  (attenuate*12.5)
798 #define SigmaRandom  (attenuate)
799 #define TauGaussian  (attenuate*0.078125)
800
801   double
802     alpha,
803     beta,
804     noise,
805     sigma;
806
807   alpha=GetPseudoRandomValue(random_info);
808   switch (noise_type)
809   {
810     case UniformNoise:
811     default:
812     {
813       noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
814       break;
815     }
816     case GaussianNoise:
817     {
818       double
819         gamma,
820         tau;
821
822       if (alpha == 0.0)
823         alpha=1.0;
824       beta=GetPseudoRandomValue(random_info);
825       gamma=sqrt(-2.0*log(alpha));
826       sigma=gamma*cos((double) (2.0*MagickPI*beta));
827       tau=gamma*sin((double) (2.0*MagickPI*beta));
828       noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
829         QuantumRange*TauGaussian*tau);
830       break;
831     }
832     case ImpulseNoise:
833     {
834       if (alpha < (SigmaImpulse/2.0))
835         noise=0.0;
836       else
837         if (alpha >= (1.0-(SigmaImpulse/2.0)))
838           noise=(double) QuantumRange;
839         else
840           noise=(double) pixel;
841       break;
842     }
843     case LaplacianNoise:
844     {
845       if (alpha <= 0.5)
846         {
847           if (alpha <= MagickEpsilon)
848             noise=(double) (pixel-QuantumRange);
849           else
850             noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
851               0.5);
852           break;
853         }
854       beta=1.0-alpha;
855       if (beta <= (0.5*MagickEpsilon))
856         noise=(double) (pixel+QuantumRange);
857       else
858         noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
859       break;
860     }
861     case MultiplicativeGaussianNoise:
862     {
863       sigma=1.0;
864       if (alpha > MagickEpsilon)
865         sigma=sqrt(-2.0*log(alpha));
866       beta=GetPseudoRandomValue(random_info);
867       noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
868         cos((double) (2.0*MagickPI*beta))/2.0);
869       break;
870     }
871     case PoissonNoise:
872     {
873       double
874         poisson;
875
876       register ssize_t
877         i;
878
879       poisson=exp(-SigmaPoisson*QuantumScale*pixel);
880       for (i=0; alpha > poisson; i++)
881       {
882         beta=GetPseudoRandomValue(random_info);
883         alpha*=beta;
884       }
885       noise=(double) (QuantumRange*i/SigmaPoisson);
886       break;
887     }
888     case RandomNoise:
889     {
890       noise=(double) (QuantumRange*SigmaRandom*alpha);
891       break;
892     }
893   }
894   return(noise);
895 }
896 \f
897 /*
898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899 %                                                                             %
900 %                                                                             %
901 %                                                                             %
902 %   G e t O p t i m a l K e r n e l W i d t h                                 %
903 %                                                                             %
904 %                                                                             %
905 %                                                                             %
906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
907 %
908 %  GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
909 %  filter.  Start with the minimum value of 3 pixels and walk out until we drop
910 %  below the threshold of one pixel numerical accuracy.
911 %
912 %  The format of the GetOptimalKernelWidth method is:
913 %
914 %      size_t GetOptimalKernelWidth(const double radius,
915 %        const double sigma)
916 %
917 %  A description of each parameter follows:
918 %
919 %    o width: Method GetOptimalKernelWidth returns the optimal width of
920 %      a convolution kernel.
921 %
922 %    o radius: the radius of the Gaussian, in pixels, not counting the center
923 %      pixel.
924 %
925 %    o sigma: the standard deviation of the Gaussian, in pixels.
926 %
927 */
928 MagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
929   const double sigma)
930 {
931   double
932     alpha,
933     beta,
934     gamma,
935     normalize,
936     value;
937
938   register ssize_t
939     i;
940
941   size_t
942     width;
943
944   ssize_t
945     j;
946
947   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
948   if (radius > MagickEpsilon)
949     return((size_t) (2.0*ceil(radius)+1.0));
950   gamma=fabs(sigma);
951   if (gamma <= MagickEpsilon)
952     return(3UL);
953   alpha=MagickEpsilonReciprocal(2.0*gamma*gamma);
954   beta=(double) MagickEpsilonReciprocal((double) MagickSQ2PI*gamma);
955   for (width=5; ; )
956   {
957     normalize=0.0;
958     j=(ssize_t) width/2;
959     for (i=(-j); i <= j; i++)
960       normalize+=exp(-((double) (i*i))*alpha)*beta;
961     value=exp(-((double) (j*j))*alpha)*beta/normalize;
962     if ((value < QuantumScale) || (value < MagickEpsilon))
963       break;
964     width+=2;
965   }
966   return((size_t) (width-2));
967 }
968
969 MagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
970   const double sigma)
971 {
972   double
973     alpha,
974     beta,
975     gamma,
976     normalize,
977     value;
978
979   size_t
980     width;
981
982   ssize_t
983     j,
984     u,
985     v;
986
987   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
988   if (radius > MagickEpsilon)
989     return((size_t) (2.0*ceil(radius)+1.0));
990   gamma=fabs(sigma);
991   if (gamma <= MagickEpsilon)
992     return(3UL);
993   alpha=MagickEpsilonReciprocal(2.0*gamma*gamma);
994   beta=(double) MagickEpsilonReciprocal((double) Magick2PI*gamma*gamma);
995   for (width=5; ; )
996   {
997     normalize=0.0;
998     j=(ssize_t) width/2;
999     for (v=(-j); v <= j; v++)
1000       for (u=(-j); u <= j; u++)
1001         normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
1002     value=exp(-((double) (j*j))*alpha)*beta/normalize;
1003     if ((value < QuantumScale) || (value < MagickEpsilon))
1004       break;
1005     width+=2;
1006   }
1007   return((size_t) (width-2));
1008 }
1009
1010 MagickPrivate size_t  GetOptimalKernelWidth(const double radius,
1011   const double sigma)
1012 {
1013   return(GetOptimalKernelWidth1D(radius,sigma));
1014 }