]> 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-2013 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
100   /*
101     Convert HCL to RGB colorspace.
102   */
103   assert(red != (double *) NULL);
104   assert(green != (double *) NULL);
105   assert(blue != (double *) NULL);
106   h=6.0*hue;
107   c=chroma;
108   x=c*(1.0-fabs(fmod(h,2.0)-1.0));
109   r=0.0;
110   g=0.0;
111   b=0.0;
112   if ((0.0 <= h) && (h < 1.0))
113     {
114       r=c;
115       g=x;
116     }
117   else
118     if ((1.0 <= h) && (h < 2.0))
119       {
120         r=x;
121         g=c;
122       }
123     else
124       if ((2.0 <= h) && (h < 3.0))
125         {
126           g=c;
127           b=x;
128         }
129       else
130         if ((3.0 <= h) && (h < 4.0))
131           {
132             g=x;
133             b=c;
134           }
135         else
136           if ((4.0 <= h) && (h < 5.0))
137             {
138               r=x;
139               b=c;
140             }
141           else
142             if ((5.0 <= h) && (h < 6.0))
143               {
144                 r=c;
145                 b=x;
146               }
147   m=luma-(0.298839f*r+0.586811f*g+0.114350f*b);
148   *red=QuantumRange*(r+m);
149   *green=QuantumRange*(g+m);
150   *blue=QuantumRange*(b+m);
151 }
152 \f
153 /*
154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155 %                                                                             %
156 %                                                                             %
157 %                                                                             %
158 %   C o n v e r t H S B T o R G B                                             %
159 %                                                                             %
160 %                                                                             %
161 %                                                                             %
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
163 %
164 %  ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
165 %  green, blue) triple.
166 %
167 %  The format of the ConvertHSBToRGBImage method is:
168 %
169 %      void ConvertHSBToRGB(const double hue,const double saturation,
170 %        const double brightness,double *red,double *green,double *blue)
171 %
172 %  A description of each parameter follows:
173 %
174 %    o hue, saturation, brightness: A double value representing a
175 %      component of the HSB color space.
176 %
177 %    o red, green, blue: A pointer to a pixel component of type Quantum.
178 %
179 */
180 MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
181   const double brightness,double *red,double *green,double *blue)
182 {
183   double
184     f,
185     h,
186     p,
187     q,
188     t;
189
190   /*
191     Convert HSB to RGB colorspace.
192   */
193   assert(red != (double *) NULL);
194   assert(green != (double *) NULL);
195   assert(blue != (double *) NULL);
196   if (saturation == 0.0)
197     {
198       *red=QuantumRange*brightness;
199       *green=(*red);
200       *blue=(*red);
201       return;
202     }
203   h=6.0*(hue-floor(hue));
204   f=h-floor((double) h);
205   p=brightness*(1.0-saturation);
206   q=brightness*(1.0-saturation*f);
207   t=brightness*(1.0-(saturation*(1.0-f)));
208   switch ((int) h)
209   {
210     case 0:
211     default:
212     {
213       *red=QuantumRange*brightness;
214       *green=QuantumRange*t;
215       *blue=QuantumRange*p;
216       break;
217     }
218     case 1:
219     {
220       *red=QuantumRange*q;
221       *green=QuantumRange*brightness;
222       *blue=QuantumRange*p;
223       break;
224     }
225     case 2:
226     {
227       *red=QuantumRange*p;
228       *green=QuantumRange*brightness;
229       *blue=QuantumRange*t;
230       break;
231     }
232     case 3:
233     {
234       *red=QuantumRange*p;
235       *green=QuantumRange*q;
236       *blue=QuantumRange*brightness;
237       break;
238     }
239     case 4:
240     {
241       *red=QuantumRange*t;
242       *green=QuantumRange*p;
243       *blue=QuantumRange*brightness;
244       break;
245     }
246     case 5:
247     {
248       *red=QuantumRange*brightness;
249       *green=QuantumRange*p;
250       *blue=QuantumRange*q;
251       break;
252     }
253   }
254 }
255 \f
256 /*
257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258 %                                                                             %
259 %                                                                             %
260 %                                                                             %
261 %   C o n v e r t H S L T o R G B                                             %
262 %                                                                             %
263 %                                                                             %
264 %                                                                             %
265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266 %
267 %  ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
268 %  green, blue) triple.
269 %
270 %  The format of the ConvertHSLToRGBImage method is:
271 %
272 %      void ConvertHSLToRGB(const double hue,const double saturation,
273 %        const double lightness,double *red,double *green,double *blue)
274 %
275 %  A description of each parameter follows:
276 %
277 %    o hue, saturation, lightness: A double value representing a
278 %      component of the HSL color space.
279 %
280 %    o red, green, blue: A pointer to a pixel component of type Quantum.
281 %
282 */
283
284 static inline double ConvertHueToRGB(double m1,double m2,double hue)
285 {
286   if (hue < 0.0)
287     hue+=1.0;
288   if (hue >= 1.0)
289     hue-=1.0;
290   if ((6.0*hue) < 1.0)
291     return(m1+6.0*(m2-m1)*hue);
292   if ((2.0*hue) < 1.0)
293     return(m2);
294   if ((3.0*hue) < 2.0)
295     return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
296   return(m1);
297 }
298
299 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
300   const double lightness,double *red,double *green,double *blue)
301 {
302   double
303     b,
304     g,
305     r,
306     m1,
307     m2;
308
309   /*
310     Convert HSL to RGB colorspace.
311   */
312   assert(red != (double *) NULL);
313   assert(green != (double *) NULL);
314   assert(blue != (double *) NULL);
315   if (saturation == 0)
316     {
317       *red=QuantumRange*lightness;
318       *green=(*red);
319       *blue=(*red);
320       return;
321     }
322   if (lightness < 0.5)
323     m2=lightness*(saturation+1.0);
324   else
325     m2=(lightness+saturation)-(lightness*saturation);
326   m1=2.0*lightness-m2;
327   r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
328   g=ConvertHueToRGB(m1,m2,hue);
329   b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
330   *red=QuantumRange*r;
331   *green=QuantumRange*g;
332   *blue=QuantumRange*b;
333 }
334 \f
335 /*
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %                                                                             %
338 %                                                                             %
339 %                                                                             %
340 %   C o n v e r t H W B T o R G B                                             %
341 %                                                                             %
342 %                                                                             %
343 %                                                                             %
344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345 %
346 %  ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
347 %  blue) triple.
348 %
349 %  The format of the ConvertHWBToRGBImage method is:
350 %
351 %      void ConvertHWBToRGB(const double hue,const double whiteness,
352 %        const double blackness,double *red,double *green,double *blue)
353 %
354 %  A description of each parameter follows:
355 %
356 %    o hue, whiteness, blackness: A double value representing a
357 %      component of the HWB color space.
358 %
359 %    o red, green, blue: A pointer to a pixel component of type Quantum.
360 %
361 */
362 MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
363   const double blackness,double *red,double *green,double *blue)
364 {
365   double
366     b,
367     f,
368     g,
369     n,
370     r,
371     v;
372
373   register ssize_t
374     i;
375
376   /*
377     Convert HWB to RGB colorspace.
378   */
379   assert(red != (double *) NULL);
380   assert(green != (double *) NULL);
381   assert(blue != (double *) NULL);
382   v=1.0-blackness;
383   if (hue == -1.0)
384     {
385       *red=QuantumRange*v;
386       *green=QuantumRange*v;
387       *blue=QuantumRange*v;
388       return;
389     }
390   i=(ssize_t) floor(6.0*hue);
391   f=6.0*hue-i;
392   if ((i & 0x01) != 0)
393     f=1.0-f;
394   n=whiteness+f*(v-whiteness);  /* linear interpolation */
395   switch (i)
396   {
397     default:
398     case 6:
399     case 0: r=v; g=n; b=whiteness; break;
400     case 1: r=n; g=v; b=whiteness; break;
401     case 2: r=whiteness; g=v; b=n; break;
402     case 3: r=whiteness; g=n; b=v; break;
403     case 4: r=n; g=whiteness; b=v; break;
404     case 5: r=v; g=whiteness; b=n; break;
405   }
406   *red=QuantumRange*r;
407   *green=QuantumRange*g;
408   *blue=QuantumRange*b;
409 }
410 \f
411 /*
412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
413 %                                                                             %
414 %                                                                             %
415 %                                                                             %
416 %   C o n v e r t L C H a b T o R G B                                         %
417 %                                                                             %
418 %                                                                             %
419 %                                                                             %
420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
421 %
422 %  ConvertLCHabToRGB() transforms a (luma, chroma, hue) to a (red, green,
423 %  blue) triple.
424 %
425 %  The format of the ConvertLCHabToRGBImage method is:
426 %
427 %      void ConvertLCHabToRGB(const double luma,const double chroma,
428 %        const double hue,double *red,double *green,double *blue)
429 %
430 %  A description of each parameter follows:
431 %
432 %    o luma, chroma, hue: A double value representing a component of the
433 %      LCHab color space.
434 %
435 %    o red, green, blue: A pointer to a pixel component of type Quantum.
436 %
437 */
438 MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
439   const double hue,double *red,double *green,double *blue)
440 {
441   double
442     a,
443     b,
444     C,
445     H,
446     L,
447     X,
448     Y,
449     Z;
450
451   /*
452     Convert LCHab to RGB colorspace.
453   */
454   assert(red != (double *) NULL);
455   assert(green != (double *) NULL);
456   assert(blue != (double *) NULL);
457   L=luma;
458   C=chroma;
459   H=hue;
460   a=C*cos(360.0*H*MagickPI/180.0)+0.5;
461   b=C*sin(360.0*H*MagickPI/180.0)+0.5;
462   ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
463   ConvertXYZToRGB(X,Y,Z,red,green,blue);
464 }
465 \f
466 /*
467 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
468 %                                                                             %
469 %                                                                             %
470 %                                                                             %
471 %   C o n v e r t L C H u v T o R G B                                         %
472 %                                                                             %
473 %                                                                             %
474 %                                                                             %
475 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
476 %
477 %  ConvertLCHuvToRGB() transforms a (luma, chroma, hue) to a (red, green,
478 %  blue) triple.
479 %
480 %  The format of the ConvertLCHuvToRGBImage method is:
481 %
482 %      void ConvertLCHuvToRGB(const double luma,const double chroma,
483 %        const double hue,double *red,double *green,double *blue)
484 %
485 %  A description of each parameter follows:
486 %
487 %    o luma, chroma, hue: A double value representing a component of the
488 %      LCHuv color space.
489 %
490 %    o red, green, blue: A pointer to a pixel component of type Quantum.
491 %
492 */
493 MagickPrivate void ConvertLCHuvToRGB(const double luma,const double chroma,
494   const double hue,double *red,double *green,double *blue)
495 {
496   double
497     C,
498     H,
499     L,
500     u,
501     v,
502     X,
503     Y,
504     Z;
505
506   /*
507     Convert LCHuv to RGB colorspace.
508   */
509   assert(red != (double *) NULL);
510   assert(green != (double *) NULL);
511   assert(blue != (double *) NULL);
512   L=luma;
513   C=chroma;
514   H=hue;
515   u=(C*cos(360.0*H*MagickPI/180.0)+134.0)/354.0;
516   v=(C*sin(360.0*H*MagickPI/180.0)+140.0)/262.0;
517   ConvertLuvToXYZ(L,u,v,&X,&Y,&Z);
518   ConvertXYZToRGB(X,Y,Z,red,green,blue);
519 }
520 \f
521 /*
522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
523 %                                                                             %
524 %                                                                             %
525 %                                                                             %
526 %   C o n v e r t R G B T o H C L                                             %
527 %                                                                             %
528 %                                                                             %
529 %                                                                             %
530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
531 %
532 %  ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
533 %  luma) triple.
534 %
535 %  The format of the ConvertRGBToHCL method is:
536 %
537 %      void ConvertRGBToHCL(const double red,const double green,
538 %        const double blue,double *hue,double *chroma,double *luma)
539 %
540 %  A description of each parameter follows:
541 %
542 %    o red, green, blue: A Quantum value representing the red, green, and
543 %      blue component of a pixel.
544 %
545 %    o hue, chroma, luma: A pointer to a double value representing a
546 %      component of the HCL color space.
547 %
548 */
549
550 static inline double MagickMax(const double x,const double y)
551 {
552   if (x > y)
553     return(x);
554   return(y);
555 }
556
557 static inline double MagickMin(const double x,const double y)
558 {
559   if (x < y)
560     return(x);
561   return(y);
562 }
563
564 MagickPrivate void ConvertRGBToHCL(const double red,const double green,
565   const double blue,double *hue,double *chroma,double *luma)
566 {
567   double
568     b,
569     c,
570     g,
571     h,
572     max,
573     r;
574
575   /*
576     Convert RGB to HCL colorspace.
577   */
578   assert(hue != (double *) NULL);
579   assert(chroma != (double *) NULL);
580   assert(luma != (double *) NULL);
581   r=red;
582   g=green;
583   b=blue;
584   max=MagickMax(r,MagickMax(g,b));
585   c=max-(double) MagickMin(r,MagickMin(g,b));
586   h=0.0;
587   if (c == 0.0)
588     h=0.0;
589   else
590     if (red == max)
591       h=fmod((g-b)/c+6.0,6.0);
592     else
593       if (green == max)
594         h=((b-r)/c)+2.0;
595       else
596         if (blue == max)
597           h=((r-g)/c)+4.0;
598   *hue=(h/6.0);
599   *chroma=QuantumScale*c;
600   *luma=QuantumScale*(0.298839f*r+0.586811f*g+0.114350f*b);
601 }
602 \f
603 /*
604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
605 %                                                                             %
606 %                                                                             %
607 %                                                                             %
608 %   C o n v e r t R G B T o H S B                                             %
609 %                                                                             %
610 %                                                                             %
611 %                                                                             %
612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613 %
614 %  ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
615 %  brightness) triple.
616 %
617 %  The format of the ConvertRGBToHSB method is:
618 %
619 %      void ConvertRGBToHSB(const double red,const double green,
620 %        const double blue,double *hue,double *saturation,double *brightness)
621 %
622 %  A description of each parameter follows:
623 %
624 %    o red, green, blue: A Quantum value representing the red, green, and
625 %      blue component of a pixel..
626 %
627 %    o hue, saturation, brightness: A pointer to a double value representing a
628 %      component of the HSB color space.
629 %
630 */
631 MagickPrivate void ConvertRGBToHSB(const double red,const double green,
632   const double blue,double *hue,double *saturation,double *brightness)
633 {
634   double
635     b,
636     delta,
637     g,
638     max,
639     min,
640     r;
641
642   /*
643     Convert RGB to HSB colorspace.
644   */
645   assert(hue != (double *) NULL);
646   assert(saturation != (double *) NULL);
647   assert(brightness != (double *) NULL);
648   *hue=0.0;
649   *saturation=0.0;
650   *brightness=0.0;
651   r=red;
652   g=green;
653   b=blue;
654   min=r < g ? r : g;
655   if (b < min)
656     min=b;
657   max=r > g ? r : g;
658   if (b > max)
659     max=b;
660   if (max == 0.0)
661     return;
662   delta=max-min;
663   *saturation=delta/max;
664   *brightness=QuantumScale*max;
665   if (delta == 0.0)
666     return;
667   if (r == max)
668     *hue=(g-b)/delta;
669   else
670     if (g == max)
671       *hue=2.0+(b-r)/delta;
672     else
673       *hue=4.0+(r-g)/delta;
674   *hue/=6.0;
675   if (*hue < 0.0)
676     *hue+=1.0;
677 }
678 \f
679 /*
680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
681 %                                                                             %
682 %                                                                             %
683 %                                                                             %
684 %   C o n v e r t R G B T o H S L                                             %
685 %                                                                             %
686 %                                                                             %
687 %                                                                             %
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 %
690 %  ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
691 %  lightness) triple.
692 %
693 %  The format of the ConvertRGBToHSL method is:
694 %
695 %      void ConvertRGBToHSL(const double red,const double green,
696 %        const double blue,double *hue,double *saturation,double *lightness)
697 %
698 %  A description of each parameter follows:
699 %
700 %    o red, green, blue: A Quantum value representing the red, green, and
701 %      blue component of a pixel..
702 %
703 %    o hue, saturation, lightness: A pointer to a double value representing a
704 %      component of the HSL color space.
705 %
706 */
707 MagickExport void ConvertRGBToHSL(const double red,const double green,
708   const double blue,double *hue,double *saturation,double *lightness)
709 {
710   double
711     b,
712     delta,
713     g,
714     max,
715     min,
716     r;
717
718   /*
719     Convert RGB to HSL colorspace.
720   */
721   assert(hue != (double *) NULL);
722   assert(saturation != (double *) NULL);
723   assert(lightness != (double *) NULL);
724   r=QuantumScale*red;
725   g=QuantumScale*green;
726   b=QuantumScale*blue;
727   max=MagickMax(r,MagickMax(g,b));
728   min=MagickMin(r,MagickMin(g,b));
729   *lightness=(double) ((min+max)/2.0);
730   delta=max-min;
731   if (delta == 0.0)
732     {
733       *hue=0.0;
734       *saturation=0.0;
735       return;
736     }
737   if (*lightness < 0.5)
738     *saturation=(double) (delta/(min+max));
739   else
740     *saturation=(double) (delta/(2.0-max-min));
741   if (r == max)
742     *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
743   else
744     if (g == max)
745       *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
746         delta;
747     else
748       if (b == max)
749         *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
750           (delta/2.0)))/delta;
751   if (*hue < 0.0)
752     *hue+=1.0;
753   if (*hue >= 1.0)
754     *hue-=1.0;
755 }
756 \f
757 /*
758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
759 %                                                                             %
760 %                                                                             %
761 %                                                                             %
762 %   C o n v e r t R G B T o H W B                                             %
763 %                                                                             %
764 %                                                                             %
765 %                                                                             %
766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
767 %
768 %  ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
769 %  blackness) triple.
770 %
771 %  The format of the ConvertRGBToHWB method is:
772 %
773 %      void ConvertRGBToHWB(const double red,const double green,
774 %        const double blue,double *hue,double *whiteness,double *blackness)
775 %
776 %  A description of each parameter follows:
777 %
778 %    o red, green, blue: A Quantum value representing the red, green, and
779 %      blue component of a pixel.
780 %
781 %    o hue, whiteness, blackness: A pointer to a double value representing a
782 %      component of the HWB color space.
783 %
784 */
785 MagickPrivate void ConvertRGBToHWB(const double red,const double green,
786   const double blue,double *hue,double *whiteness,double *blackness)
787 {
788   double
789     b,
790     f,
791     g,
792     p,
793     r,
794     v,
795     w;
796
797   /*
798     Convert RGB to HWB colorspace.
799   */
800   assert(hue != (double *) NULL);
801   assert(whiteness != (double *) NULL);
802   assert(blackness != (double *) NULL);
803   r=red;
804   g=green;
805   b=blue;
806   w=MagickMin(r,MagickMin(g,b));
807   v=MagickMax(r,MagickMax(g,b));
808   *blackness=1.0-QuantumScale*v;
809   *whiteness=QuantumScale*w;
810   if (v == w)
811     {
812       *hue=(-1.0);
813       return;
814     }
815   f=(r == w) ? g-b : ((g == w) ? b-r : r-g);
816   p=(r == w) ? 3.0 : ((g == w) ? 5.0 : 1.0);
817   *hue=(p-f/(v-1.0*w))/6.0;
818 }
819 \f
820 /*
821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822 %                                                                             %
823 %                                                                             %
824 %                                                                             %
825 %   C o n v e r t R G B a b T o L C H                                         %
826 %                                                                             %
827 %                                                                             %
828 %                                                                             %
829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830 %
831 %  ConvertRGBToLCHab() transforms a (red, green, blue) to a (luma, chroma,
832 %  hue) triple.
833 %
834 %  The format of the ConvertRGBToLCHab method is:
835 %
836 %      void ConvertRGBToLCHab(const double red,const double green,
837 %        const double blue,double *luma,double *chroma,double *hue)
838 %
839 %  A description of each parameter follows:
840 %
841 %    o red, green, blue: A Quantum value representing the red, green, and
842 %      blue component of a pixel.
843 %
844 %    o luma, chroma, hue: A pointer to a double value representing a
845 %      component of the LCH color space.
846 %
847 */
848 MagickPrivate void ConvertRGBToLCHab(const double red,const double green,
849   const double blue,double *luma,double *chroma,double *hue)
850 {
851   double
852     a,
853     b,
854     C,
855     H,
856     L,
857     X,
858     Y,
859     Z;
860
861   /*
862     Convert RGB to LCHab colorspace.
863   */
864   assert(luma != (double *) NULL);
865   assert(chroma != (double *) NULL);
866   assert(hue != (double *) NULL);
867   ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
868   ConvertXYZToLab(X,Y,Z,&L,&a,&b);
869   C=hypot(a,b);
870   H=180.0*atan2(b,a)/MagickPI/360.0;
871   if (H < 0.0)
872     H+=1.0;
873   if (H >= 1.0)
874     H-=1.0;
875   *luma=L;
876   *chroma=C;
877   *hue=H;
878 }
879 \f
880 /*
881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882 %                                                                             %
883 %                                                                             %
884 %                                                                             %
885 %   C o n v e r t R G B u v T o L C H                                         %
886 %                                                                             %
887 %                                                                             %
888 %                                                                             %
889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890 %
891 %  ConvertRGBToLCHuv() transforms a (red, green, blue) to a (luma, chroma,
892 %  hue) triple.
893 %
894 %  The format of the ConvertRGBToLCHuv method is:
895 %
896 %      void ConvertRGBToLCHuv(const double red,const double green,
897 %        const double blue,double *luma,double *chroma,double *hue)
898 %
899 %  A description of each parameter follows:
900 %
901 %    o red, green, blue: A Quantum value representing the red, green, and
902 %      blue component of a pixel.
903 %
904 %    o luma, chroma, hue: A pointer to a double value representing a
905 %      component of the LCHuv color space.
906 %
907 */
908 MagickPrivate void ConvertRGBToLCHuv(const double red,const double green,
909   const double blue,double *luma,double *chroma,double *hue)
910 {
911   double
912     C,
913     H,
914     L,
915     u,
916     v,
917     X,
918     Y,
919     Z;
920
921   /*
922     Convert RGB to LCHuv colorspace.
923   */
924   assert(luma != (double *) NULL);
925   assert(chroma != (double *) NULL);
926   assert(hue != (double *) NULL);
927   ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
928   ConvertXYZToLuv(X,Y,Z,&L,&u,&v);
929   C=hypot(u,v);
930   H=180.0*atan2(v,u)/MagickPI/360.0;
931   if (H < 0.0)
932     H+=1.0;
933   if (H >= 1.0)
934     H-=1.0;
935   *luma=L;
936   *chroma=C;
937   *hue=H;
938 }
939 \f
940 /*
941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942 %                                                                             %
943 %                                                                             %
944 %                                                                             %
945 %   E x p a n d A f f i n e                                                   %
946 %                                                                             %
947 %                                                                             %
948 %                                                                             %
949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
950 %
951 %  ExpandAffine() computes the affine's expansion factor, i.e. the square root
952 %  of the factor by which the affine transform affects area. In an affine
953 %  transform composed of scaling, rotation, shearing, and translation, returns
954 %  the amount of scaling.
955 %
956 %  The format of the ExpandAffine method is:
957 %
958 %      double ExpandAffine(const AffineMatrix *affine)
959 %
960 %  A description of each parameter follows:
961 %
962 %    o expansion: Method ExpandAffine returns the affine's expansion factor.
963 %
964 %    o affine: A pointer the affine transform of type AffineMatrix.
965 %
966 */
967 MagickExport double ExpandAffine(const AffineMatrix *affine)
968 {
969   assert(affine != (const AffineMatrix *) NULL);
970   return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
971 }
972 \f
973 /*
974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
975 %                                                                             %
976 %                                                                             %
977 %                                                                             %
978 %   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                         %
979 %                                                                             %
980 %                                                                             %
981 %                                                                             %
982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
983 %
984 %  GenerateDifferentialNoise() generates differentual noise.
985 %
986 %  The format of the GenerateDifferentialNoise method is:
987 %
988 %      double GenerateDifferentialNoise(RandomInfo *random_info,
989 %        const Quantum pixel,const NoiseType noise_type,const double attenuate)
990 %
991 %  A description of each parameter follows:
992 %
993 %    o random_info: the random info.
994 %
995 %    o pixel: noise is relative to this pixel value.
996 %
997 %    o noise_type: the type of noise.
998 %
999 %    o attenuate:  attenuate the noise.
1000 %
1001 */
1002 MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
1003   const Quantum pixel,const NoiseType noise_type,const double attenuate)
1004 {
1005 #define SigmaUniform  (attenuate*0.015625)
1006 #define SigmaGaussian  (attenuate*0.015625)
1007 #define SigmaImpulse  (attenuate*0.1)
1008 #define SigmaLaplacian (attenuate*0.0390625)
1009 #define SigmaMultiplicativeGaussian  (attenuate*0.5)
1010 #define SigmaPoisson  (attenuate*12.5)
1011 #define SigmaRandom  (attenuate)
1012 #define TauGaussian  (attenuate*0.078125)
1013
1014   double
1015     alpha,
1016     beta,
1017     noise,
1018     sigma;
1019
1020   alpha=GetPseudoRandomValue(random_info);
1021   switch (noise_type)
1022   {
1023     case UniformNoise:
1024     default:
1025     {
1026       noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
1027       break;
1028     }
1029     case GaussianNoise:
1030     {
1031       double
1032         gamma,
1033         tau;
1034
1035       if (alpha == 0.0)
1036         alpha=1.0;
1037       beta=GetPseudoRandomValue(random_info);
1038       gamma=sqrt(-2.0*log(alpha));
1039       sigma=gamma*cos((double) (2.0*MagickPI*beta));
1040       tau=gamma*sin((double) (2.0*MagickPI*beta));
1041       noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
1042         QuantumRange*TauGaussian*tau);
1043       break;
1044     }
1045     case ImpulseNoise:
1046     {
1047       if (alpha < (SigmaImpulse/2.0))
1048         noise=0.0;
1049       else
1050         if (alpha >= (1.0-(SigmaImpulse/2.0)))
1051           noise=(double) QuantumRange;
1052         else
1053           noise=(double) pixel;
1054       break;
1055     }
1056     case LaplacianNoise:
1057     {
1058       if (alpha <= 0.5)
1059         {
1060           if (alpha <= MagickEpsilon)
1061             noise=(double) (pixel-QuantumRange);
1062           else
1063             noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
1064               0.5);
1065           break;
1066         }
1067       beta=1.0-alpha;
1068       if (beta <= (0.5*MagickEpsilon))
1069         noise=(double) (pixel+QuantumRange);
1070       else
1071         noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
1072       break;
1073     }
1074     case MultiplicativeGaussianNoise:
1075     {
1076       sigma=1.0;
1077       if (alpha > MagickEpsilon)
1078         sigma=sqrt(-2.0*log(alpha));
1079       beta=GetPseudoRandomValue(random_info);
1080       noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
1081         cos((double) (2.0*MagickPI*beta))/2.0);
1082       break;
1083     }
1084     case PoissonNoise:
1085     {
1086       double
1087         poisson;
1088
1089       register ssize_t
1090         i;
1091
1092       poisson=exp(-SigmaPoisson*QuantumScale*pixel);
1093       for (i=0; alpha > poisson; i++)
1094       {
1095         beta=GetPseudoRandomValue(random_info);
1096         alpha*=beta;
1097       }
1098       noise=(double) (QuantumRange*i/SigmaPoisson);
1099       break;
1100     }
1101     case RandomNoise:
1102     {
1103       noise=(double) (QuantumRange*SigmaRandom*alpha);
1104       break;
1105     }
1106   }
1107   return(noise);
1108 }
1109 \f
1110 /*
1111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1112 %                                                                             %
1113 %                                                                             %
1114 %                                                                             %
1115 %   G e t O p t i m a l K e r n e l W i d t h                                 %
1116 %                                                                             %
1117 %                                                                             %
1118 %                                                                             %
1119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1120 %
1121 %  GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
1122 %  filter.  Start with the minimum value of 3 pixels and walk out until we drop
1123 %  below the threshold of one pixel numerical accuracy.
1124 %
1125 %  The format of the GetOptimalKernelWidth method is:
1126 %
1127 %      size_t GetOptimalKernelWidth(const double radius,
1128 %        const double sigma)
1129 %
1130 %  A description of each parameter follows:
1131 %
1132 %    o width: Method GetOptimalKernelWidth returns the optimal width of
1133 %      a convolution kernel.
1134 %
1135 %    o radius: the radius of the Gaussian, in pixels, not counting the center
1136 %      pixel.
1137 %
1138 %    o sigma: the standard deviation of the Gaussian, in pixels.
1139 %
1140 */
1141 MagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
1142   const double sigma)
1143 {
1144   double
1145     alpha,
1146     beta,
1147     gamma,
1148     normalize,
1149     value;
1150
1151   register ssize_t
1152     i;
1153
1154   size_t
1155     width;
1156
1157   ssize_t
1158     j;
1159
1160   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1161   if (radius > MagickEpsilon)
1162     return((size_t) (2.0*ceil(radius)+1.0));
1163   gamma=fabs(sigma);
1164   if (gamma <= MagickEpsilon)
1165     return(3UL);
1166   alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1167   beta=(double) PerceptibleReciprocal((double) MagickSQ2PI*gamma);
1168   for (width=5; ; )
1169   {
1170     normalize=0.0;
1171     j=(ssize_t) (width-1)/2;
1172     for (i=(-j); i <= j; i++)
1173       normalize+=exp(-((double) (i*i))*alpha)*beta;
1174     value=exp(-((double) (j*j))*alpha)*beta/normalize;
1175     if ((value < QuantumScale) || (value < MagickEpsilon))
1176       break;
1177     width+=2;
1178   }
1179   return((size_t) (width-2));
1180 }
1181
1182 MagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
1183   const double sigma)
1184 {
1185   double
1186     alpha,
1187     beta,
1188     gamma,
1189     normalize,
1190     value;
1191
1192   size_t
1193     width;
1194
1195   ssize_t
1196     j,
1197     u,
1198     v;
1199
1200   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1201   if (radius > MagickEpsilon)
1202     return((size_t) (2.0*ceil(radius)+1.0));
1203   gamma=fabs(sigma);
1204   if (gamma <= MagickEpsilon)
1205     return(3UL);
1206   alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1207   beta=(double) PerceptibleReciprocal((double) Magick2PI*gamma*gamma);
1208   for (width=5; ; )
1209   {
1210     normalize=0.0;
1211     j=(ssize_t) (width-1)/2;
1212     for (v=(-j); v <= j; v++)
1213       for (u=(-j); u <= j; u++)
1214         normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
1215     value=exp(-((double) (j*j))*alpha)*beta/normalize;
1216     if ((value < QuantumScale) || (value < MagickEpsilon))
1217       break;
1218     width+=2;
1219   }
1220   return((size_t) (width-2));
1221 }
1222
1223 MagickPrivate size_t  GetOptimalKernelWidth(const double radius,
1224   const double sigma)
1225 {
1226   return(GetOptimalKernelWidth1D(radius,sigma));
1227 }