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