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-2016 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41  Include declarations.
42*/
43#include "MagickCore/studio.h"
44#include "MagickCore/color-private.h"
45#include "MagickCore/draw.h"
46#include "MagickCore/gem.h"
47#include "MagickCore/gem-private.h"
48#include "MagickCore/image.h"
49#include "MagickCore/image-private.h"
50#include "MagickCore/log.h"
51#include "MagickCore/memory_.h"
52#include "MagickCore/pixel-accessor.h"
53#include "MagickCore/pixel-private.h"
54#include "MagickCore/quantum.h"
55#include "MagickCore/quantum-private.h"
56#include "MagickCore/random_.h"
57#include "MagickCore/resize.h"
58#include "MagickCore/transform.h"
59#include "MagickCore/signature-private.h"
60
61/*
62%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63%                                                                             %
64%                                                                             %
65%                                                                             %
66%   C o n v e r t H C L T o R G B                                             %
67%                                                                             %
68%                                                                             %
69%                                                                             %
70%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71%
72%  ConvertHCLToRGB() transforms a (hue, chroma, luma) to a (red, green,
73%  blue) triple.
74%
75%  The format of the ConvertHCLToRGBImage method is:
76%
77%      void ConvertHCLToRGB(const double hue,const double chroma,
78%        const double luma,double *red,double *green,double *blue)
79%
80%  A description of each parameter follows:
81%
82%    o hue, chroma, luma: A double value representing a component of the
83%      HCL color space.
84%
85%    o red, green, blue: A pointer to a pixel component of type Quantum.
86%
87*/
88MagickPrivate 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*/
181MagickPrivate 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*/
286MagickPrivate 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*/
389MagickPrivate 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*/
462MagickExport 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*/
566MagickPrivate 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*/
667MagickPrivate 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  register 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=(ssize_t) 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
744static inline void ConvertLCHabToXYZ(const double luma,const double chroma,
745  const double hue,double *X,double *Y,double *Z)
746{
747  ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
748    sin(hue*MagickPI/180.0),X,Y,Z);
749}
750
751MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
752  const double hue,double *red,double *green,double *blue)
753{
754  double
755    X,
756    Y,
757    Z;
758
759  /*
760    Convert LCHab to RGB colorspace.
761  */
762  assert(red != (double *) NULL);
763  assert(green != (double *) NULL);
764  assert(blue != (double *) NULL);
765  ConvertLCHabToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z);
766  ConvertXYZToRGB(X,Y,Z,red,green,blue);
767}
768
769/*
770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
771%                                                                             %
772%                                                                             %
773%                                                                             %
774%   C o n v e r t L C H u v T o R G B                                         %
775%                                                                             %
776%                                                                             %
777%                                                                             %
778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
779%
780%  ConvertLCHuvToRGB() transforms a (luma, chroma, hue) to a (red, green,
781%  blue) triple.
782%
783%  The format of the ConvertLCHuvToRGBImage method is:
784%
785%      void ConvertLCHuvToRGB(const double luma,const double chroma,
786%        const double hue,double *red,double *green,double *blue)
787%
788%  A description of each parameter follows:
789%
790%    o luma, chroma, hue: A double value representing a component of the
791%      LCHuv color space.
792%
793%    o red, green, blue: A pointer to a pixel component of type Quantum.
794%
795*/
796
797static inline void ConvertLCHuvToXYZ(const double luma,const double chroma,
798  const double hue,double *X,double *Y,double *Z)
799{
800  ConvertLuvToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
801    sin(hue*MagickPI/180.0),X,Y,Z);
802}
803
804MagickPrivate void ConvertLCHuvToRGB(const double luma,const double chroma,
805  const double hue,double *red,double *green,double *blue)
806{
807  double
808    X,
809    Y,
810    Z;
811
812  /*
813    Convert LCHuv to RGB colorspace.
814  */
815  assert(red != (double *) NULL);
816  assert(green != (double *) NULL);
817  assert(blue != (double *) NULL);
818  ConvertLCHuvToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z);
819  ConvertXYZToRGB(X,Y,Z,red,green,blue);
820}
821
822/*
823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824%                                                                             %
825%                                                                             %
826%                                                                             %
827%   C o n v e r t R G B T o H C L                                             %
828%                                                                             %
829%                                                                             %
830%                                                                             %
831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832%
833%  ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
834%  luma) triple.
835%
836%  The format of the ConvertRGBToHCL method is:
837%
838%      void ConvertRGBToHCL(const double red,const double green,
839%        const double blue,double *hue,double *chroma,double *luma)
840%
841%  A description of each parameter follows:
842%
843%    o red, green, blue: A Quantum value representing the red, green, and
844%      blue component of a pixel.
845%
846%    o hue, chroma, luma: A pointer to a double value representing a
847%      component of the HCL color space.
848%
849*/
850MagickPrivate void ConvertRGBToHCL(const double red,const double green,
851  const double blue,double *hue,double *chroma,double *luma)
852{
853  double
854    c,
855    h,
856    max;
857
858  /*
859    Convert RGB to HCL colorspace.
860  */
861  assert(hue != (double *) NULL);
862  assert(chroma != (double *) NULL);
863  assert(luma != (double *) NULL);
864  max=MagickMax(red,MagickMax(green,blue));
865  c=max-(double) MagickMin(red,MagickMin(green,blue));
866  h=0.0;
867  if (fabs(c) < MagickEpsilon)
868    h=0.0;
869  else
870    if (fabs(red-max) < MagickEpsilon)
871      h=fmod((green-blue)/c+6.0,6.0);
872    else
873      if (fabs(green-max) < MagickEpsilon)
874        h=((blue-red)/c)+2.0;
875      else
876        if (fabs(blue-max) < MagickEpsilon)
877          h=((red-green)/c)+4.0;
878  *hue=(h/6.0);
879  *chroma=QuantumScale*c;
880  *luma=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
881}
882
883/*
884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
885%                                                                             %
886%                                                                             %
887%                                                                             %
888%   C o n v e r t R G B T o H C L p                                           %
889%                                                                             %
890%                                                                             %
891%                                                                             %
892%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
893%
894%  ConvertRGBToHCLp() transforms a (red, green, blue) to a (hue, chroma,
895%  luma) triple.
896%
897%  The format of the ConvertRGBToHCLp method is:
898%
899%      void ConvertRGBToHCLp(const double red,const double green,
900%        const double blue,double *hue,double *chroma,double *luma)
901%
902%  A description of each parameter follows:
903%
904%    o red, green, blue: A Quantum value representing the red, green, and
905%      blue component of a pixel.
906%
907%    o hue, chroma, luma: A pointer to a double value representing a
908%      component of the HCL color space.
909%
910*/
911MagickPrivate void ConvertRGBToHCLp(const double red,const double green,
912  const double blue,double *hue,double *chroma,double *luma)
913{
914  double
915    c,
916    h,
917    max;
918
919  /*
920    Convert RGB to HCL colorspace.
921  */
922  assert(hue != (double *) NULL);
923  assert(chroma != (double *) NULL);
924  assert(luma != (double *) NULL);
925  max=MagickMax(red,MagickMax(green,blue));
926  c=max-MagickMin(red,MagickMin(green,blue));
927  h=0.0;
928  if (fabs(c) < MagickEpsilon)
929    h=0.0;
930  else
931    if (fabs(red-max) < MagickEpsilon)
932      h=fmod((green-blue)/c+6.0,6.0);
933    else
934      if (fabs(green-max) < MagickEpsilon)
935        h=((blue-red)/c)+2.0;
936      else
937        if (fabs(blue-max) < MagickEpsilon)
938          h=((red-green)/c)+4.0;
939  *hue=(h/6.0);
940  *chroma=QuantumScale*c;
941  *luma=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
942}
943
944/*
945%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
946%                                                                             %
947%                                                                             %
948%                                                                             %
949%   C o n v e r t R G B T o H S B                                             %
950%                                                                             %
951%                                                                             %
952%                                                                             %
953%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954%
955%  ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
956%  brightness) triple.
957%
958%  The format of the ConvertRGBToHSB method is:
959%
960%      void ConvertRGBToHSB(const double red,const double green,
961%        const double blue,double *hue,double *saturation,double *brightness)
962%
963%  A description of each parameter follows:
964%
965%    o red, green, blue: A Quantum value representing the red, green, and
966%      blue component of a pixel..
967%
968%    o hue, saturation, brightness: A pointer to a double value representing a
969%      component of the HSB color space.
970%
971*/
972MagickPrivate void ConvertRGBToHSB(const double red,const double green,
973  const double blue,double *hue,double *saturation,double *brightness)
974{
975  double
976    delta,
977    max,
978    min;
979
980  /*
981    Convert RGB to HSB colorspace.
982  */
983  assert(hue != (double *) NULL);
984  assert(saturation != (double *) NULL);
985  assert(brightness != (double *) NULL);
986  *hue=0.0;
987  *saturation=0.0;
988  *brightness=0.0;
989  min=red < green ? red : green;
990  if (blue < min)
991    min=blue;
992  max=red > green ? red : green;
993  if (blue > max)
994    max=blue;
995  if (fabs(max) < MagickEpsilon)
996    return;
997  delta=max-min;
998  *saturation=delta/max;
999  *brightness=QuantumScale*max;
1000  if (fabs(delta) < MagickEpsilon)
1001    return;
1002  if (fabs(red-max) < MagickEpsilon)
1003    *hue=(green-blue)/delta;
1004  else
1005    if (fabs(green-max) < MagickEpsilon)
1006      *hue=2.0+(blue-red)/delta;
1007    else
1008      *hue=4.0+(red-green)/delta;
1009  *hue/=6.0;
1010  if (*hue < 0.0)
1011    *hue+=1.0;
1012}
1013
1014/*
1015%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1016%                                                                             %
1017%                                                                             %
1018%                                                                             %
1019%   C o n v e r t R G B T o H S I                                             %
1020%                                                                             %
1021%                                                                             %
1022%                                                                             %
1023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024%
1025%  ConvertRGBToHSI() transforms a (red, green, blue) to a (hue, saturation,
1026%  intensity) triple.
1027%
1028%  The format of the ConvertRGBToHSI method is:
1029%
1030%      void ConvertRGBToHSI(const double red,const double green,
1031%        const double blue,double *hue,double *saturation,double *intensity)
1032%
1033%  A description of each parameter follows:
1034%
1035%    o red, green, blue: A Quantum value representing the red, green, and
1036%      blue component of a pixel..
1037%
1038%    o hue, saturation, intensity: A pointer to a double value representing a
1039%      component of the HSI color space.
1040%
1041*/
1042MagickPrivate void ConvertRGBToHSI(const double red,const double green,
1043  const double blue,double *hue,double *saturation,double *intensity)
1044{
1045  double
1046    alpha,
1047    beta;
1048
1049  /*
1050    Convert RGB to HSI colorspace.
1051  */
1052  assert(hue != (double *) NULL);
1053  assert(saturation != (double *) NULL);
1054  assert(intensity != (double *) NULL);
1055  *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0;
1056  if (*intensity <= 0.0)
1057    {
1058      *hue=0.0;
1059      *saturation=0.0;
1060      return;
1061    }
1062  *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1063    QuantumScale*blue))/(*intensity);
1064  alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
1065  beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue);
1066  *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
1067  if (*hue < 0.0)
1068    *hue+=1.0;
1069}
1070
1071/*
1072%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1073%                                                                             %
1074%                                                                             %
1075%                                                                             %
1076%   C o n v e r t R G B T o H S L                                             %
1077%                                                                             %
1078%                                                                             %
1079%                                                                             %
1080%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1081%
1082%  ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
1083%  lightness) triple.
1084%
1085%  The format of the ConvertRGBToHSL method is:
1086%
1087%      void ConvertRGBToHSL(const double red,const double green,
1088%        const double blue,double *hue,double *saturation,double *lightness)
1089%
1090%  A description of each parameter follows:
1091%
1092%    o red, green, blue: A Quantum value representing the red, green, and
1093%      blue component of a pixel..
1094%
1095%    o hue, saturation, lightness: A pointer to a double value representing a
1096%      component of the HSL color space.
1097%
1098*/
1099MagickExport void ConvertRGBToHSL(const double red,const double green,
1100  const double blue,double *hue,double *saturation,double *lightness)
1101{
1102  double
1103    c,
1104    max,
1105    min;
1106
1107  /*
1108    Convert RGB to HSL colorspace.
1109  */
1110  assert(hue != (double *) NULL);
1111  assert(saturation != (double *) NULL);
1112  assert(lightness != (double *) NULL);
1113  max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1114    QuantumScale*blue));
1115  min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1116    QuantumScale*blue));
1117  c=max-min;
1118  *lightness=(max+min)/2.0;
1119  if (c <= 0.0)
1120    {
1121      *hue=0.0;
1122      *saturation=0.0;
1123      return;
1124    }
1125  if (fabs(max-QuantumScale*red) < MagickEpsilon)
1126    {
1127      *hue=(QuantumScale*green-QuantumScale*blue)/c;
1128      if ((QuantumScale*green) < (QuantumScale*blue))
1129        *hue+=6.0;
1130    }
1131  else
1132    if (fabs(max-QuantumScale*green) < MagickEpsilon)
1133      *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1134    else
1135      *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1136  *hue*=60.0/360.0;
1137  if (*lightness <= 0.5)
1138    *saturation=c/(2.0*(*lightness));
1139  else
1140    *saturation=c/(2.0-2.0*(*lightness));
1141}
1142
1143/*
1144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1145%                                                                             %
1146%                                                                             %
1147%                                                                             %
1148%   C o n v e r t R G B T o H S V                                             %
1149%                                                                             %
1150%                                                                             %
1151%                                                                             %
1152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1153%
1154%  ConvertRGBToHSV() transforms a (red, green, blue) to a (hue, saturation,
1155%  value) triple.
1156%
1157%  The format of the ConvertRGBToHSV method is:
1158%
1159%      void ConvertRGBToHSV(const double red,const double green,
1160%        const double blue,double *hue,double *saturation,double *value)
1161%
1162%  A description of each parameter follows:
1163%
1164%    o red, green, blue: A Quantum value representing the red, green, and
1165%      blue component of a pixel..
1166%
1167%    o hue, saturation, value: A pointer to a double value representing a
1168%      component of the HSV color space.
1169%
1170*/
1171MagickPrivate void ConvertRGBToHSV(const double red,const double green,
1172  const double blue,double *hue,double *saturation,double *value)
1173{
1174  double
1175    c,
1176    max,
1177    min;
1178
1179  /*
1180    Convert RGB to HSV colorspace.
1181  */
1182  assert(hue != (double *) NULL);
1183  assert(saturation != (double *) NULL);
1184  assert(value != (double *) NULL);
1185  max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1186    QuantumScale*blue));
1187  min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1188    QuantumScale*blue));
1189  c=max-min;
1190  *value=max;
1191  if (c <= 0.0)
1192    {
1193      *hue=0.0;
1194      *saturation=0.0;
1195      return;
1196    }
1197  if (fabs(max-QuantumScale*red) < MagickEpsilon)
1198    {
1199      *hue=(QuantumScale*green-QuantumScale*blue)/c;
1200      if ((QuantumScale*green) < (QuantumScale*blue))
1201        *hue+=6.0;
1202    }
1203  else
1204    if (fabs(max-QuantumScale*green) < MagickEpsilon)
1205      *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1206    else
1207      *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1208  *hue*=60.0/360.0;
1209  *saturation=c/max;
1210}
1211
1212/*
1213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1214%                                                                             %
1215%                                                                             %
1216%                                                                             %
1217%   C o n v e r t R G B T o H W B                                             %
1218%                                                                             %
1219%                                                                             %
1220%                                                                             %
1221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1222%
1223%  ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
1224%  blackness) triple.
1225%
1226%  The format of the ConvertRGBToHWB method is:
1227%
1228%      void ConvertRGBToHWB(const double red,const double green,
1229%        const double blue,double *hue,double *whiteness,double *blackness)
1230%
1231%  A description of each parameter follows:
1232%
1233%    o red, green, blue: A Quantum value representing the red, green, and
1234%      blue component of a pixel.
1235%
1236%    o hue, whiteness, blackness: A pointer to a double value representing a
1237%      component of the HWB color space.
1238%
1239*/
1240MagickPrivate void ConvertRGBToHWB(const double red,const double green,
1241  const double blue,double *hue,double *whiteness,double *blackness)
1242{
1243  double
1244    f,
1245    p,
1246    v,
1247    w;
1248
1249  /*
1250    Convert RGB to HWB colorspace.
1251  */
1252  assert(hue != (double *) NULL);
1253  assert(whiteness != (double *) NULL);
1254  assert(blackness != (double *) NULL);
1255  w=MagickMin(red,MagickMin(green,blue));
1256  v=MagickMax(red,MagickMax(green,blue));
1257  *blackness=1.0-QuantumScale*v;
1258  *whiteness=QuantumScale*w;
1259  if (fabs(v-w) < MagickEpsilon)
1260    {
1261      *hue=(-1.0);
1262      return;
1263    }
1264  f=(fabs(red-w) < MagickEpsilon) ? green-blue :
1265    ((fabs(green-w) < MagickEpsilon) ? blue-red : red-green);
1266  p=(fabs(red-w) < MagickEpsilon) ? 3.0 :
1267    ((fabs(green-w) < MagickEpsilon) ? 5.0 : 1.0);
1268  *hue=(p-f/(v-1.0*w))/6.0;
1269}
1270
1271/*
1272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1273%                                                                             %
1274%                                                                             %
1275%                                                                             %
1276%   C o n v e r t R G B T o L C H a b                                         %
1277%                                                                             %
1278%                                                                             %
1279%                                                                             %
1280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1281%
1282%  ConvertRGBToLCHab() transforms a (red, green, blue) to a (luma, chroma,
1283%  hue) triple.
1284%
1285%  The format of the ConvertRGBToLCHab method is:
1286%
1287%      void ConvertRGBToLCHab(const double red,const double green,
1288%        const double blue,double *luma,double *chroma,double *hue)
1289%
1290%  A description of each parameter follows:
1291%
1292%    o red, green, blue: A Quantum value representing the red, green, and
1293%      blue component of a pixel.
1294%
1295%    o luma, chroma, hue: A pointer to a double value representing a
1296%      component of the LCH color space.
1297%
1298*/
1299
1300static inline void ConvertXYZToLCHab(const double X,const double Y,
1301  const double Z,double *luma,double *chroma,double *hue)
1302{
1303  double
1304    a,
1305    b;
1306
1307  ConvertXYZToLab(X,Y,Z,luma,&a,&b);
1308  *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5))/255.0+0.5;
1309  *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI/360.0;
1310  if (*hue < 0.0)
1311    *hue+=1.0;
1312}
1313
1314MagickPrivate void ConvertRGBToLCHab(const double red,const double green,
1315  const double blue,double *luma,double *chroma,double *hue)
1316{
1317  double
1318    X,
1319    Y,
1320    Z;
1321
1322  /*
1323    Convert RGB to LCHab colorspace.
1324  */
1325  assert(luma != (double *) NULL);
1326  assert(chroma != (double *) NULL);
1327  assert(hue != (double *) NULL);
1328  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1329  ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue);
1330}
1331
1332/*
1333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1334%                                                                             %
1335%                                                                             %
1336%                                                                             %
1337%   C o n v e r t R G B T o L C H u v                                         %
1338%                                                                             %
1339%                                                                             %
1340%                                                                             %
1341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1342%
1343%  ConvertRGBToLCHuv() transforms a (red, green, blue) to a (luma, chroma,
1344%  hue) triple.
1345%
1346%  The format of the ConvertRGBToLCHuv method is:
1347%
1348%      void ConvertRGBToLCHuv(const double red,const double green,
1349%        const double blue,double *luma,double *chroma,double *hue)
1350%
1351%  A description of each parameter follows:
1352%
1353%    o red, green, blue: A Quantum value representing the red, green, and
1354%      blue component of a pixel.
1355%
1356%    o luma, chroma, hue: A pointer to a double value representing a
1357%      component of the LCHuv color space.
1358%
1359*/
1360
1361static inline void ConvertXYZToLCHuv(const double X,const double Y,
1362  const double Z,double *luma,double *chroma,double *hue)
1363{
1364  double
1365    u,
1366    v;
1367
1368  ConvertXYZToLuv(X,Y,Z,luma,&u,&v);
1369  *chroma=hypot(354.0*u-134.0,262.0*v-140.0)/255.0+0.5;
1370  *hue=180.0*atan2(262.0*v-140.0,354.0*u-134.0)/MagickPI/360.0;
1371  if (*hue < 0.0)
1372    *hue+=1.0;
1373}
1374
1375MagickPrivate void ConvertRGBToLCHuv(const double red,const double green,
1376  const double blue,double *luma,double *chroma,double *hue)
1377{
1378  double
1379    X,
1380    Y,
1381    Z;
1382
1383  /*
1384    Convert RGB to LCHuv colorspace.
1385  */
1386  assert(luma != (double *) NULL);
1387  assert(chroma != (double *) NULL);
1388  assert(hue != (double *) NULL);
1389  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1390  ConvertXYZToLCHuv(X,Y,Z,luma,chroma,hue);
1391}
1392
1393/*
1394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1395%                                                                             %
1396%                                                                             %
1397%                                                                             %
1398%   E x p a n d A f f i n e                                                   %
1399%                                                                             %
1400%                                                                             %
1401%                                                                             %
1402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1403%
1404%  ExpandAffine() computes the affine's expansion factor, i.e. the square root
1405%  of the factor by which the affine transform affects area. In an affine
1406%  transform composed of scaling, rotation, shearing, and translation, returns
1407%  the amount of scaling.
1408%
1409%  The format of the ExpandAffine method is:
1410%
1411%      double ExpandAffine(const AffineMatrix *affine)
1412%
1413%  A description of each parameter follows:
1414%
1415%    o expansion: ExpandAffine returns the affine's expansion factor.
1416%
1417%    o affine: A pointer the affine transform of type AffineMatrix.
1418%
1419*/
1420MagickExport double ExpandAffine(const AffineMatrix *affine)
1421{
1422  assert(affine != (const AffineMatrix *) NULL);
1423  return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
1424}
1425
1426/*
1427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1428%                                                                             %
1429%                                                                             %
1430%                                                                             %
1431%   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                         %
1432%                                                                             %
1433%                                                                             %
1434%                                                                             %
1435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436%
1437%  GenerateDifferentialNoise() generates differentual noise.
1438%
1439%  The format of the GenerateDifferentialNoise method is:
1440%
1441%      double GenerateDifferentialNoise(RandomInfo *random_info,
1442%        const Quantum pixel,const NoiseType noise_type,const double attenuate)
1443%
1444%  A description of each parameter follows:
1445%
1446%    o random_info: the random info.
1447%
1448%    o pixel: noise is relative to this pixel value.
1449%
1450%    o noise_type: the type of noise.
1451%
1452%    o attenuate:  attenuate the noise.
1453%
1454*/
1455MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
1456  const Quantum pixel,const NoiseType noise_type,const double attenuate)
1457{
1458#define SigmaUniform  (attenuate*0.015625)
1459#define SigmaGaussian  (attenuate*0.015625)
1460#define SigmaImpulse  (attenuate*0.1)
1461#define SigmaLaplacian (attenuate*0.0390625)
1462#define SigmaMultiplicativeGaussian  (attenuate*0.5)
1463#define SigmaPoisson  (attenuate*12.5)
1464#define SigmaRandom  (attenuate)
1465#define TauGaussian  (attenuate*0.078125)
1466
1467  double
1468    alpha,
1469    beta,
1470    noise,
1471    sigma;
1472
1473  alpha=GetPseudoRandomValue(random_info);
1474  switch (noise_type)
1475  {
1476    case UniformNoise:
1477    default:
1478    {
1479      noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
1480      break;
1481    }
1482    case GaussianNoise:
1483    {
1484      double
1485        gamma,
1486        tau;
1487
1488      if (fabs(alpha) < MagickEpsilon)
1489        alpha=1.0;
1490      beta=GetPseudoRandomValue(random_info);
1491      gamma=sqrt(-2.0*log(alpha));
1492      sigma=gamma*cos((double) (2.0*MagickPI*beta));
1493      tau=gamma*sin((double) (2.0*MagickPI*beta));
1494      noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
1495        QuantumRange*TauGaussian*tau);
1496      break;
1497    }
1498    case ImpulseNoise:
1499    {
1500      if (alpha < (SigmaImpulse/2.0))
1501        noise=0.0;
1502      else
1503        if (alpha >= (1.0-(SigmaImpulse/2.0)))
1504          noise=(double) QuantumRange;
1505        else
1506          noise=(double) pixel;
1507      break;
1508    }
1509    case LaplacianNoise:
1510    {
1511      if (alpha <= 0.5)
1512        {
1513          if (alpha <= MagickEpsilon)
1514            noise=(double) (pixel-QuantumRange);
1515          else
1516            noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
1517              0.5);
1518          break;
1519        }
1520      beta=1.0-alpha;
1521      if (beta <= (0.5*MagickEpsilon))
1522        noise=(double) (pixel+QuantumRange);
1523      else
1524        noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
1525      break;
1526    }
1527    case MultiplicativeGaussianNoise:
1528    {
1529      sigma=1.0;
1530      if (alpha > MagickEpsilon)
1531        sigma=sqrt(-2.0*log(alpha));
1532      beta=GetPseudoRandomValue(random_info);
1533      noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
1534        cos((double) (2.0*MagickPI*beta))/2.0);
1535      break;
1536    }
1537    case PoissonNoise:
1538    {
1539      double
1540        poisson;
1541
1542      register ssize_t
1543        i;
1544
1545      poisson=exp(-SigmaPoisson*QuantumScale*pixel);
1546      for (i=0; alpha > poisson; i++)
1547      {
1548        beta=GetPseudoRandomValue(random_info);
1549        alpha*=beta;
1550      }
1551      noise=(double) (QuantumRange*i/SigmaPoisson);
1552      break;
1553    }
1554    case RandomNoise:
1555    {
1556      noise=(double) (QuantumRange*SigmaRandom*alpha);
1557      break;
1558    }
1559  }
1560  return(noise);
1561}
1562
1563/*
1564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1565%                                                                             %
1566%                                                                             %
1567%                                                                             %
1568%   G e t O p t i m a l K e r n e l W i d t h                                 %
1569%                                                                             %
1570%                                                                             %
1571%                                                                             %
1572%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1573%
1574%  GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
1575%  filter.  Start with the minimum value of 3 pixels and walk out until we drop
1576%  below the threshold of one pixel numerical accuracy.
1577%
1578%  The format of the GetOptimalKernelWidth method is:
1579%
1580%      size_t GetOptimalKernelWidth(const double radius,
1581%        const double sigma)
1582%
1583%  A description of each parameter follows:
1584%
1585%    o width: GetOptimalKernelWidth returns the optimal width of a
1586%      convolution kernel.
1587%
1588%    o radius: the radius of the Gaussian, in pixels, not counting the center
1589%      pixel.
1590%
1591%    o sigma: the standard deviation of the Gaussian, in pixels.
1592%
1593*/
1594MagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
1595  const double sigma)
1596{
1597  double
1598    alpha,
1599    beta,
1600    gamma,
1601    normalize,
1602    value;
1603
1604  register ssize_t
1605    i;
1606
1607  size_t
1608    width;
1609
1610  ssize_t
1611    j;
1612
1613  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1614  if (radius > MagickEpsilon)
1615    return((size_t) (2.0*ceil(radius)+1.0));
1616  gamma=fabs(sigma);
1617  if (gamma <= MagickEpsilon)
1618    return(3UL);
1619  alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1620  beta=(double) PerceptibleReciprocal((double) MagickSQ2PI*gamma);
1621  for (width=5; ; )
1622  {
1623    normalize=0.0;
1624    j=(ssize_t) (width-1)/2;
1625    for (i=(-j); i <= j; i++)
1626      normalize+=exp(-((double) (i*i))*alpha)*beta;
1627    value=exp(-((double) (j*j))*alpha)*beta/normalize;
1628    if ((value < QuantumScale) || (value < MagickEpsilon))
1629      break;
1630    width+=2;
1631  }
1632  return((size_t) (width-2));
1633}
1634
1635MagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
1636  const double sigma)
1637{
1638  double
1639    alpha,
1640    beta,
1641    gamma,
1642    normalize,
1643    value;
1644
1645  size_t
1646    width;
1647
1648  ssize_t
1649    j,
1650    u,
1651    v;
1652
1653  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1654  if (radius > MagickEpsilon)
1655    return((size_t) (2.0*ceil(radius)+1.0));
1656  gamma=fabs(sigma);
1657  if (gamma <= MagickEpsilon)
1658    return(3UL);
1659  alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1660  beta=(double) PerceptibleReciprocal((double) Magick2PI*gamma*gamma);
1661  for (width=5; ; )
1662  {
1663    normalize=0.0;
1664    j=(ssize_t) (width-1)/2;
1665    for (v=(-j); v <= j; v++)
1666      for (u=(-j); u <= j; u++)
1667        normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
1668    value=exp(-((double) (j*j))*alpha)*beta/normalize;
1669    if ((value < QuantumScale) || (value < MagickEpsilon))
1670      break;
1671    width+=2;
1672  }
1673  return((size_t) (width-2));
1674}
1675
1676MagickPrivate size_t  GetOptimalKernelWidth(const double radius,
1677  const double sigma)
1678{
1679  return(GetOptimalKernelWidth1D(radius,sigma));
1680}
1681