• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 %                                    Cristy                                   %
17 %                                 August 1996                                 %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2021 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 %    https://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 
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 
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 component of the
83 %      HCL color space.
84 %
85 %    o red, green, blue: A pointer to a pixel component of type Quantum.
86 %
87 */
ConvertHCLToRGB(const double hue,const double chroma,const double luma,double * red,double * green,double * blue)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.298839*r+0.586811*g+0.114350*b);
148   *red=QuantumRange*(r+m);
149   *green=QuantumRange*(g+m);
150   *blue=QuantumRange*(b+m);
151 }
152 
153 /*
154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155 %                                                                             %
156 %                                                                             %
157 %                                                                             %
158 %   C o n v e r t H C L p T o R G B                                           %
159 %                                                                             %
160 %                                                                             %
161 %                                                                             %
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
163 %
164 %  ConvertHCLpToRGB() transforms a (hue, chroma, luma) to a (red, green,
165 %  blue) triple.  Since HCL colorspace is wider than RGB, we instead choose a
166 %  saturation strategy to project it on the RGB cube.
167 %
168 %  The format of the ConvertHCLpToRGBImage method is:
169 %
170 %      void ConvertHCLpToRGB(const double hue,const double chroma,
171 %        const double luma,double *red,double *green,double *blue)
172 %
173 %  A description of each parameter follows:
174 %
175 %    o hue, chroma, luma: A double value representing a componenet of the
176 %      HCLp color space.
177 %
178 %    o red, green, blue: A pointer to a pixel component of type Quantum.
179 %
180 */
ConvertHCLpToRGB(const double hue,const double chroma,const double luma,double * red,double * green,double * blue)181 MagickPrivate void ConvertHCLpToRGB(const double hue,const double chroma,
182   const double luma,double *red,double *green,double *blue)
183 {
184   double
185     b,
186     c,
187     g,
188     h,
189     m,
190     r,
191     x,
192     z;
193 
194   /*
195     Convert HCLp to RGB colorspace.
196   */
197   assert(red != (double *) NULL);
198   assert(green != (double *) NULL);
199   assert(blue != (double *) NULL);
200   h=6.0*hue;
201   c=chroma;
202   x=c*(1.0-fabs(fmod(h,2.0)-1.0));
203   r=0.0;
204   g=0.0;
205   b=0.0;
206   if ((0.0 <= h) && (h < 1.0))
207     {
208       r=c;
209       g=x;
210     }
211   else
212     if ((1.0 <= h) && (h < 2.0))
213       {
214         r=x;
215         g=c;
216       }
217     else
218       if ((2.0 <= h) && (h < 3.0))
219         {
220           g=c;
221           b=x;
222         }
223       else
224         if ((3.0 <= h) && (h < 4.0))
225           {
226             g=x;
227             b=c;
228           }
229         else
230           if ((4.0 <= h) && (h < 5.0))
231             {
232               r=x;
233               b=c;
234             }
235           else
236             if ((5.0 <= h) && (h < 6.0))
237               {
238                 r=c;
239                 b=x;
240               }
241   m=luma-(0.298839*r+0.586811*g+0.114350*b);
242   z=1.0;
243   if (m < 0.0)
244     {
245       z=luma/(luma-m);
246       m=0.0;
247     }
248   else
249     if (m+c > 1.0)
250       {
251         z=(1.0-luma)/(m+c-luma);
252         m=1.0-z*c;
253       }
254   *red=QuantumRange*(z*r+m);
255   *green=QuantumRange*(z*g+m);
256   *blue=QuantumRange*(z*b+m);
257 }
258 
259 /*
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 %                                                                             %
262 %                                                                             %
263 %                                                                             %
264 %   C o n v e r t H S B T o R G B                                             %
265 %                                                                             %
266 %                                                                             %
267 %                                                                             %
268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269 %
270 %  ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
271 %  green, blue) triple.
272 %
273 %  The format of the ConvertHSBToRGBImage method is:
274 %
275 %      void ConvertHSBToRGB(const double hue,const double saturation,
276 %        const double brightness,double *red,double *green,double *blue)
277 %
278 %  A description of each parameter follows:
279 %
280 %    o hue, saturation, brightness: A double value representing a
281 %      component of the HSB color space.
282 %
283 %    o red, green, blue: A pointer to a pixel component of type Quantum.
284 %
285 */
ConvertHSBToRGB(const double hue,const double saturation,const double brightness,double * red,double * green,double * blue)286 MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
287   const double brightness,double *red,double *green,double *blue)
288 {
289   double
290     f,
291     h,
292     p,
293     q,
294     t;
295 
296   /*
297     Convert HSB to RGB colorspace.
298   */
299   assert(red != (double *) NULL);
300   assert(green != (double *) NULL);
301   assert(blue != (double *) NULL);
302   if (fabs(saturation) < MagickEpsilon)
303     {
304       *red=QuantumRange*brightness;
305       *green=(*red);
306       *blue=(*red);
307       return;
308     }
309   h=6.0*(hue-floor(hue));
310   f=h-floor((double) h);
311   p=brightness*(1.0-saturation);
312   q=brightness*(1.0-saturation*f);
313   t=brightness*(1.0-(saturation*(1.0-f)));
314   switch ((int) h)
315   {
316     case 0:
317     default:
318     {
319       *red=QuantumRange*brightness;
320       *green=QuantumRange*t;
321       *blue=QuantumRange*p;
322       break;
323     }
324     case 1:
325     {
326       *red=QuantumRange*q;
327       *green=QuantumRange*brightness;
328       *blue=QuantumRange*p;
329       break;
330     }
331     case 2:
332     {
333       *red=QuantumRange*p;
334       *green=QuantumRange*brightness;
335       *blue=QuantumRange*t;
336       break;
337     }
338     case 3:
339     {
340       *red=QuantumRange*p;
341       *green=QuantumRange*q;
342       *blue=QuantumRange*brightness;
343       break;
344     }
345     case 4:
346     {
347       *red=QuantumRange*t;
348       *green=QuantumRange*p;
349       *blue=QuantumRange*brightness;
350       break;
351     }
352     case 5:
353     {
354       *red=QuantumRange*brightness;
355       *green=QuantumRange*p;
356       *blue=QuantumRange*q;
357       break;
358     }
359   }
360 }
361 
362 /*
363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
364 %                                                                             %
365 %                                                                             %
366 %                                                                             %
367 %   C o n v e r t H S I T o R G B                                             %
368 %                                                                             %
369 %                                                                             %
370 %                                                                             %
371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372 %
373 %  ConvertHSIToRGB() transforms a (hue, saturation, intensity) to a (red,
374 %  green, blue) triple.
375 %
376 %  The format of the ConvertHSIToRGBImage method is:
377 %
378 %      void ConvertHSIToRGB(const double hue,const double saturation,
379 %        const double intensity,double *red,double *green,double *blue)
380 %
381 %  A description of each parameter follows:
382 %
383 %    o hue, saturation, intensity: A double value representing a
384 %      component of the HSI color space.
385 %
386 %    o red, green, blue: A pointer to a pixel component of type Quantum.
387 %
388 */
ConvertHSIToRGB(const double hue,const double saturation,const double intensity,double * red,double * green,double * blue)389 MagickPrivate void ConvertHSIToRGB(const double hue,const double saturation,
390   const double intensity,double *red,double *green,double *blue)
391 {
392   double
393     b,
394     g,
395     h,
396     r;
397 
398   /*
399     Convert HSI to RGB colorspace.
400   */
401   assert(red != (double *) NULL);
402   assert(green != (double *) NULL);
403   assert(blue != (double *) NULL);
404   h=360.0*hue;
405   h-=360.0*floor(h/360.0);
406   if (h < 120.0)
407     {
408       b=intensity*(1.0-saturation);
409       r=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
410         (MagickPI/180.0)));
411       g=3.0*intensity-r-b;
412     }
413   else
414     if (h < 240.0)
415       {
416         h-=120.0;
417         r=intensity*(1.0-saturation);
418         g=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
419           (MagickPI/180.0)));
420         b=3.0*intensity-r-g;
421       }
422     else
423       {
424         h-=240.0;
425         g=intensity*(1.0-saturation);
426         b=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
427           (MagickPI/180.0)));
428         r=3.0*intensity-g-b;
429       }
430   *red=QuantumRange*r;
431   *green=QuantumRange*g;
432   *blue=QuantumRange*b;
433 }
434 
435 /*
436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437 %                                                                             %
438 %                                                                             %
439 %                                                                             %
440 %   C o n v e r t H S L T o R G B                                             %
441 %                                                                             %
442 %                                                                             %
443 %                                                                             %
444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445 %
446 %  ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
447 %  green, blue) triple.
448 %
449 %  The format of the ConvertHSLToRGBImage method is:
450 %
451 %      void ConvertHSLToRGB(const double hue,const double saturation,
452 %        const double lightness,double *red,double *green,double *blue)
453 %
454 %  A description of each parameter follows:
455 %
456 %    o hue, saturation, lightness: A double value representing a
457 %      component of the HSL color space.
458 %
459 %    o red, green, blue: A pointer to a pixel component of type Quantum.
460 %
461 */
ConvertHSLToRGB(const double hue,const double saturation,const double lightness,double * red,double * green,double * blue)462 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
463   const double lightness,double *red,double *green,double *blue)
464 {
465   double
466     c,
467     h,
468     min,
469     x;
470 
471   /*
472     Convert HSL to RGB colorspace.
473   */
474   assert(red != (double *) NULL);
475   assert(green != (double *) NULL);
476   assert(blue != (double *) NULL);
477   h=hue*360.0;
478   if (lightness <= 0.5)
479     c=2.0*lightness*saturation;
480   else
481     c=(2.0-2.0*lightness)*saturation;
482   min=lightness-0.5*c;
483   h-=360.0*floor(h/360.0);
484   h/=60.0;
485   x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
486   switch ((int) floor(h))
487   {
488     case 0:
489     {
490       *red=QuantumRange*(min+c);
491       *green=QuantumRange*(min+x);
492       *blue=QuantumRange*min;
493       break;
494     }
495     case 1:
496     {
497       *red=QuantumRange*(min+x);
498       *green=QuantumRange*(min+c);
499       *blue=QuantumRange*min;
500       break;
501     }
502     case 2:
503     {
504       *red=QuantumRange*min;
505       *green=QuantumRange*(min+c);
506       *blue=QuantumRange*(min+x);
507       break;
508     }
509     case 3:
510     {
511       *red=QuantumRange*min;
512       *green=QuantumRange*(min+x);
513       *blue=QuantumRange*(min+c);
514       break;
515     }
516     case 4:
517     {
518       *red=QuantumRange*(min+x);
519       *green=QuantumRange*min;
520       *blue=QuantumRange*(min+c);
521       break;
522     }
523     case 5:
524     {
525       *red=QuantumRange*(min+c);
526       *green=QuantumRange*min;
527       *blue=QuantumRange*(min+x);
528       break;
529     }
530     default:
531     {
532       *red=0.0;
533       *green=0.0;
534       *blue=0.0;
535     }
536   }
537 }
538 
539 /*
540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
541 %                                                                             %
542 %                                                                             %
543 %                                                                             %
544 %   C o n v e r t H S V T o R G B                                             %
545 %                                                                             %
546 %                                                                             %
547 %                                                                             %
548 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
549 %
550 %  ConvertHSVToRGB() transforms a (hue, saturation, value) to a (red,
551 %  green, blue) triple.
552 %
553 %  The format of the ConvertHSVToRGBImage method is:
554 %
555 %      void ConvertHSVToRGB(const double hue,const double saturation,
556 %        const double value,double *red,double *green,double *blue)
557 %
558 %  A description of each parameter follows:
559 %
560 %    o hue, saturation, value: A double value representing a
561 %      component of the HSV color space.
562 %
563 %    o red, green, blue: A pointer to a pixel component of type Quantum.
564 %
565 */
ConvertHSVToRGB(const double hue,const double saturation,const double value,double * red,double * green,double * blue)566 MagickPrivate void ConvertHSVToRGB(const double hue,const double saturation,
567   const double value,double *red,double *green,double *blue)
568 {
569   double
570     c,
571     h,
572     min,
573     x;
574 
575   /*
576     Convert HSV to RGB colorspace.
577   */
578   assert(red != (double *) NULL);
579   assert(green != (double *) NULL);
580   assert(blue != (double *) NULL);
581   h=hue*360.0;
582   c=value*saturation;
583   min=value-c;
584   h-=360.0*floor(h/360.0);
585   h/=60.0;
586   x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
587   switch ((int) floor(h))
588   {
589     case 0:
590     {
591       *red=QuantumRange*(min+c);
592       *green=QuantumRange*(min+x);
593       *blue=QuantumRange*min;
594       break;
595     }
596     case 1:
597     {
598       *red=QuantumRange*(min+x);
599       *green=QuantumRange*(min+c);
600       *blue=QuantumRange*min;
601       break;
602     }
603     case 2:
604     {
605       *red=QuantumRange*min;
606       *green=QuantumRange*(min+c);
607       *blue=QuantumRange*(min+x);
608       break;
609     }
610     case 3:
611     {
612       *red=QuantumRange*min;
613       *green=QuantumRange*(min+x);
614       *blue=QuantumRange*(min+c);
615       break;
616     }
617     case 4:
618     {
619       *red=QuantumRange*(min+x);
620       *green=QuantumRange*min;
621       *blue=QuantumRange*(min+c);
622       break;
623     }
624     case 5:
625     {
626       *red=QuantumRange*(min+c);
627       *green=QuantumRange*min;
628       *blue=QuantumRange*(min+x);
629       break;
630     }
631     default:
632     {
633       *red=0.0;
634       *green=0.0;
635       *blue=0.0;
636     }
637   }
638 }
639 
640 /*
641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
642 %                                                                             %
643 %                                                                             %
644 %                                                                             %
645 %   C o n v e r t H W B T o R G B                                             %
646 %                                                                             %
647 %                                                                             %
648 %                                                                             %
649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
650 %
651 %  ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
652 %  blue) triple.
653 %
654 %  The format of the ConvertHWBToRGBImage method is:
655 %
656 %      void ConvertHWBToRGB(const double hue,const double whiteness,
657 %        const double blackness,double *red,double *green,double *blue)
658 %
659 %  A description of each parameter follows:
660 %
661 %    o hue, whiteness, blackness: A double value representing a
662 %      component of the HWB color space.
663 %
664 %    o red, green, blue: A pointer to a pixel component of type Quantum.
665 %
666 */
ConvertHWBToRGB(const double hue,const double whiteness,const double blackness,double * red,double * green,double * blue)667 MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
668   const double blackness,double *red,double *green,double *blue)
669 {
670   double
671     b,
672     f,
673     g,
674     n,
675     r,
676     v;
677 
678   ssize_t
679     i;
680 
681   /*
682     Convert HWB to RGB colorspace.
683   */
684   assert(red != (double *) NULL);
685   assert(green != (double *) NULL);
686   assert(blue != (double *) NULL);
687   v=1.0-blackness;
688   if (fabs(hue-(-1.0)) < MagickEpsilon)
689     {
690       *red=QuantumRange*v;
691       *green=QuantumRange*v;
692       *blue=QuantumRange*v;
693       return;
694     }
695   i=CastDoubleToLong(floor(6.0*hue));
696   f=6.0*hue-i;
697   if ((i & 0x01) != 0)
698     f=1.0-f;
699   n=whiteness+f*(v-whiteness);  /* linear interpolation */
700   switch (i)
701   {
702     default:
703     case 6:
704     case 0: r=v; g=n; b=whiteness; break;
705     case 1: r=n; g=v; b=whiteness; break;
706     case 2: r=whiteness; g=v; b=n; break;
707     case 3: r=whiteness; g=n; b=v; break;
708     case 4: r=n; g=whiteness; b=v; break;
709     case 5: r=v; g=whiteness; b=n; break;
710   }
711   *red=QuantumRange*r;
712   *green=QuantumRange*g;
713   *blue=QuantumRange*b;
714 }
715 
716 /*
717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718 %                                                                             %
719 %                                                                             %
720 %                                                                             %
721 %   C o n v e r t L C H a b T o R G B                                         %
722 %                                                                             %
723 %                                                                             %
724 %                                                                             %
725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
726 %
727 %  ConvertLCHabToRGB() transforms a (luma, chroma, hue) to a (red, green,
728 %  blue) triple.
729 %
730 %  The format of the ConvertLCHabToRGBImage method is:
731 %
732 %      void ConvertLCHabToRGB(const double luma,const double chroma,
733 %        const double hue,double *red,double *green,double *blue)
734 %
735 %  A description of each parameter follows:
736 %
737 %    o luma, chroma, hue: A double value representing a component of the
738 %      LCHab color space.
739 %
740 %    o red, green, blue: A pointer to a pixel component of type Quantum.
741 %
742 */
743 
ConvertLCHabToXYZ(const double luma,const double chroma,const double hue,const IlluminantType illuminant,double * X,double * Y,double * Z)744 static inline void ConvertLCHabToXYZ(const double luma,const double chroma,
745   const double hue,const IlluminantType illuminant,double *X,double *Y,
746   double *Z)
747 {
748   ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
749     sin(hue*MagickPI/180.0),illuminant,X,Y,Z);
750 }
751 
ConvertLCHabToRGB(const double luma,const double chroma,const double hue,const IlluminantType illuminant,double * red,double * green,double * blue)752 MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
753   const double hue,const IlluminantType illuminant,double *red,double *green,
754   double *blue)
755 {
756   double
757     X,
758     Y,
759     Z;
760 
761   /*
762     Convert LCHab to RGB colorspace.
763   */
764   assert(red != (double *) NULL);
765   assert(green != (double *) NULL);
766   assert(blue != (double *) NULL);
767   ConvertLCHabToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,illuminant,
768     &X,&Y,&Z);
769   ConvertXYZToRGB(X,Y,Z,red,green,blue);
770 }
771 
772 /*
773 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
774 %                                                                             %
775 %                                                                             %
776 %                                                                             %
777 %   C o n v e r t L C H u v T o R G B                                         %
778 %                                                                             %
779 %                                                                             %
780 %                                                                             %
781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
782 %
783 %  ConvertLCHuvToRGB() transforms a (luma, chroma, hue) to a (red, green,
784 %  blue) triple.
785 %
786 %  The format of the ConvertLCHuvToRGBImage method is:
787 %
788 %      void ConvertLCHuvToRGB(const double luma,const double chroma,
789 %        const double hue,double *red,double *green,double *blue)
790 %
791 %  A description of each parameter follows:
792 %
793 %    o luma, chroma, hue: A double value representing a component of the
794 %      LCHuv color space.
795 %
796 %    o red, green, blue: A pointer to a pixel component of type Quantum.
797 %
798 */
799 
ConvertLCHuvToXYZ(const double luma,const double chroma,const double hue,const IlluminantType illuminant,double * X,double * Y,double * Z)800 static inline void ConvertLCHuvToXYZ(const double luma,const double chroma,
801   const double hue,const IlluminantType illuminant,double *X,double *Y,
802   double *Z)
803 {
804   ConvertLuvToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
805     sin(hue*MagickPI/180.0),illuminant,X,Y,Z);
806 }
807 
ConvertLCHuvToRGB(const double luma,const double chroma,const double hue,const IlluminantType illuminant,double * red,double * green,double * blue)808 MagickPrivate void ConvertLCHuvToRGB(const double luma,const double chroma,
809   const double hue,const IlluminantType illuminant,double *red,double *green,
810   double *blue)
811 {
812   double
813     X,
814     Y,
815     Z;
816 
817   /*
818     Convert LCHuv to RGB colorspace.
819   */
820   assert(red != (double *) NULL);
821   assert(green != (double *) NULL);
822   assert(blue != (double *) NULL);
823   ConvertLCHuvToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,illuminant,
824     &X,&Y,&Z);
825   ConvertXYZToRGB(X,Y,Z,red,green,blue);
826 }
827 
828 /*
829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830 %                                                                             %
831 %                                                                             %
832 %                                                                             %
833 %   C o n v e r t R G B T o H C L                                             %
834 %                                                                             %
835 %                                                                             %
836 %                                                                             %
837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
838 %
839 %  ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
840 %  luma) triple.
841 %
842 %  The format of the ConvertRGBToHCL method is:
843 %
844 %      void ConvertRGBToHCL(const double red,const double green,
845 %        const double blue,double *hue,double *chroma,double *luma)
846 %
847 %  A description of each parameter follows:
848 %
849 %    o red, green, blue: A Quantum value representing the red, green, and
850 %      blue component of a pixel.
851 %
852 %    o hue, chroma, luma: A pointer to a double value representing a
853 %      component of the HCL color space.
854 %
855 */
ConvertRGBToHCL(const double red,const double green,const double blue,double * hue,double * chroma,double * luma)856 MagickPrivate void ConvertRGBToHCL(const double red,const double green,
857   const double blue,double *hue,double *chroma,double *luma)
858 {
859   double
860     c,
861     h,
862     max;
863 
864   /*
865     Convert RGB to HCL colorspace.
866   */
867   assert(hue != (double *) NULL);
868   assert(chroma != (double *) NULL);
869   assert(luma != (double *) NULL);
870   max=MagickMax(red,MagickMax(green,blue));
871   c=max-(double) MagickMin(red,MagickMin(green,blue));
872   h=0.0;
873   if (fabs(c) < MagickEpsilon)
874     h=0.0;
875   else
876     if (fabs(red-max) < MagickEpsilon)
877       h=fmod((green-blue)/c+6.0,6.0);
878     else
879       if (fabs(green-max) < MagickEpsilon)
880         h=((blue-red)/c)+2.0;
881       else
882         if (fabs(blue-max) < MagickEpsilon)
883           h=((red-green)/c)+4.0;
884   *hue=(h/6.0);
885   *chroma=QuantumScale*c;
886   *luma=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
887 }
888 
889 /*
890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891 %                                                                             %
892 %                                                                             %
893 %                                                                             %
894 %   C o n v e r t R G B T o H C L p                                           %
895 %                                                                             %
896 %                                                                             %
897 %                                                                             %
898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899 %
900 %  ConvertRGBToHCLp() transforms a (red, green, blue) to a (hue, chroma,
901 %  luma) triple.
902 %
903 %  The format of the ConvertRGBToHCLp method is:
904 %
905 %      void ConvertRGBToHCLp(const double red,const double green,
906 %        const double blue,double *hue,double *chroma,double *luma)
907 %
908 %  A description of each parameter follows:
909 %
910 %    o red, green, blue: A Quantum value representing the red, green, and
911 %      blue component of a pixel.
912 %
913 %    o hue, chroma, luma: A pointer to a double value representing a
914 %      component of the HCL color space.
915 %
916 */
ConvertRGBToHCLp(const double red,const double green,const double blue,double * hue,double * chroma,double * luma)917 MagickPrivate void ConvertRGBToHCLp(const double red,const double green,
918   const double blue,double *hue,double *chroma,double *luma)
919 {
920   double
921     c,
922     h,
923     max;
924 
925   /*
926     Convert RGB to HCL colorspace.
927   */
928   assert(hue != (double *) NULL);
929   assert(chroma != (double *) NULL);
930   assert(luma != (double *) NULL);
931   max=MagickMax(red,MagickMax(green,blue));
932   c=max-MagickMin(red,MagickMin(green,blue));
933   h=0.0;
934   if (fabs(c) < MagickEpsilon)
935     h=0.0;
936   else
937     if (fabs(red-max) < MagickEpsilon)
938       h=fmod((green-blue)/c+6.0,6.0);
939     else
940       if (fabs(green-max) < MagickEpsilon)
941         h=((blue-red)/c)+2.0;
942       else
943         if (fabs(blue-max) < MagickEpsilon)
944           h=((red-green)/c)+4.0;
945   *hue=(h/6.0);
946   *chroma=QuantumScale*c;
947   *luma=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
948 }
949 
950 /*
951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952 %                                                                             %
953 %                                                                             %
954 %                                                                             %
955 %   C o n v e r t R G B T o H S B                                             %
956 %                                                                             %
957 %                                                                             %
958 %                                                                             %
959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
960 %
961 %  ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
962 %  brightness) triple.
963 %
964 %  The format of the ConvertRGBToHSB method is:
965 %
966 %      void ConvertRGBToHSB(const double red,const double green,
967 %        const double blue,double *hue,double *saturation,double *brightness)
968 %
969 %  A description of each parameter follows:
970 %
971 %    o red, green, blue: A Quantum value representing the red, green, and
972 %      blue component of a pixel..
973 %
974 %    o hue, saturation, brightness: A pointer to a double value representing a
975 %      component of the HSB color space.
976 %
977 */
ConvertRGBToHSB(const double red,const double green,const double blue,double * hue,double * saturation,double * brightness)978 MagickPrivate void ConvertRGBToHSB(const double red,const double green,
979   const double blue,double *hue,double *saturation,double *brightness)
980 {
981   double
982     delta,
983     max,
984     min;
985 
986   /*
987     Convert RGB to HSB colorspace.
988   */
989   assert(hue != (double *) NULL);
990   assert(saturation != (double *) NULL);
991   assert(brightness != (double *) NULL);
992   *hue=0.0;
993   *saturation=0.0;
994   *brightness=0.0;
995   min=red < green ? red : green;
996   if (blue < min)
997     min=blue;
998   max=red > green ? red : green;
999   if (blue > max)
1000     max=blue;
1001   if (fabs(max) < MagickEpsilon)
1002     return;
1003   delta=max-min;
1004   *saturation=delta/max;
1005   *brightness=QuantumScale*max;
1006   if (fabs(delta) < MagickEpsilon)
1007     return;
1008   if (fabs(red-max) < MagickEpsilon)
1009     *hue=(green-blue)/delta;
1010   else
1011     if (fabs(green-max) < MagickEpsilon)
1012       *hue=2.0+(blue-red)/delta;
1013     else
1014       *hue=4.0+(red-green)/delta;
1015   *hue/=6.0;
1016   if (*hue < 0.0)
1017     *hue+=1.0;
1018 }
1019 
1020 /*
1021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1022 %                                                                             %
1023 %                                                                             %
1024 %                                                                             %
1025 %   C o n v e r t R G B T o H S I                                             %
1026 %                                                                             %
1027 %                                                                             %
1028 %                                                                             %
1029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1030 %
1031 %  ConvertRGBToHSI() transforms a (red, green, blue) to a (hue, saturation,
1032 %  intensity) triple.
1033 %
1034 %  The format of the ConvertRGBToHSI method is:
1035 %
1036 %      void ConvertRGBToHSI(const double red,const double green,
1037 %        const double blue,double *hue,double *saturation,double *intensity)
1038 %
1039 %  A description of each parameter follows:
1040 %
1041 %    o red, green, blue: A Quantum value representing the red, green, and
1042 %      blue component of a pixel..
1043 %
1044 %    o hue, saturation, intensity: A pointer to a double value representing a
1045 %      component of the HSI color space.
1046 %
1047 */
ConvertRGBToHSI(const double red,const double green,const double blue,double * hue,double * saturation,double * intensity)1048 MagickPrivate void ConvertRGBToHSI(const double red,const double green,
1049   const double blue,double *hue,double *saturation,double *intensity)
1050 {
1051   double
1052     alpha,
1053     beta;
1054 
1055   /*
1056     Convert RGB to HSI colorspace.
1057   */
1058   assert(hue != (double *) NULL);
1059   assert(saturation != (double *) NULL);
1060   assert(intensity != (double *) NULL);
1061   *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0;
1062   if (*intensity <= 0.0)
1063     {
1064       *hue=0.0;
1065       *saturation=0.0;
1066       return;
1067     }
1068   *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1069     QuantumScale*blue))/(*intensity);
1070   alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
1071   beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue);
1072   *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
1073   if (*hue < 0.0)
1074     *hue+=1.0;
1075 }
1076 
1077 /*
1078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1079 %                                                                             %
1080 %                                                                             %
1081 %                                                                             %
1082 %   C o n v e r t R G B T o H S L                                             %
1083 %                                                                             %
1084 %                                                                             %
1085 %                                                                             %
1086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1087 %
1088 %  ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
1089 %  lightness) triple.
1090 %
1091 %  The format of the ConvertRGBToHSL method is:
1092 %
1093 %      void ConvertRGBToHSL(const double red,const double green,
1094 %        const double blue,double *hue,double *saturation,double *lightness)
1095 %
1096 %  A description of each parameter follows:
1097 %
1098 %    o red, green, blue: A Quantum value representing the red, green, and
1099 %      blue component of a pixel..
1100 %
1101 %    o hue, saturation, lightness: A pointer to a double value representing a
1102 %      component of the HSL color space.
1103 %
1104 */
ConvertRGBToHSL(const double red,const double green,const double blue,double * hue,double * saturation,double * lightness)1105 MagickExport void ConvertRGBToHSL(const double red,const double green,
1106   const double blue,double *hue,double *saturation,double *lightness)
1107 {
1108   double
1109     c,
1110     max,
1111     min;
1112 
1113   /*
1114     Convert RGB to HSL colorspace.
1115   */
1116   assert(hue != (double *) NULL);
1117   assert(saturation != (double *) NULL);
1118   assert(lightness != (double *) NULL);
1119   max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1120     QuantumScale*blue));
1121   min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1122     QuantumScale*blue));
1123   c=max-min;
1124   *lightness=(max+min)/2.0;
1125   if (c <= 0.0)
1126     {
1127       *hue=0.0;
1128       *saturation=0.0;
1129       return;
1130     }
1131   if (fabs(max-QuantumScale*red) < MagickEpsilon)
1132     {
1133       *hue=(QuantumScale*green-QuantumScale*blue)/c;
1134       if ((QuantumScale*green) < (QuantumScale*blue))
1135         *hue+=6.0;
1136     }
1137   else
1138     if (fabs(max-QuantumScale*green) < MagickEpsilon)
1139       *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1140     else
1141       *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1142   *hue*=60.0/360.0;
1143   if (*lightness <= 0.5)
1144     *saturation=c*PerceptibleReciprocal(2.0*(*lightness));
1145   else
1146     *saturation=c*PerceptibleReciprocal(2.0-2.0*(*lightness));
1147 }
1148 
1149 /*
1150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1151 %                                                                             %
1152 %                                                                             %
1153 %                                                                             %
1154 %   C o n v e r t R G B T o H S V                                             %
1155 %                                                                             %
1156 %                                                                             %
1157 %                                                                             %
1158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1159 %
1160 %  ConvertRGBToHSV() transforms a (red, green, blue) to a (hue, saturation,
1161 %  value) triple.
1162 %
1163 %  The format of the ConvertRGBToHSV method is:
1164 %
1165 %      void ConvertRGBToHSV(const double red,const double green,
1166 %        const double blue,double *hue,double *saturation,double *value)
1167 %
1168 %  A description of each parameter follows:
1169 %
1170 %    o red, green, blue: A Quantum value representing the red, green, and
1171 %      blue component of a pixel..
1172 %
1173 %    o hue, saturation, value: A pointer to a double value representing a
1174 %      component of the HSV color space.
1175 %
1176 */
ConvertRGBToHSV(const double red,const double green,const double blue,double * hue,double * saturation,double * value)1177 MagickPrivate void ConvertRGBToHSV(const double red,const double green,
1178   const double blue,double *hue,double *saturation,double *value)
1179 {
1180   double
1181     c,
1182     max,
1183     min;
1184 
1185   /*
1186     Convert RGB to HSV colorspace.
1187   */
1188   assert(hue != (double *) NULL);
1189   assert(saturation != (double *) NULL);
1190   assert(value != (double *) NULL);
1191   max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1192     QuantumScale*blue));
1193   min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1194     QuantumScale*blue));
1195   c=max-min;
1196   *value=max;
1197   if (c <= 0.0)
1198     {
1199       *hue=0.0;
1200       *saturation=0.0;
1201       return;
1202     }
1203   if (fabs(max-QuantumScale*red) < MagickEpsilon)
1204     {
1205       *hue=(QuantumScale*green-QuantumScale*blue)/c;
1206       if ((QuantumScale*green) < (QuantumScale*blue))
1207         *hue+=6.0;
1208     }
1209   else
1210     if (fabs(max-QuantumScale*green) < MagickEpsilon)
1211       *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1212     else
1213       *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1214   *hue*=60.0/360.0;
1215   *saturation=c*PerceptibleReciprocal(max);
1216 }
1217 
1218 /*
1219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220 %                                                                             %
1221 %                                                                             %
1222 %                                                                             %
1223 %   C o n v e r t R G B T o H W B                                             %
1224 %                                                                             %
1225 %                                                                             %
1226 %                                                                             %
1227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1228 %
1229 %  ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
1230 %  blackness) triple.
1231 %
1232 %  The format of the ConvertRGBToHWB method is:
1233 %
1234 %      void ConvertRGBToHWB(const double red,const double green,
1235 %        const double blue,double *hue,double *whiteness,double *blackness)
1236 %
1237 %  A description of each parameter follows:
1238 %
1239 %    o red, green, blue: A Quantum value representing the red, green, and
1240 %      blue component of a pixel.
1241 %
1242 %    o hue, whiteness, blackness: A pointer to a double value representing a
1243 %      component of the HWB color space.
1244 %
1245 */
ConvertRGBToHWB(const double red,const double green,const double blue,double * hue,double * whiteness,double * blackness)1246 MagickPrivate void ConvertRGBToHWB(const double red,const double green,
1247   const double blue,double *hue,double *whiteness,double *blackness)
1248 {
1249   double
1250     f,
1251     p,
1252     v,
1253     w;
1254 
1255   /*
1256     Convert RGB to HWB colorspace.
1257   */
1258   assert(hue != (double *) NULL);
1259   assert(whiteness != (double *) NULL);
1260   assert(blackness != (double *) NULL);
1261   w=MagickMin(red,MagickMin(green,blue));
1262   v=MagickMax(red,MagickMax(green,blue));
1263   *blackness=1.0-QuantumScale*v;
1264   *whiteness=QuantumScale*w;
1265   if (fabs(v-w) < MagickEpsilon)
1266     {
1267       *hue=(-1.0);
1268       return;
1269     }
1270   f=(fabs(red-w) < MagickEpsilon) ? green-blue :
1271     ((fabs(green-w) < MagickEpsilon) ? blue-red : red-green);
1272   p=(fabs(red-w) < MagickEpsilon) ? 3.0 :
1273     ((fabs(green-w) < MagickEpsilon) ? 5.0 : 1.0);
1274   *hue=(p-f/(v-1.0*w))/6.0;
1275 }
1276 
1277 /*
1278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1279 %                                                                             %
1280 %                                                                             %
1281 %                                                                             %
1282 %   C o n v e r t R G B T o L a b                                             %
1283 %                                                                             %
1284 %                                                                             %
1285 %                                                                             %
1286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1287 %
1288 %  ConvertRGBToLab() transforms a (red, green, blue) to a (L, a, b) triple.
1289 %
1290 %  The format of the ConvertRGBToLCHab method is:
1291 %
1292 %      void ConvertRGBToLCHab(const double red,const double green,
1293 %        const double blue,double *L,double *a,double *b)
1294 %
1295 %  A description of each parameter follows:
1296 %
1297 %    o red, green, blue: A Quantum value representing the red, green, and
1298 %      blue component of a pixel.
1299 %
1300 %    o L, a, b: A pointer to a double value representing a component of the
1301 %      Lab color space.
1302 %
1303 */
ConvertRGBToLab(const double red,const double green,const double blue,const IlluminantType illuminant,double * L,double * a,double * b)1304 MagickPrivate void ConvertRGBToLab(const double red,const double green,
1305   const double blue,const IlluminantType illuminant,double *L,double *a,
1306   double *b)
1307 {
1308   double
1309     X,
1310     Y,
1311     Z;
1312 
1313   ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1314   ConvertXYZToLab(X,Y,Z,illuminant,L,a,b);
1315 }
1316 
1317 /*
1318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1319 %                                                                             %
1320 %                                                                             %
1321 %                                                                             %
1322 %   C o n v e r t R G B T o L C H a b                                         %
1323 %                                                                             %
1324 %                                                                             %
1325 %                                                                             %
1326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1327 %
1328 %  ConvertRGBToLCHab() transforms a (red, green, blue) to a (luma, chroma,
1329 %  hue) triple.
1330 %
1331 %  The format of the ConvertRGBToLCHab method is:
1332 %
1333 %      void ConvertRGBToLCHab(const double red,const double green,
1334 %        const double blue,double *luma,double *chroma,double *hue)
1335 %
1336 %  A description of each parameter follows:
1337 %
1338 %    o red, green, blue: A Quantum value representing the red, green, and
1339 %      blue component of a pixel.
1340 %
1341 %    o luma, chroma, hue: A pointer to a double value representing a
1342 %      component of the LCH color space.
1343 %
1344 */
1345 
ConvertXYZToLCHab(const double X,const double Y,const double Z,const IlluminantType illuminant,double * luma,double * chroma,double * hue)1346 static inline void ConvertXYZToLCHab(const double X,const double Y,
1347   const double Z,const IlluminantType illuminant,double *luma,double *chroma,
1348   double *hue)
1349 {
1350   double
1351     a,
1352     b;
1353 
1354   ConvertXYZToLab(X,Y,Z,illuminant,luma,&a,&b);
1355   *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5))/255.0+0.5;
1356   *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI/360.0;
1357   if (*hue < 0.0)
1358     *hue+=1.0;
1359 }
1360 
ConvertRGBToLCHab(const double red,const double green,const double blue,const IlluminantType illuminant,double * luma,double * chroma,double * hue)1361 MagickPrivate void ConvertRGBToLCHab(const double red,const double green,
1362   const double blue,const IlluminantType illuminant,double *luma,double *chroma,
1363   double *hue)
1364 {
1365   double
1366     X,
1367     Y,
1368     Z;
1369 
1370   /*
1371     Convert RGB to LCHab colorspace.
1372   */
1373   assert(luma != (double *) NULL);
1374   assert(chroma != (double *) NULL);
1375   assert(hue != (double *) NULL);
1376   ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1377   ConvertXYZToLCHab(X,Y,Z,illuminant,luma,chroma,hue);
1378 }
1379 
1380 /*
1381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1382 %                                                                             %
1383 %                                                                             %
1384 %                                                                             %
1385 %   C o n v e r t R G B T o L C H u v                                         %
1386 %                                                                             %
1387 %                                                                             %
1388 %                                                                             %
1389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1390 %
1391 %  ConvertRGBToLCHuv() transforms a (red, green, blue) to a (luma, chroma,
1392 %  hue) triple.
1393 %
1394 %  The format of the ConvertRGBToLCHuv method is:
1395 %
1396 %      void ConvertRGBToLCHuv(const double red,const double green,
1397 %        const double blue,double *luma,double *chroma,double *hue)
1398 %
1399 %  A description of each parameter follows:
1400 %
1401 %    o red, green, blue: A Quantum value representing the red, green, and
1402 %      blue component of a pixel.
1403 %
1404 %    o luma, chroma, hue: A pointer to a double value representing a
1405 %      component of the LCHuv color space.
1406 %
1407 */
1408 
ConvertXYZToLCHuv(const double X,const double Y,const double Z,const IlluminantType illuminant,double * luma,double * chroma,double * hue)1409 static inline void ConvertXYZToLCHuv(const double X,const double Y,
1410   const double Z,const IlluminantType illuminant,double *luma,double *chroma,
1411   double *hue)
1412 {
1413   double
1414     u,
1415     v;
1416 
1417   ConvertXYZToLuv(X,Y,Z,illuminant,luma,&u,&v);
1418   *chroma=hypot(354.0*u-134.0,262.0*v-140.0)/255.0+0.5;
1419   *hue=180.0*atan2(262.0*v-140.0,354.0*u-134.0)/MagickPI/360.0;
1420   if (*hue < 0.0)
1421     *hue+=1.0;
1422 }
1423 
ConvertRGBToLCHuv(const double red,const double green,const double blue,const IlluminantType illuminant,double * luma,double * chroma,double * hue)1424 MagickPrivate void ConvertRGBToLCHuv(const double red,const double green,
1425   const double blue,const IlluminantType illuminant,double *luma,double *chroma,
1426   double *hue)
1427 {
1428   double
1429     X,
1430     Y,
1431     Z;
1432 
1433   /*
1434     Convert RGB to LCHuv colorspace.
1435   */
1436   assert(luma != (double *) NULL);
1437   assert(chroma != (double *) NULL);
1438   assert(hue != (double *) NULL);
1439   ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1440   ConvertXYZToLCHuv(X,Y,Z,illuminant,luma,chroma,hue);
1441 }
1442 
1443 /*
1444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1445 %                                                                             %
1446 %                                                                             %
1447 %                                                                             %
1448 %   E x p a n d A f f i n e                                                   %
1449 %                                                                             %
1450 %                                                                             %
1451 %                                                                             %
1452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1453 %
1454 %  ExpandAffine() computes the affine's expansion factor, i.e. the square root
1455 %  of the factor by which the affine transform affects area. In an affine
1456 %  transform composed of scaling, rotation, shearing, and translation, returns
1457 %  the amount of scaling.
1458 %
1459 %  The format of the ExpandAffine method is:
1460 %
1461 %      double ExpandAffine(const AffineMatrix *affine)
1462 %
1463 %  A description of each parameter follows:
1464 %
1465 %    o expansion: ExpandAffine returns the affine's expansion factor.
1466 %
1467 %    o affine: A pointer the affine transform of type AffineMatrix.
1468 %
1469 */
ExpandAffine(const AffineMatrix * affine)1470 MagickExport double ExpandAffine(const AffineMatrix *affine)
1471 {
1472   assert(affine != (const AffineMatrix *) NULL);
1473   return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
1474 }
1475 
1476 /*
1477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1478 %                                                                             %
1479 %                                                                             %
1480 %                                                                             %
1481 %   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                         %
1482 %                                                                             %
1483 %                                                                             %
1484 %                                                                             %
1485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1486 %
1487 %  GenerateDifferentialNoise() generates differentual noise.
1488 %
1489 %  The format of the GenerateDifferentialNoise method is:
1490 %
1491 %      double GenerateDifferentialNoise(RandomInfo *random_info,
1492 %        const Quantum pixel,const NoiseType noise_type,const double attenuate)
1493 %
1494 %  A description of each parameter follows:
1495 %
1496 %    o random_info: the random info.
1497 %
1498 %    o pixel: noise is relative to this pixel value.
1499 %
1500 %    o noise_type: the type of noise.
1501 %
1502 %    o attenuate:  attenuate the noise.
1503 %
1504 */
GenerateDifferentialNoise(RandomInfo * random_info,const Quantum pixel,const NoiseType noise_type,const double attenuate)1505 MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
1506   const Quantum pixel,const NoiseType noise_type,const double attenuate)
1507 {
1508 #define SigmaUniform  (attenuate*0.015625)
1509 #define SigmaGaussian  (attenuate*0.015625)
1510 #define SigmaImpulse  (attenuate*0.1)
1511 #define SigmaLaplacian (attenuate*0.0390625)
1512 #define SigmaMultiplicativeGaussian  (attenuate*0.5)
1513 #define SigmaPoisson  (attenuate*12.5)
1514 #define SigmaRandom  (attenuate)
1515 #define TauGaussian  (attenuate*0.078125)
1516 
1517   double
1518     alpha,
1519     beta,
1520     noise,
1521     sigma;
1522 
1523   alpha=GetPseudoRandomValue(random_info);
1524   switch (noise_type)
1525   {
1526     case UniformNoise:
1527     default:
1528     {
1529       noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
1530       break;
1531     }
1532     case GaussianNoise:
1533     {
1534       double
1535         gamma,
1536         tau;
1537 
1538       if (fabs(alpha) < MagickEpsilon)
1539         alpha=1.0;
1540       beta=GetPseudoRandomValue(random_info);
1541       gamma=sqrt(-2.0*log(alpha));
1542       sigma=gamma*cos((double) (2.0*MagickPI*beta));
1543       tau=gamma*sin((double) (2.0*MagickPI*beta));
1544       noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
1545         QuantumRange*TauGaussian*tau);
1546       break;
1547     }
1548     case ImpulseNoise:
1549     {
1550       if (alpha < (SigmaImpulse/2.0))
1551         noise=0.0;
1552       else
1553         if (alpha >= (1.0-(SigmaImpulse/2.0)))
1554           noise=(double) QuantumRange;
1555         else
1556           noise=(double) pixel;
1557       break;
1558     }
1559     case LaplacianNoise:
1560     {
1561       if (alpha <= 0.5)
1562         {
1563           if (alpha <= MagickEpsilon)
1564             noise=(double) (pixel-QuantumRange);
1565           else
1566             noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
1567               0.5);
1568           break;
1569         }
1570       beta=1.0-alpha;
1571       if (beta <= (0.5*MagickEpsilon))
1572         noise=(double) (pixel+QuantumRange);
1573       else
1574         noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
1575       break;
1576     }
1577     case MultiplicativeGaussianNoise:
1578     {
1579       sigma=1.0;
1580       if (alpha > MagickEpsilon)
1581         sigma=sqrt(-2.0*log(alpha));
1582       beta=GetPseudoRandomValue(random_info);
1583       noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
1584         cos((double) (2.0*MagickPI*beta))/2.0);
1585       break;
1586     }
1587     case PoissonNoise:
1588     {
1589       double
1590         poisson;
1591 
1592       ssize_t
1593         i;
1594 
1595       poisson=exp(-SigmaPoisson*QuantumScale*pixel);
1596       for (i=0; alpha > poisson; i++)
1597       {
1598         beta=GetPseudoRandomValue(random_info);
1599         alpha*=beta;
1600       }
1601       noise=(double) (QuantumRange*i*PerceptibleReciprocal(SigmaPoisson));
1602       break;
1603     }
1604     case RandomNoise:
1605     {
1606       noise=(double) (QuantumRange*SigmaRandom*alpha);
1607       break;
1608     }
1609   }
1610   return(noise);
1611 }
1612 
1613 /*
1614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1615 %                                                                             %
1616 %                                                                             %
1617 %                                                                             %
1618 %   G e t O p t i m a l K e r n e l W i d t h                                 %
1619 %                                                                             %
1620 %                                                                             %
1621 %                                                                             %
1622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1623 %
1624 %  GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
1625 %  filter.  Start with the minimum value of 3 pixels and walk out until we drop
1626 %  below the threshold of one pixel numerical accuracy.
1627 %
1628 %  The format of the GetOptimalKernelWidth method is:
1629 %
1630 %      size_t GetOptimalKernelWidth(const double radius,
1631 %        const double sigma)
1632 %
1633 %  A description of each parameter follows:
1634 %
1635 %    o width: GetOptimalKernelWidth returns the optimal width of a
1636 %      convolution kernel.
1637 %
1638 %    o radius: the radius of the Gaussian, in pixels, not counting the center
1639 %      pixel.
1640 %
1641 %    o sigma: the standard deviation of the Gaussian, in pixels.
1642 %
1643 */
GetOptimalKernelWidth1D(const double radius,const double sigma)1644 MagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
1645   const double sigma)
1646 {
1647   double
1648     alpha,
1649     beta,
1650     gamma,
1651     normalize,
1652     value;
1653 
1654   ssize_t
1655     i;
1656 
1657   size_t
1658     width;
1659 
1660   ssize_t
1661     j;
1662 
1663   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1664   if (radius > MagickEpsilon)
1665     return((size_t) (2.0*ceil(radius)+1.0));
1666   gamma=fabs(sigma);
1667   if (gamma <= MagickEpsilon)
1668     return(3UL);
1669   alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1670   beta=(double) PerceptibleReciprocal((double) MagickSQ2PI*gamma);
1671   for (width=5; ; )
1672   {
1673     normalize=0.0;
1674     j=(ssize_t) (width-1)/2;
1675     for (i=(-j); i <= j; i++)
1676       normalize+=exp(-((double) (i*i))*alpha)*beta;
1677     value=exp(-((double) (j*j))*alpha)*beta/normalize;
1678     if ((value < QuantumScale) || (value < MagickEpsilon))
1679       break;
1680     width+=2;
1681   }
1682   return((size_t) (width-2));
1683 }
1684 
GetOptimalKernelWidth2D(const double radius,const double sigma)1685 MagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
1686   const double sigma)
1687 {
1688   double
1689     alpha,
1690     beta,
1691     gamma,
1692     normalize,
1693     value;
1694 
1695   size_t
1696     width;
1697 
1698   ssize_t
1699     j,
1700     u,
1701     v;
1702 
1703   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1704   if (radius > MagickEpsilon)
1705     return((size_t) (2.0*ceil(radius)+1.0));
1706   gamma=fabs(sigma);
1707   if (gamma <= MagickEpsilon)
1708     return(3UL);
1709   alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1710   beta=(double) PerceptibleReciprocal((double) Magick2PI*gamma*gamma);
1711   for (width=5; ; )
1712   {
1713     normalize=0.0;
1714     j=(ssize_t) (width-1)/2;
1715     for (v=(-j); v <= j; v++)
1716       for (u=(-j); u <= j; u++)
1717         normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
1718     value=exp(-((double) (j*j))*alpha)*beta/normalize;
1719     if ((value < QuantumScale) || (value < MagickEpsilon))
1720       break;
1721     width+=2;
1722   }
1723   return((size_t) (width-2));
1724 }
1725 
GetOptimalKernelWidth(const double radius,const double sigma)1726 MagickPrivate size_t  GetOptimalKernelWidth(const double radius,
1727   const double sigma)
1728 {
1729   return(GetOptimalKernelWidth1D(radius,sigma));
1730 }
1731