MagickCore  7.1.0
gem.c
Go to the documentation of this file.
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"
45 #include "MagickCore/draw.h"
46 #include "MagickCore/gem.h"
47 #include "MagickCore/gem-private.h"
48 #include "MagickCore/image.h"
50 #include "MagickCore/log.h"
51 #include "MagickCore/memory_.h"
54 #include "MagickCore/quantum.h"
56 #include "MagickCore/random_.h"
57 #include "MagickCore/resize.h"
58 #include "MagickCore/transform.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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 
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 
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 
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 
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 */
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 */
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 */
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 */
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 */
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);
1120  QuantumScale*blue));
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 */
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);
1192  QuantumScale*blue));
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 */
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 */
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 
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 
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 
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 
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 */
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 */
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 
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;
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+
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  }
1578  {
1579  sigma=1.0;
1580  if (alpha > MagickEpsilon)
1581  sigma=sqrt(-2.0*log(alpha));
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  {
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 */
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 
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 
1726 MagickPrivate size_t GetOptimalKernelWidth(const double radius,
1727  const double sigma)
1728 {
1729  return(GetOptimalKernelWidth1D(radius,sigma));
1730 }
#define SigmaPoisson
static void ConvertLCHuvToXYZ(const double luma, const double chroma, const double hue, const IlluminantType illuminant, double *X, double *Y, double *Z)
Definition: gem.c:800
double rx
Definition: geometry.h:96
MagickExport void ConvertRGBToHSL(const double red, const double green, const double blue, double *hue, double *saturation, double *lightness)
Definition: gem.c:1105
static void ConvertXYZToLuv(const double X, const double Y, const double Z, const IlluminantType illuminant, double *L, double *u, double *v)
Definition: gem-private.h:310
#define SigmaRandom
#define MagickPI
Definition: image-private.h:40
MagickPrivate void ConvertRGBToHSV(const double red, const double green, const double blue, double *hue, double *saturation, double *value)
Definition: gem.c:1177
NoiseType
MagickPrivate void ConvertHSVToRGB(const double hue, const double saturation, const double value, double *red, double *green, double *blue)
Definition: gem.c:566
#define MagickEpsilon
Definition: magick-type.h:114
#define SigmaLaplacian
MagickPrivate void ConvertHSBToRGB(const double hue, const double saturation, const double brightness, double *red, double *green, double *blue)
Definition: gem.c:286
Definition: log.h:52
MagickPrivate void ConvertHSIToRGB(const double hue, const double saturation, const double intensity, double *red, double *green, double *blue)
Definition: gem.c:389
MagickPrivate size_t GetOptimalKernelWidth(const double radius, const double sigma)
Definition: gem.c:1726
MagickExport double ExpandAffine(const AffineMatrix *affine)
Definition: gem.c:1470
#define SigmaUniform
static double PerceptibleReciprocal(const double x)
MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info, const Quantum pixel, const NoiseType noise_type, const double attenuate)
Definition: gem.c:1505
#define Magick2PI
Definition: image-private.h:34
static void ConvertXYZToLCHuv(const double X, const double Y, const double Z, const IlluminantType illuminant, double *luma, double *chroma, double *hue)
Definition: gem.c:1409
#define SigmaGaussian
MagickPrivate size_t GetOptimalKernelWidth1D(const double radius, const double sigma)
Definition: gem.c:1644
#define MagickSQ2PI
Definition: image-private.h:43
#define SigmaMultiplicativeGaussian
#define TauGaussian
double ry
Definition: geometry.h:96
static void ConvertXYZToLab(const double X, const double Y, const double Z, const IlluminantType illuminant, double *L, double *a, double *b)
Definition: gem-private.h:282
double sx
Definition: geometry.h:96
static void ConvertLCHabToXYZ(const double luma, const double chroma, const double hue, const IlluminantType illuminant, double *X, double *Y, double *Z)
Definition: gem.c:744
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1660
static void ConvertLabToXYZ(const double L, const double a, const double b, const IlluminantType illuminant, double *X, double *Y, double *Z)
Definition: gem-private.h:139
#define QuantumScale
Definition: magick-type.h:119
MagickPrivate void ConvertRGBToLCHab(const double red, const double green, const double blue, const IlluminantType illuminant, double *luma, double *chroma, double *hue)
Definition: gem.c:1361
IlluminantType
Definition: color.h:40
MagickExport void ConvertHSLToRGB(const double hue, const double saturation, const double lightness, double *red, double *green, double *blue)
Definition: gem.c:462
#define MagickMax(x, y)
Definition: image-private.h:36
static void ConvertLuvToXYZ(const double L, const double u, const double v, const IlluminantType illuminant, double *X, double *Y, double *Z)
Definition: gem-private.h:170
MagickPrivate size_t GetOptimalKernelWidth2D(const double radius, const double sigma)
Definition: gem.c:1685
MagickPrivate void ConvertHCLToRGB(const double hue, const double chroma, const double luma, double *red, double *green, double *blue)
Definition: gem.c:88
static ssize_t CastDoubleToLong(const double value)
Definition: image-private.h:53
#define GetMagickModule()
Definition: log.h:28
double sy
Definition: geometry.h:96
static void ConvertRGBToXYZ(const double red, const double green, const double blue, double *X, double *Y, double *Z)
Definition: gem-private.h:222
unsigned short Quantum
Definition: magick-type.h:86
MagickPrivate void ConvertHWBToRGB(const double hue, const double whiteness, const double blackness, double *red, double *green, double *blue)
Definition: gem.c:667
MagickExport double GetPseudoRandomValue(RandomInfo *magick_restrict random_info)
Definition: random.c:584
MagickPrivate void ConvertLCHabToRGB(const double luma, const double chroma, const double hue, const IlluminantType illuminant, double *red, double *green, double *blue)
Definition: gem.c:752
MagickPrivate void ConvertRGBToLab(const double red, const double green, const double blue, const IlluminantType illuminant, double *L, double *a, double *b)
Definition: gem.c:1304
MagickPrivate void ConvertLCHuvToRGB(const double luma, const double chroma, const double hue, const IlluminantType illuminant, double *red, double *green, double *blue)
Definition: gem.c:808
#define MagickMin(x, y)
Definition: image-private.h:37
static RandomInfo * random_info
Definition: resource.c:113
MagickPrivate void ConvertRGBToHCL(const double red, const double green, const double blue, double *hue, double *chroma, double *luma)
Definition: gem.c:856
#define SigmaImpulse
static void ConvertXYZToRGB(const double X, const double Y, const double Z, double *red, double *green, double *blue)
Definition: gem-private.h:357
MagickPrivate void ConvertRGBToHSI(const double red, const double green, const double blue, double *hue, double *saturation, double *intensity)
Definition: gem.c:1048
#define MagickPrivate
MagickPrivate void ConvertRGBToLCHuv(const double red, const double green, const double blue, const IlluminantType illuminant, double *luma, double *chroma, double *hue)
Definition: gem.c:1424
#define MagickExport
MagickPrivate void ConvertRGBToHWB(const double red, const double green, const double blue, double *hue, double *whiteness, double *blackness)
Definition: gem.c:1246
static void ConvertXYZToLCHab(const double X, const double Y, const double Z, const IlluminantType illuminant, double *luma, double *chroma, double *hue)
Definition: gem.c:1346
#define QuantumRange
Definition: magick-type.h:87
MagickPrivate void ConvertRGBToHCLp(const double red, const double green, const double blue, double *hue, double *chroma, double *luma)
Definition: gem.c:917
MagickPrivate void ConvertHCLpToRGB(const double hue, const double chroma, const double luma, double *red, double *green, double *blue)
Definition: gem.c:181
MagickPrivate void ConvertRGBToHSB(const double red, const double green, const double blue, double *hue, double *saturation, double *brightness)
Definition: gem.c:978