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