gem.c revision 89106f86b28a27c7b7d9b07e13db58516ab8d01f
13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              GGGG  EEEEE  M   M                             %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                             G      E      MM MM                             %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                             G GG   EEE    M M M                             %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                             G   G  E      M   M                             %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              GGGG  EEEEE  M   M                             %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                    Graphic Gems - Graphic Support Methods                   %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                               Software Design                               %
163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 John Cristy                                 %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 August 1996                                 %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2045ef08fd6a09813e4a8f5ddadf85ba9e0ec2cdc7cristy%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color-private.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/draw.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/gem.h"
47d1dd6e4fefa0810b9893e6ac9418f79c97c1b39acristy#include "MagickCore/gem-private.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h"
494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/log.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
5335f1530f0591e7380a976a606080774c28bc4da2cristy#include "MagickCore/pixel-private.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/random_.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resize.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/transform.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/signature-private.h"
603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
66722fc0cce634eb07588336accc3bb52979738a5ccristy%   C o n v e r t H C L T o R G B                                             %
67722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
68722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
69722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
70722fc0cce634eb07588336accc3bb52979738a5ccristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71722fc0cce634eb07588336accc3bb52979738a5ccristy%
72722fc0cce634eb07588336accc3bb52979738a5ccristy%  ConvertHCLToRGB() transforms a (hue, chroma, luma) to a (red, green,
73722fc0cce634eb07588336accc3bb52979738a5ccristy%  blue) triple.
74722fc0cce634eb07588336accc3bb52979738a5ccristy%
75722fc0cce634eb07588336accc3bb52979738a5ccristy%  The format of the ConvertHCLToRGBImage method is:
76722fc0cce634eb07588336accc3bb52979738a5ccristy%
77722fc0cce634eb07588336accc3bb52979738a5ccristy%      void ConvertHCLToRGB(const double hue,const double chroma,
78722fc0cce634eb07588336accc3bb52979738a5ccristy%        const double luma,double *red,double *green,double *blue)
79722fc0cce634eb07588336accc3bb52979738a5ccristy%
80722fc0cce634eb07588336accc3bb52979738a5ccristy%  A description of each parameter follows:
81722fc0cce634eb07588336accc3bb52979738a5ccristy%
829e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%    o hue, chroma, luma: A double value representing a component of the
839e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%      HCL color space.
84722fc0cce634eb07588336accc3bb52979738a5ccristy%
85722fc0cce634eb07588336accc3bb52979738a5ccristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
86722fc0cce634eb07588336accc3bb52979738a5ccristy%
87722fc0cce634eb07588336accc3bb52979738a5ccristy*/
88722fc0cce634eb07588336accc3bb52979738a5ccristyMagickPrivate void ConvertHCLToRGB(const double hue,const double chroma,
89722fc0cce634eb07588336accc3bb52979738a5ccristy  const double luma,double *red,double *green,double *blue)
90722fc0cce634eb07588336accc3bb52979738a5ccristy{
91722fc0cce634eb07588336accc3bb52979738a5ccristy  double
925756d82f940337296549c59f25ff7f96eff132b1cristy    b,
935756d82f940337296549c59f25ff7f96eff132b1cristy    c,
945756d82f940337296549c59f25ff7f96eff132b1cristy    g,
955756d82f940337296549c59f25ff7f96eff132b1cristy    h,
965756d82f940337296549c59f25ff7f96eff132b1cristy    m,
975756d82f940337296549c59f25ff7f96eff132b1cristy    r,
989e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    x;
999e2436a78bdabef900e018dc77c0cc497bf6fbafcristy
1009e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  /*
1019e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    Convert HCL to RGB colorspace.
1029e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  */
1039e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  assert(red != (double *) NULL);
1049e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  assert(green != (double *) NULL);
1059e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  assert(blue != (double *) NULL);
1069e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  h=6.0*hue;
1079e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  c=chroma;
1089e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  x=c*(1.0-fabs(fmod(h,2.0)-1.0));
1099e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  r=0.0;
1109e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  g=0.0;
1119e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  b=0.0;
1129e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  if ((0.0 <= h) && (h < 1.0))
1139e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    {
1149e2436a78bdabef900e018dc77c0cc497bf6fbafcristy      r=c;
1159e2436a78bdabef900e018dc77c0cc497bf6fbafcristy      g=x;
1169e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    }
1179e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  else
1189e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    if ((1.0 <= h) && (h < 2.0))
1199e2436a78bdabef900e018dc77c0cc497bf6fbafcristy      {
1209e2436a78bdabef900e018dc77c0cc497bf6fbafcristy        r=x;
1219e2436a78bdabef900e018dc77c0cc497bf6fbafcristy        g=c;
1229e2436a78bdabef900e018dc77c0cc497bf6fbafcristy      }
1239e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    else
1249e2436a78bdabef900e018dc77c0cc497bf6fbafcristy      if ((2.0 <= h) && (h < 3.0))
1259e2436a78bdabef900e018dc77c0cc497bf6fbafcristy        {
1269e2436a78bdabef900e018dc77c0cc497bf6fbafcristy          g=c;
1279e2436a78bdabef900e018dc77c0cc497bf6fbafcristy          b=x;
1289e2436a78bdabef900e018dc77c0cc497bf6fbafcristy        }
1299e2436a78bdabef900e018dc77c0cc497bf6fbafcristy      else
1309e2436a78bdabef900e018dc77c0cc497bf6fbafcristy        if ((3.0 <= h) && (h < 4.0))
1319e2436a78bdabef900e018dc77c0cc497bf6fbafcristy          {
1329e2436a78bdabef900e018dc77c0cc497bf6fbafcristy            g=x;
1339e2436a78bdabef900e018dc77c0cc497bf6fbafcristy            b=c;
1349e2436a78bdabef900e018dc77c0cc497bf6fbafcristy          }
1359e2436a78bdabef900e018dc77c0cc497bf6fbafcristy        else
1369e2436a78bdabef900e018dc77c0cc497bf6fbafcristy          if ((4.0 <= h) && (h < 5.0))
1379e2436a78bdabef900e018dc77c0cc497bf6fbafcristy            {
1389e2436a78bdabef900e018dc77c0cc497bf6fbafcristy              r=x;
1399e2436a78bdabef900e018dc77c0cc497bf6fbafcristy              b=c;
1409e2436a78bdabef900e018dc77c0cc497bf6fbafcristy            }
1419e2436a78bdabef900e018dc77c0cc497bf6fbafcristy          else
1429e2436a78bdabef900e018dc77c0cc497bf6fbafcristy            if ((5.0 <= h) && (h < 6.0))
1439e2436a78bdabef900e018dc77c0cc497bf6fbafcristy              {
1449e2436a78bdabef900e018dc77c0cc497bf6fbafcristy                r=c;
1459e2436a78bdabef900e018dc77c0cc497bf6fbafcristy                b=x;
1469e2436a78bdabef900e018dc77c0cc497bf6fbafcristy              }
1479e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  m=luma-(0.298839*r+0.586811*g+0.114350*b);
1489e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  *red=QuantumRange*(r+m);
1499e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  *green=QuantumRange*(g+m);
1509e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  *blue=QuantumRange*(b+m);
1519e2436a78bdabef900e018dc77c0cc497bf6fbafcristy}
1529e2436a78bdabef900e018dc77c0cc497bf6fbafcristy
1539e2436a78bdabef900e018dc77c0cc497bf6fbafcristy/*
1549e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1559e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
1569e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
1579e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
1589e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%   C o n v e r t H C L p T o R G B                                           %
1599e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
1609e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
1619e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
1629e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1639e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
1649e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%  ConvertHCLpToRGB() transforms a (hue, chroma, luma) to a (red, green,
1659e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%  blue) triple.  Since HCL colorspace is wider than RGB, we instead choose a
1669e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%  saturation strategy to project it on the RGB cube.
1679e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
1689e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%  The format of the ConvertHCLpToRGBImage method is:
1699e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
1709e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%      void ConvertHCLpToRGB(const double hue,const double chroma,
1719e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%        const double luma,double *red,double *green,double *blue)
1729e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
1739e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%  A description of each parameter follows:
1749e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
1759e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%    o hue, chroma, luma: A double value representing a componenet of the
1769e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%      HCLp color space.
1779e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
1789e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
1799e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
1809e2436a78bdabef900e018dc77c0cc497bf6fbafcristy*/
1819e2436a78bdabef900e018dc77c0cc497bf6fbafcristyMagickPrivate void ConvertHCLpToRGB(const double hue,const double chroma,
1829e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  const double luma,double *red,double *green,double *blue)
1839e2436a78bdabef900e018dc77c0cc497bf6fbafcristy{
1849e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  double
1859e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    b,
1869e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    c,
1879e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    g,
1889e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    h,
1899e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    m,
1909e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    r,
191c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy    x,
192c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy    z;
193722fc0cce634eb07588336accc3bb52979738a5ccristy
194722fc0cce634eb07588336accc3bb52979738a5ccristy  /*
1959e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    Convert HCLp to RGB colorspace.
196722fc0cce634eb07588336accc3bb52979738a5ccristy  */
197722fc0cce634eb07588336accc3bb52979738a5ccristy  assert(red != (double *) NULL);
198722fc0cce634eb07588336accc3bb52979738a5ccristy  assert(green != (double *) NULL);
199722fc0cce634eb07588336accc3bb52979738a5ccristy  assert(blue != (double *) NULL);
2005756d82f940337296549c59f25ff7f96eff132b1cristy  h=6.0*hue;
2015756d82f940337296549c59f25ff7f96eff132b1cristy  c=chroma;
2025756d82f940337296549c59f25ff7f96eff132b1cristy  x=c*(1.0-fabs(fmod(h,2.0)-1.0));
2035756d82f940337296549c59f25ff7f96eff132b1cristy  r=0.0;
2045756d82f940337296549c59f25ff7f96eff132b1cristy  g=0.0;
2055756d82f940337296549c59f25ff7f96eff132b1cristy  b=0.0;
2065756d82f940337296549c59f25ff7f96eff132b1cristy  if ((0.0 <= h) && (h < 1.0))
2075756d82f940337296549c59f25ff7f96eff132b1cristy    {
2085756d82f940337296549c59f25ff7f96eff132b1cristy      r=c;
2095756d82f940337296549c59f25ff7f96eff132b1cristy      g=x;
2105756d82f940337296549c59f25ff7f96eff132b1cristy    }
2115756d82f940337296549c59f25ff7f96eff132b1cristy  else
2125756d82f940337296549c59f25ff7f96eff132b1cristy    if ((1.0 <= h) && (h < 2.0))
2135756d82f940337296549c59f25ff7f96eff132b1cristy      {
2145756d82f940337296549c59f25ff7f96eff132b1cristy        r=x;
2155756d82f940337296549c59f25ff7f96eff132b1cristy        g=c;
2165756d82f940337296549c59f25ff7f96eff132b1cristy      }
2175756d82f940337296549c59f25ff7f96eff132b1cristy    else
2185756d82f940337296549c59f25ff7f96eff132b1cristy      if ((2.0 <= h) && (h < 3.0))
2195756d82f940337296549c59f25ff7f96eff132b1cristy        {
2205756d82f940337296549c59f25ff7f96eff132b1cristy          g=c;
2215756d82f940337296549c59f25ff7f96eff132b1cristy          b=x;
2225756d82f940337296549c59f25ff7f96eff132b1cristy        }
2235756d82f940337296549c59f25ff7f96eff132b1cristy      else
2245756d82f940337296549c59f25ff7f96eff132b1cristy        if ((3.0 <= h) && (h < 4.0))
2255756d82f940337296549c59f25ff7f96eff132b1cristy          {
2265756d82f940337296549c59f25ff7f96eff132b1cristy            g=x;
2275756d82f940337296549c59f25ff7f96eff132b1cristy            b=c;
2285756d82f940337296549c59f25ff7f96eff132b1cristy          }
2295756d82f940337296549c59f25ff7f96eff132b1cristy        else
2305756d82f940337296549c59f25ff7f96eff132b1cristy          if ((4.0 <= h) && (h < 5.0))
2315756d82f940337296549c59f25ff7f96eff132b1cristy            {
2325756d82f940337296549c59f25ff7f96eff132b1cristy              r=x;
2335756d82f940337296549c59f25ff7f96eff132b1cristy              b=c;
2345756d82f940337296549c59f25ff7f96eff132b1cristy            }
2355756d82f940337296549c59f25ff7f96eff132b1cristy          else
2365756d82f940337296549c59f25ff7f96eff132b1cristy            if ((5.0 <= h) && (h < 6.0))
2375756d82f940337296549c59f25ff7f96eff132b1cristy              {
2385756d82f940337296549c59f25ff7f96eff132b1cristy                r=c;
2395756d82f940337296549c59f25ff7f96eff132b1cristy                b=x;
2405756d82f940337296549c59f25ff7f96eff132b1cristy              }
2419e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  m=luma-(0.298839*r+0.586811*g+0.114350*b);
242c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy  z=1.0;
243c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy  if (m < 0.0)
244c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy    {
245c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy      z=luma/(luma-m);
246c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy      m=0.0;
247c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy    }
248c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy  else
249c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy    if (m+c > 1.0)
250c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy      {
251c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy        z=(1.0-luma)/(m+c-luma);
252c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy        m=1.0-z*c;
253c41e5fa39a01f3b6e5d26cc7b32afe5556038f21cristy      }
254a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  *red=QuantumRange*(z*r+m);
255a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  *green=QuantumRange*(z*g+m);
256a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  *blue=QuantumRange*(z*b+m);
257722fc0cce634eb07588336accc3bb52979738a5ccristy}
258722fc0cce634eb07588336accc3bb52979738a5ccristy
259722fc0cce634eb07588336accc3bb52979738a5ccristy/*
260722fc0cce634eb07588336accc3bb52979738a5ccristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
262722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
263722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
2640a39a5c567fca70403bc431d18890e89fc253eefcristy%   C o n v e r t H S B T o R G B                                             %
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2700a39a5c567fca70403bc431d18890e89fc253eefcristy%  ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  green, blue) triple.
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2730a39a5c567fca70403bc431d18890e89fc253eefcristy%  The format of the ConvertHSBToRGBImage method is:
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2750a39a5c567fca70403bc431d18890e89fc253eefcristy%      void ConvertHSBToRGB(const double hue,const double saturation,
2763094b7f3243820cc5559d370412a9d406d074348cristy%        const double brightness,double *red,double *green,double *blue)
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, saturation, brightness: A double value representing a
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HSB color space.
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
2860a39a5c567fca70403bc431d18890e89fc253eefcristyMagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
2873094b7f3243820cc5559d370412a9d406d074348cristy  const double brightness,double *red,double *green,double *blue)
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
289caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  double
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    f,
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    h,
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p,
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q,
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    t;
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert HSB to RGB colorspace.
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2993094b7f3243820cc5559d370412a9d406d074348cristy  assert(red != (double *) NULL);
3003094b7f3243820cc5559d370412a9d406d074348cristy  assert(green != (double *) NULL);
3013094b7f3243820cc5559d370412a9d406d074348cristy  assert(blue != (double *) NULL);
30298a65d5565159ce59b24013f0e3d148428af50d6cristy  if (saturation == 0.0)
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
304caf4580de0f80e561a5fcb59c89f2f8adac91006cristy      *red=QuantumRange*brightness;
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *green=(*red);
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *blue=(*red);
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
30998a65d5565159ce59b24013f0e3d148428af50d6cristy  h=6.0*(hue-floor(hue));
31098a65d5565159ce59b24013f0e3d148428af50d6cristy  f=h-floor((double) h);
31198a65d5565159ce59b24013f0e3d148428af50d6cristy  p=brightness*(1.0-saturation);
31298a65d5565159ce59b24013f0e3d148428af50d6cristy  q=brightness*(1.0-saturation*f);
31398a65d5565159ce59b24013f0e3d148428af50d6cristy  t=brightness*(1.0-(saturation*(1.0-f)));
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch ((int) h)
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 0:
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default:
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
3190a39a5c567fca70403bc431d18890e89fc253eefcristy      *red=QuantumRange*brightness;
3200a39a5c567fca70403bc431d18890e89fc253eefcristy      *green=QuantumRange*t;
3210a39a5c567fca70403bc431d18890e89fc253eefcristy      *blue=QuantumRange*p;
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 1:
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
3260a39a5c567fca70403bc431d18890e89fc253eefcristy      *red=QuantumRange*q;
3270a39a5c567fca70403bc431d18890e89fc253eefcristy      *green=QuantumRange*brightness;
3280a39a5c567fca70403bc431d18890e89fc253eefcristy      *blue=QuantumRange*p;
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 2:
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
3330a39a5c567fca70403bc431d18890e89fc253eefcristy      *red=QuantumRange*p;
3340a39a5c567fca70403bc431d18890e89fc253eefcristy      *green=QuantumRange*brightness;
3350a39a5c567fca70403bc431d18890e89fc253eefcristy      *blue=QuantumRange*t;
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 3:
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
3400a39a5c567fca70403bc431d18890e89fc253eefcristy      *red=QuantumRange*p;
3410a39a5c567fca70403bc431d18890e89fc253eefcristy      *green=QuantumRange*q;
3420a39a5c567fca70403bc431d18890e89fc253eefcristy      *blue=QuantumRange*brightness;
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 4:
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
3470a39a5c567fca70403bc431d18890e89fc253eefcristy      *red=QuantumRange*t;
3480a39a5c567fca70403bc431d18890e89fc253eefcristy      *green=QuantumRange*p;
3490a39a5c567fca70403bc431d18890e89fc253eefcristy      *blue=QuantumRange*brightness;
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 5:
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
3540a39a5c567fca70403bc431d18890e89fc253eefcristy      *red=QuantumRange*brightness;
3550a39a5c567fca70403bc431d18890e89fc253eefcristy      *green=QuantumRange*p;
3560a39a5c567fca70403bc431d18890e89fc253eefcristy      *blue=QuantumRange*q;
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
367af64eb219382bdf6243c4b8dc589268b8934304acristy%   C o n v e r t H S I T o R G B                                             %
368af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
369af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
370af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
371af64eb219382bdf6243c4b8dc589268b8934304acristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372af64eb219382bdf6243c4b8dc589268b8934304acristy%
373af64eb219382bdf6243c4b8dc589268b8934304acristy%  ConvertHSIToRGB() transforms a (hue, saturation, intensity) to a (red,
374af64eb219382bdf6243c4b8dc589268b8934304acristy%  green, blue) triple.
375af64eb219382bdf6243c4b8dc589268b8934304acristy%
376af64eb219382bdf6243c4b8dc589268b8934304acristy%  The format of the ConvertHSIToRGBImage method is:
377af64eb219382bdf6243c4b8dc589268b8934304acristy%
378af64eb219382bdf6243c4b8dc589268b8934304acristy%      void ConvertHSIToRGB(const double hue,const double saturation,
379af64eb219382bdf6243c4b8dc589268b8934304acristy%        const double intensity,double *red,double *green,double *blue)
380af64eb219382bdf6243c4b8dc589268b8934304acristy%
381af64eb219382bdf6243c4b8dc589268b8934304acristy%  A description of each parameter follows:
382af64eb219382bdf6243c4b8dc589268b8934304acristy%
383af64eb219382bdf6243c4b8dc589268b8934304acristy%    o hue, saturation, intensity: A double value representing a
384af64eb219382bdf6243c4b8dc589268b8934304acristy%      component of the HSI color space.
385af64eb219382bdf6243c4b8dc589268b8934304acristy%
386af64eb219382bdf6243c4b8dc589268b8934304acristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
387af64eb219382bdf6243c4b8dc589268b8934304acristy%
388af64eb219382bdf6243c4b8dc589268b8934304acristy*/
389af64eb219382bdf6243c4b8dc589268b8934304acristyMagickPrivate void ConvertHSIToRGB(const double hue,const double saturation,
390af64eb219382bdf6243c4b8dc589268b8934304acristy  const double intensity,double *red,double *green,double *blue)
391af64eb219382bdf6243c4b8dc589268b8934304acristy{
392af64eb219382bdf6243c4b8dc589268b8934304acristy  double
393af64eb219382bdf6243c4b8dc589268b8934304acristy    h;
394af64eb219382bdf6243c4b8dc589268b8934304acristy
395af64eb219382bdf6243c4b8dc589268b8934304acristy  /*
396af64eb219382bdf6243c4b8dc589268b8934304acristy    Convert HSI to RGB colorspace.
397af64eb219382bdf6243c4b8dc589268b8934304acristy  */
398af64eb219382bdf6243c4b8dc589268b8934304acristy  assert(red != (double *) NULL);
399af64eb219382bdf6243c4b8dc589268b8934304acristy  assert(green != (double *) NULL);
400af64eb219382bdf6243c4b8dc589268b8934304acristy  assert(blue != (double *) NULL);
401af64eb219382bdf6243c4b8dc589268b8934304acristy  h=360.0*hue;
402af64eb219382bdf6243c4b8dc589268b8934304acristy  h-=360.0*floor(h/360.0);
403af64eb219382bdf6243c4b8dc589268b8934304acristy  if (h < 120.0)
404af64eb219382bdf6243c4b8dc589268b8934304acristy    {
405af64eb219382bdf6243c4b8dc589268b8934304acristy      *blue=intensity*(1.0-saturation);
406af64eb219382bdf6243c4b8dc589268b8934304acristy      *red=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
407af64eb219382bdf6243c4b8dc589268b8934304acristy        (MagickPI/180.0)));
408af64eb219382bdf6243c4b8dc589268b8934304acristy      *green=3.0*intensity-*red-*blue;
409af64eb219382bdf6243c4b8dc589268b8934304acristy    }
410af64eb219382bdf6243c4b8dc589268b8934304acristy  else
411af64eb219382bdf6243c4b8dc589268b8934304acristy    if (h < 240.0)
412af64eb219382bdf6243c4b8dc589268b8934304acristy      {
413af64eb219382bdf6243c4b8dc589268b8934304acristy        h-=120.0;
414af64eb219382bdf6243c4b8dc589268b8934304acristy        *red=intensity*(1.0-saturation);
415af64eb219382bdf6243c4b8dc589268b8934304acristy        *green=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
416af64eb219382bdf6243c4b8dc589268b8934304acristy          (MagickPI/180.0)));
417af64eb219382bdf6243c4b8dc589268b8934304acristy        *blue=3.0*intensity-*red-*green;
418af64eb219382bdf6243c4b8dc589268b8934304acristy      }
419af64eb219382bdf6243c4b8dc589268b8934304acristy    else
420af64eb219382bdf6243c4b8dc589268b8934304acristy      {
421af64eb219382bdf6243c4b8dc589268b8934304acristy        h-=240.0;
422af64eb219382bdf6243c4b8dc589268b8934304acristy        *green=intensity*(1.0-saturation);
423af64eb219382bdf6243c4b8dc589268b8934304acristy        *blue=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
424af64eb219382bdf6243c4b8dc589268b8934304acristy          (MagickPI/180.0)));
425af64eb219382bdf6243c4b8dc589268b8934304acristy        *red=3.0*intensity-*green-*blue;
426af64eb219382bdf6243c4b8dc589268b8934304acristy      }
427af64eb219382bdf6243c4b8dc589268b8934304acristy  *red*=QuantumRange;
428af64eb219382bdf6243c4b8dc589268b8934304acristy  *green*=QuantumRange;
429af64eb219382bdf6243c4b8dc589268b8934304acristy  *blue*=QuantumRange;
430af64eb219382bdf6243c4b8dc589268b8934304acristy}
431af64eb219382bdf6243c4b8dc589268b8934304acristy
432af64eb219382bdf6243c4b8dc589268b8934304acristy/*
433af64eb219382bdf6243c4b8dc589268b8934304acristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
435af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
436af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
4370a39a5c567fca70403bc431d18890e89fc253eefcristy%   C o n v e r t H S L T o R G B                                             %
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4430a39a5c567fca70403bc431d18890e89fc253eefcristy%  ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  green, blue) triple.
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4460a39a5c567fca70403bc431d18890e89fc253eefcristy%  The format of the ConvertHSLToRGBImage method is:
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4480a39a5c567fca70403bc431d18890e89fc253eefcristy%      void ConvertHSLToRGB(const double hue,const double saturation,
4493094b7f3243820cc5559d370412a9d406d074348cristy%        const double lightness,double *red,double *green,double *blue)
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, saturation, lightness: A double value representing a
4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HSL color space.
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
4590a39a5c567fca70403bc431d18890e89fc253eefcristyMagickExport void ConvertHSLToRGB(const double hue,const double saturation,
4603094b7f3243820cc5559d370412a9d406d074348cristy  const double lightness,double *red,double *green,double *blue)
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
462caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  double
463a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    c,
464a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    h,
465a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    min,
466a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    x;
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert HSL to RGB colorspace.
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4713094b7f3243820cc5559d370412a9d406d074348cristy  assert(red != (double *) NULL);
4723094b7f3243820cc5559d370412a9d406d074348cristy  assert(green != (double *) NULL);
4733094b7f3243820cc5559d370412a9d406d074348cristy  assert(blue != (double *) NULL);
474a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  h=hue*360.0;
475a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  if (lightness <= 0.5)
476a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    c=2.0*lightness*saturation;
477a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  else
478a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    c=(2.0-2.0*lightness)*saturation;
479a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  min=lightness-0.5*c;
480a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  h-=360.0*floor(h/360.0);
481a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  h/=60.0;
482a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
483a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  switch ((int) floor(h))
484a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  {
485a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    case 0:
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
487a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *red=QuantumRange*(min+c);
488a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *green=QuantumRange*(min+x);
489a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *blue=QuantumRange*min;
490a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      break;
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
492a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    case 1:
493a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    {
494a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *red=QuantumRange*(min+x);
495a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *green=QuantumRange*(min+c);
496a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *blue=QuantumRange*min;
497a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      break;
498a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    }
499a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    case 2:
500a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    {
501a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *red=QuantumRange*min;
502a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *green=QuantumRange*(min+c);
503a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *blue=QuantumRange*(min+x);
504a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      break;
505a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    }
506a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    case 3:
507a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    {
508a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *red=QuantumRange*min;
509a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *green=QuantumRange*(min+x);
510a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *blue=QuantumRange*(min+c);
511a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      break;
512a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    }
513a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    case 4:
514a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    {
515a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *red=QuantumRange*(min+x);
516a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *green=QuantumRange*min;
517a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *blue=QuantumRange*(min+c);
518a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      break;
519a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    }
520a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    case 5:
521a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    {
522a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *red=QuantumRange*(min+c);
523a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *green=QuantumRange*min;
524a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *blue=QuantumRange*(min+x);
525a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      break;
526a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    }
527a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    default:
528a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    {
529a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *red=0.0;
530a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *green=0.0;
531a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *blue=0.0;
532a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    }
533a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  }
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
541246c3135a833b00ed2e42448c85cc2ea1269b177cristy%   C o n v e r t H S V T o R G B                                             %
542246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
543246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
544246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
545246c3135a833b00ed2e42448c85cc2ea1269b177cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
547246c3135a833b00ed2e42448c85cc2ea1269b177cristy%  ConvertHSVToRGB() transforms a (hue, saturation, value) to a (red,
548246c3135a833b00ed2e42448c85cc2ea1269b177cristy%  green, blue) triple.
549246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
550246c3135a833b00ed2e42448c85cc2ea1269b177cristy%  The format of the ConvertHSVToRGBImage method is:
551246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
552246c3135a833b00ed2e42448c85cc2ea1269b177cristy%      void ConvertHSVToRGB(const double hue,const double saturation,
553246c3135a833b00ed2e42448c85cc2ea1269b177cristy%        const double value,double *red,double *green,double *blue)
554246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
555246c3135a833b00ed2e42448c85cc2ea1269b177cristy%  A description of each parameter follows:
556246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
557246c3135a833b00ed2e42448c85cc2ea1269b177cristy%    o hue, saturation, value: A double value representing a
558246c3135a833b00ed2e42448c85cc2ea1269b177cristy%      component of the HSV color space.
559246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
560246c3135a833b00ed2e42448c85cc2ea1269b177cristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
561246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
562246c3135a833b00ed2e42448c85cc2ea1269b177cristy*/
563246c3135a833b00ed2e42448c85cc2ea1269b177cristyMagickPrivate void ConvertHSVToRGB(const double hue,const double saturation,
564246c3135a833b00ed2e42448c85cc2ea1269b177cristy  const double value,double *red,double *green,double *blue)
565246c3135a833b00ed2e42448c85cc2ea1269b177cristy{
566246c3135a833b00ed2e42448c85cc2ea1269b177cristy  double
567246c3135a833b00ed2e42448c85cc2ea1269b177cristy    c,
568246c3135a833b00ed2e42448c85cc2ea1269b177cristy    h,
569246c3135a833b00ed2e42448c85cc2ea1269b177cristy    min,
570246c3135a833b00ed2e42448c85cc2ea1269b177cristy    x;
571246c3135a833b00ed2e42448c85cc2ea1269b177cristy
572246c3135a833b00ed2e42448c85cc2ea1269b177cristy  /*
573246c3135a833b00ed2e42448c85cc2ea1269b177cristy    Convert HSV to RGB colorspace.
574246c3135a833b00ed2e42448c85cc2ea1269b177cristy  */
575246c3135a833b00ed2e42448c85cc2ea1269b177cristy  assert(red != (double *) NULL);
576246c3135a833b00ed2e42448c85cc2ea1269b177cristy  assert(green != (double *) NULL);
577246c3135a833b00ed2e42448c85cc2ea1269b177cristy  assert(blue != (double *) NULL);
578246c3135a833b00ed2e42448c85cc2ea1269b177cristy  h=hue*360.0;
579246c3135a833b00ed2e42448c85cc2ea1269b177cristy  c=value*saturation;
580246c3135a833b00ed2e42448c85cc2ea1269b177cristy  min=value-c;
581246c3135a833b00ed2e42448c85cc2ea1269b177cristy  h-=360.0*floor(h/360.0);
582246c3135a833b00ed2e42448c85cc2ea1269b177cristy  h/=60.0;
583246c3135a833b00ed2e42448c85cc2ea1269b177cristy  x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
584246c3135a833b00ed2e42448c85cc2ea1269b177cristy  switch ((int) floor(h))
585246c3135a833b00ed2e42448c85cc2ea1269b177cristy  {
586246c3135a833b00ed2e42448c85cc2ea1269b177cristy    case 0:
587246c3135a833b00ed2e42448c85cc2ea1269b177cristy    {
588246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *red=QuantumRange*(min+c);
589246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *green=QuantumRange*(min+x);
590246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *blue=QuantumRange*min;
591246c3135a833b00ed2e42448c85cc2ea1269b177cristy      break;
592246c3135a833b00ed2e42448c85cc2ea1269b177cristy    }
593246c3135a833b00ed2e42448c85cc2ea1269b177cristy    case 1:
594246c3135a833b00ed2e42448c85cc2ea1269b177cristy    {
595246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *red=QuantumRange*(min+x);
596246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *green=QuantumRange*(min+c);
597246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *blue=QuantumRange*min;
598246c3135a833b00ed2e42448c85cc2ea1269b177cristy      break;
599246c3135a833b00ed2e42448c85cc2ea1269b177cristy    }
600246c3135a833b00ed2e42448c85cc2ea1269b177cristy    case 2:
601246c3135a833b00ed2e42448c85cc2ea1269b177cristy    {
602246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *red=QuantumRange*min;
603246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *green=QuantumRange*(min+c);
604246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *blue=QuantumRange*(min+x);
605246c3135a833b00ed2e42448c85cc2ea1269b177cristy      break;
606246c3135a833b00ed2e42448c85cc2ea1269b177cristy    }
607246c3135a833b00ed2e42448c85cc2ea1269b177cristy    case 3:
608246c3135a833b00ed2e42448c85cc2ea1269b177cristy    {
609246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *red=QuantumRange*min;
610246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *green=QuantumRange*(min+x);
611246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *blue=QuantumRange*(min+c);
612246c3135a833b00ed2e42448c85cc2ea1269b177cristy      break;
613246c3135a833b00ed2e42448c85cc2ea1269b177cristy    }
614246c3135a833b00ed2e42448c85cc2ea1269b177cristy    case 4:
615246c3135a833b00ed2e42448c85cc2ea1269b177cristy    {
616246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *red=QuantumRange*(min+x);
617246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *green=QuantumRange*min;
618246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *blue=QuantumRange*(min+c);
619246c3135a833b00ed2e42448c85cc2ea1269b177cristy      break;
620246c3135a833b00ed2e42448c85cc2ea1269b177cristy    }
621246c3135a833b00ed2e42448c85cc2ea1269b177cristy    case 5:
622246c3135a833b00ed2e42448c85cc2ea1269b177cristy    {
623246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *red=QuantumRange*(min+c);
624246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *green=QuantumRange*min;
625246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *blue=QuantumRange*(min+x);
626246c3135a833b00ed2e42448c85cc2ea1269b177cristy      break;
627246c3135a833b00ed2e42448c85cc2ea1269b177cristy    }
628246c3135a833b00ed2e42448c85cc2ea1269b177cristy    default:
629246c3135a833b00ed2e42448c85cc2ea1269b177cristy    {
630246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *red=0.0;
631246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *green=0.0;
632246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *blue=0.0;
633246c3135a833b00ed2e42448c85cc2ea1269b177cristy    }
634246c3135a833b00ed2e42448c85cc2ea1269b177cristy  }
635246c3135a833b00ed2e42448c85cc2ea1269b177cristy}
636246c3135a833b00ed2e42448c85cc2ea1269b177cristy
637246c3135a833b00ed2e42448c85cc2ea1269b177cristy/*
638246c3135a833b00ed2e42448c85cc2ea1269b177cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
640246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
641246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
6420a39a5c567fca70403bc431d18890e89fc253eefcristy%   C o n v e r t H W B T o R G B                                             %
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6480a39a5c567fca70403bc431d18890e89fc253eefcristy%  ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  blue) triple.
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6510a39a5c567fca70403bc431d18890e89fc253eefcristy%  The format of the ConvertHWBToRGBImage method is:
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6530a39a5c567fca70403bc431d18890e89fc253eefcristy%      void ConvertHWBToRGB(const double hue,const double whiteness,
6543094b7f3243820cc5559d370412a9d406d074348cristy%        const double blackness,double *red,double *green,double *blue)
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, whiteness, blackness: A double value representing a
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HWB color space.
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
6640a39a5c567fca70403bc431d18890e89fc253eefcristyMagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
6653094b7f3243820cc5559d370412a9d406d074348cristy  const double blackness,double *red,double *green,double *blue)
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
667caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  double
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    b,
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    f,
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    g,
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    n,
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r,
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    v;
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
675bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert HWB to RGB colorspace.
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6813094b7f3243820cc5559d370412a9d406d074348cristy  assert(red != (double *) NULL);
6823094b7f3243820cc5559d370412a9d406d074348cristy  assert(green != (double *) NULL);
6833094b7f3243820cc5559d370412a9d406d074348cristy  assert(blue != (double *) NULL);
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  v=1.0-blackness;
685af10b112a3fe7f0ca502f9cf0f8de2873ff7b97ecristy  if (hue == -1.0)
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6870a39a5c567fca70403bc431d18890e89fc253eefcristy      *red=QuantumRange*v;
6880a39a5c567fca70403bc431d18890e89fc253eefcristy      *green=QuantumRange*v;
6890a39a5c567fca70403bc431d18890e89fc253eefcristy      *blue=QuantumRange*v;
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
692bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  i=(ssize_t) floor(6.0*hue);
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  f=6.0*hue-i;
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((i & 0x01) != 0)
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    f=1.0-f;
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  n=whiteness+f*(v-whiteness);  /* linear interpolation */
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch (i)
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default:
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 6:
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 0: r=v; g=n; b=whiteness; break;
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 1: r=n; g=v; b=whiteness; break;
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 2: r=whiteness; g=v; b=n; break;
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 3: r=whiteness; g=n; b=v; break;
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 4: r=n; g=whiteness; b=v; break;
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 5: r=v; g=whiteness; b=n; break;
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7080a39a5c567fca70403bc431d18890e89fc253eefcristy  *red=QuantumRange*r;
7090a39a5c567fca70403bc431d18890e89fc253eefcristy  *green=QuantumRange*g;
7100a39a5c567fca70403bc431d18890e89fc253eefcristy  *blue=QuantumRange*b;
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
717722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
718df42b17380e9d59e0ef874a62e553c9390157b7dcristy%   C o n v e r t L C H a b T o R G B                                         %
719b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
720b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
721b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
722b285095a81498ca0f0b24a0591e02aa599065b12cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723b285095a81498ca0f0b24a0591e02aa599065b12cristy%
724df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  ConvertLCHabToRGB() transforms a (luma, chroma, hue) to a (red, green,
725b285095a81498ca0f0b24a0591e02aa599065b12cristy%  blue) triple.
726b285095a81498ca0f0b24a0591e02aa599065b12cristy%
727df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  The format of the ConvertLCHabToRGBImage method is:
728b285095a81498ca0f0b24a0591e02aa599065b12cristy%
729df42b17380e9d59e0ef874a62e553c9390157b7dcristy%      void ConvertLCHabToRGB(const double luma,const double chroma,
730b285095a81498ca0f0b24a0591e02aa599065b12cristy%        const double hue,double *red,double *green,double *blue)
731b285095a81498ca0f0b24a0591e02aa599065b12cristy%
732b285095a81498ca0f0b24a0591e02aa599065b12cristy%  A description of each parameter follows:
733b285095a81498ca0f0b24a0591e02aa599065b12cristy%
734df42b17380e9d59e0ef874a62e553c9390157b7dcristy%    o luma, chroma, hue: A double value representing a component of the
735df42b17380e9d59e0ef874a62e553c9390157b7dcristy%      LCHab color space.
736b285095a81498ca0f0b24a0591e02aa599065b12cristy%
737b285095a81498ca0f0b24a0591e02aa599065b12cristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
738b285095a81498ca0f0b24a0591e02aa599065b12cristy%
739b285095a81498ca0f0b24a0591e02aa599065b12cristy*/
74035605e9ee687899cf1c79cf27572fba678ce636ecristy
74135605e9ee687899cf1c79cf27572fba678ce636ecristystatic inline void ConvertLCHabToXYZ(const double luma,const double chroma,
74235605e9ee687899cf1c79cf27572fba678ce636ecristy  const double hue,double *X,double *Y,double *Z)
74335605e9ee687899cf1c79cf27572fba678ce636ecristy{
74435605e9ee687899cf1c79cf27572fba678ce636ecristy  ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
74535605e9ee687899cf1c79cf27572fba678ce636ecristy    sin(hue*MagickPI/180.0),X,Y,Z);
74635605e9ee687899cf1c79cf27572fba678ce636ecristy}
74735605e9ee687899cf1c79cf27572fba678ce636ecristy
748df42b17380e9d59e0ef874a62e553c9390157b7dcristyMagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
749b285095a81498ca0f0b24a0591e02aa599065b12cristy  const double hue,double *red,double *green,double *blue)
750b285095a81498ca0f0b24a0591e02aa599065b12cristy{
751b285095a81498ca0f0b24a0591e02aa599065b12cristy  double
752b285095a81498ca0f0b24a0591e02aa599065b12cristy    X,
753b285095a81498ca0f0b24a0591e02aa599065b12cristy    Y,
754b285095a81498ca0f0b24a0591e02aa599065b12cristy    Z;
755b285095a81498ca0f0b24a0591e02aa599065b12cristy
756b285095a81498ca0f0b24a0591e02aa599065b12cristy  /*
757df42b17380e9d59e0ef874a62e553c9390157b7dcristy    Convert LCHab to RGB colorspace.
758b285095a81498ca0f0b24a0591e02aa599065b12cristy  */
759b285095a81498ca0f0b24a0591e02aa599065b12cristy  assert(red != (double *) NULL);
760b285095a81498ca0f0b24a0591e02aa599065b12cristy  assert(green != (double *) NULL);
761b285095a81498ca0f0b24a0591e02aa599065b12cristy  assert(blue != (double *) NULL);
7620c125416d27796cd9becc0df8cbb763ee1c5e189cristy  ConvertLCHabToXYZ(100.0*luma,255.0*(chroma-0.5),255.0*(hue-0.5),&X,&Y,&Z);
763b285095a81498ca0f0b24a0591e02aa599065b12cristy  ConvertXYZToRGB(X,Y,Z,red,green,blue);
764b285095a81498ca0f0b24a0591e02aa599065b12cristy}
765b285095a81498ca0f0b24a0591e02aa599065b12cristy
766b285095a81498ca0f0b24a0591e02aa599065b12cristy/*
767b285095a81498ca0f0b24a0591e02aa599065b12cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
769b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
770b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
771df42b17380e9d59e0ef874a62e553c9390157b7dcristy%   C o n v e r t L C H u v T o R G B                                         %
772df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
773df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
774df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
775df42b17380e9d59e0ef874a62e553c9390157b7dcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
776df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
777df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  ConvertLCHuvToRGB() transforms a (luma, chroma, hue) to a (red, green,
778df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  blue) triple.
779df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
780df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  The format of the ConvertLCHuvToRGBImage method is:
781df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
782df42b17380e9d59e0ef874a62e553c9390157b7dcristy%      void ConvertLCHuvToRGB(const double luma,const double chroma,
783df42b17380e9d59e0ef874a62e553c9390157b7dcristy%        const double hue,double *red,double *green,double *blue)
784df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
785df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  A description of each parameter follows:
786df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
787df42b17380e9d59e0ef874a62e553c9390157b7dcristy%    o luma, chroma, hue: A double value representing a component of the
788df42b17380e9d59e0ef874a62e553c9390157b7dcristy%      LCHuv color space.
789df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
790df42b17380e9d59e0ef874a62e553c9390157b7dcristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
791df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
792df42b17380e9d59e0ef874a62e553c9390157b7dcristy*/
793a8716919a55158a0c96230260000665d0db38a3acristy
794a8716919a55158a0c96230260000665d0db38a3acristystatic inline void ConvertLCHuvToXYZ(const double luma,const double chroma,
795a8716919a55158a0c96230260000665d0db38a3acristy  const double hue,double *X,double *Y,double *Z)
796a8716919a55158a0c96230260000665d0db38a3acristy{
797a8716919a55158a0c96230260000665d0db38a3acristy  ConvertLuvToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
798a8716919a55158a0c96230260000665d0db38a3acristy    sin(hue*MagickPI/180.0),X,Y,Z);
799a8716919a55158a0c96230260000665d0db38a3acristy}
800a8716919a55158a0c96230260000665d0db38a3acristy
801df42b17380e9d59e0ef874a62e553c9390157b7dcristyMagickPrivate void ConvertLCHuvToRGB(const double luma,const double chroma,
802df42b17380e9d59e0ef874a62e553c9390157b7dcristy  const double hue,double *red,double *green,double *blue)
803df42b17380e9d59e0ef874a62e553c9390157b7dcristy{
804df42b17380e9d59e0ef874a62e553c9390157b7dcristy  double
805df42b17380e9d59e0ef874a62e553c9390157b7dcristy    X,
806df42b17380e9d59e0ef874a62e553c9390157b7dcristy    Y,
807df42b17380e9d59e0ef874a62e553c9390157b7dcristy    Z;
808df42b17380e9d59e0ef874a62e553c9390157b7dcristy
809df42b17380e9d59e0ef874a62e553c9390157b7dcristy  /*
810df42b17380e9d59e0ef874a62e553c9390157b7dcristy    Convert LCHuv to RGB colorspace.
811df42b17380e9d59e0ef874a62e553c9390157b7dcristy  */
812df42b17380e9d59e0ef874a62e553c9390157b7dcristy  assert(red != (double *) NULL);
813df42b17380e9d59e0ef874a62e553c9390157b7dcristy  assert(green != (double *) NULL);
814df42b17380e9d59e0ef874a62e553c9390157b7dcristy  assert(blue != (double *) NULL);
815a8716919a55158a0c96230260000665d0db38a3acristy  ConvertLCHuvToXYZ(100.0*luma,354.0*chroma-134.0,262.0*hue-140.0,&X,&Y,&Z);
816df42b17380e9d59e0ef874a62e553c9390157b7dcristy  ConvertXYZToRGB(X,Y,Z,red,green,blue);
817df42b17380e9d59e0ef874a62e553c9390157b7dcristy}
818df42b17380e9d59e0ef874a62e553c9390157b7dcristy
819df42b17380e9d59e0ef874a62e553c9390157b7dcristy/*
820df42b17380e9d59e0ef874a62e553c9390157b7dcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
822df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
823df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
824722fc0cce634eb07588336accc3bb52979738a5ccristy%   C o n v e r t R G B T o H C L                                             %
825722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
826722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
827722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
828722fc0cce634eb07588336accc3bb52979738a5ccristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829722fc0cce634eb07588336accc3bb52979738a5ccristy%
830722fc0cce634eb07588336accc3bb52979738a5ccristy%  ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
831722fc0cce634eb07588336accc3bb52979738a5ccristy%  luma) triple.
832722fc0cce634eb07588336accc3bb52979738a5ccristy%
833722fc0cce634eb07588336accc3bb52979738a5ccristy%  The format of the ConvertRGBToHCL method is:
834722fc0cce634eb07588336accc3bb52979738a5ccristy%
835722fc0cce634eb07588336accc3bb52979738a5ccristy%      void ConvertRGBToHCL(const double red,const double green,
836722fc0cce634eb07588336accc3bb52979738a5ccristy%        const double blue,double *hue,double *chroma,double *luma)
837722fc0cce634eb07588336accc3bb52979738a5ccristy%
838722fc0cce634eb07588336accc3bb52979738a5ccristy%  A description of each parameter follows:
839722fc0cce634eb07588336accc3bb52979738a5ccristy%
840722fc0cce634eb07588336accc3bb52979738a5ccristy%    o red, green, blue: A Quantum value representing the red, green, and
841722fc0cce634eb07588336accc3bb52979738a5ccristy%      blue component of a pixel.
842722fc0cce634eb07588336accc3bb52979738a5ccristy%
843722fc0cce634eb07588336accc3bb52979738a5ccristy%    o hue, chroma, luma: A pointer to a double value representing a
844722fc0cce634eb07588336accc3bb52979738a5ccristy%      component of the HCL color space.
845722fc0cce634eb07588336accc3bb52979738a5ccristy%
846722fc0cce634eb07588336accc3bb52979738a5ccristy*/
8475756d82f940337296549c59f25ff7f96eff132b1cristy
8485756d82f940337296549c59f25ff7f96eff132b1cristystatic inline double MagickMax(const double x,const double y)
8495756d82f940337296549c59f25ff7f96eff132b1cristy{
8505756d82f940337296549c59f25ff7f96eff132b1cristy  if (x > y)
8515756d82f940337296549c59f25ff7f96eff132b1cristy    return(x);
8525756d82f940337296549c59f25ff7f96eff132b1cristy  return(y);
8535756d82f940337296549c59f25ff7f96eff132b1cristy}
8545756d82f940337296549c59f25ff7f96eff132b1cristy
8555756d82f940337296549c59f25ff7f96eff132b1cristystatic inline double MagickMin(const double x,const double y)
8565756d82f940337296549c59f25ff7f96eff132b1cristy{
8575756d82f940337296549c59f25ff7f96eff132b1cristy  if (x < y)
8585756d82f940337296549c59f25ff7f96eff132b1cristy    return(x);
8595756d82f940337296549c59f25ff7f96eff132b1cristy  return(y);
8605756d82f940337296549c59f25ff7f96eff132b1cristy}
8615756d82f940337296549c59f25ff7f96eff132b1cristy
862722fc0cce634eb07588336accc3bb52979738a5ccristyMagickPrivate void ConvertRGBToHCL(const double red,const double green,
863722fc0cce634eb07588336accc3bb52979738a5ccristy  const double blue,double *hue,double *chroma,double *luma)
864722fc0cce634eb07588336accc3bb52979738a5ccristy{
865722fc0cce634eb07588336accc3bb52979738a5ccristy  double
8665756d82f940337296549c59f25ff7f96eff132b1cristy    b,
8675756d82f940337296549c59f25ff7f96eff132b1cristy    c,
8685756d82f940337296549c59f25ff7f96eff132b1cristy    g,
8695756d82f940337296549c59f25ff7f96eff132b1cristy    h,
8705756d82f940337296549c59f25ff7f96eff132b1cristy    max,
8715756d82f940337296549c59f25ff7f96eff132b1cristy    r;
872722fc0cce634eb07588336accc3bb52979738a5ccristy
873722fc0cce634eb07588336accc3bb52979738a5ccristy  /*
874722fc0cce634eb07588336accc3bb52979738a5ccristy    Convert RGB to HCL colorspace.
875722fc0cce634eb07588336accc3bb52979738a5ccristy  */
8769427c42b6fe25470c57cbb224651080a7813e7cccristy  assert(hue != (double *) NULL);
8775756d82f940337296549c59f25ff7f96eff132b1cristy  assert(chroma != (double *) NULL);
8785756d82f940337296549c59f25ff7f96eff132b1cristy  assert(luma != (double *) NULL);
8795756d82f940337296549c59f25ff7f96eff132b1cristy  r=red;
8805756d82f940337296549c59f25ff7f96eff132b1cristy  g=green;
8815756d82f940337296549c59f25ff7f96eff132b1cristy  b=blue;
8825756d82f940337296549c59f25ff7f96eff132b1cristy  max=MagickMax(r,MagickMax(g,b));
8835756d82f940337296549c59f25ff7f96eff132b1cristy  c=max-(double) MagickMin(r,MagickMin(g,b));
8845756d82f940337296549c59f25ff7f96eff132b1cristy  h=0.0;
8855756d82f940337296549c59f25ff7f96eff132b1cristy  if (c == 0.0)
8865756d82f940337296549c59f25ff7f96eff132b1cristy    h=0.0;
8875756d82f940337296549c59f25ff7f96eff132b1cristy  else
8885756d82f940337296549c59f25ff7f96eff132b1cristy    if (red == max)
8895756d82f940337296549c59f25ff7f96eff132b1cristy      h=fmod((g-b)/c+6.0,6.0);
8905756d82f940337296549c59f25ff7f96eff132b1cristy    else
8915756d82f940337296549c59f25ff7f96eff132b1cristy      if (green == max)
8925756d82f940337296549c59f25ff7f96eff132b1cristy        h=((b-r)/c)+2.0;
8935756d82f940337296549c59f25ff7f96eff132b1cristy      else
8945756d82f940337296549c59f25ff7f96eff132b1cristy        if (blue == max)
8955756d82f940337296549c59f25ff7f96eff132b1cristy          h=((r-g)/c)+4.0;
8965756d82f940337296549c59f25ff7f96eff132b1cristy  *hue=(h/6.0);
8975756d82f940337296549c59f25ff7f96eff132b1cristy  *chroma=QuantumScale*c;
8989e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
8999e2436a78bdabef900e018dc77c0cc497bf6fbafcristy}
9009e2436a78bdabef900e018dc77c0cc497bf6fbafcristy
9019e2436a78bdabef900e018dc77c0cc497bf6fbafcristy/*
9029e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9039e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
9049e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
9059e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
9069e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%   C o n v e r t R G B T o H C L p                                           %
9079e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
9089e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
9099e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%                                                                             %
9109e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9119e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
9129e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%  ConvertRGBToHCLp() transforms a (red, green, blue) to a (hue, chroma,
9139e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%  luma) triple.
9149e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
9159e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%  The format of the ConvertRGBToHCLp method is:
9169e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
9179e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%      void ConvertRGBToHCLp(const double red,const double green,
9189e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%        const double blue,double *hue,double *chroma,double *luma)
9199e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
9209e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%  A description of each parameter follows:
9219e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
9229e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%    o red, green, blue: A Quantum value representing the red, green, and
9239e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%      blue component of a pixel.
9249e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
9259e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%    o hue, chroma, luma: A pointer to a double value representing a
9269e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%      component of the HCL color space.
9279e2436a78bdabef900e018dc77c0cc497bf6fbafcristy%
9289e2436a78bdabef900e018dc77c0cc497bf6fbafcristy*/
9299e2436a78bdabef900e018dc77c0cc497bf6fbafcristyMagickPrivate void ConvertRGBToHCLp(const double red,const double green,
9309e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  const double blue,double *hue,double *chroma,double *luma)
9319e2436a78bdabef900e018dc77c0cc497bf6fbafcristy{
9329e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  double
9339e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    b,
9349e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    c,
9359e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    g,
9369e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    h,
9379e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    max,
9389e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    r;
9399e2436a78bdabef900e018dc77c0cc497bf6fbafcristy
9409e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  /*
9419e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    Convert RGB to HCL colorspace.
9429e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  */
9439e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  assert(hue != (double *) NULL);
9449e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  assert(chroma != (double *) NULL);
9459e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  assert(luma != (double *) NULL);
9469e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  r=red;
9479e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  g=green;
9489e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  b=blue;
9499e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  max=MagickMax(r,MagickMax(g,b));
9509e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  c=max-(double) MagickMin(r,MagickMin(g,b));
9519e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  h=0.0;
9529e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  if (c == 0.0)
9539e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    h=0.0;
9549e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  else
9559e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    if (red == max)
9569e2436a78bdabef900e018dc77c0cc497bf6fbafcristy      h=fmod((g-b)/c+6.0,6.0);
9579e2436a78bdabef900e018dc77c0cc497bf6fbafcristy    else
9589e2436a78bdabef900e018dc77c0cc497bf6fbafcristy      if (green == max)
9599e2436a78bdabef900e018dc77c0cc497bf6fbafcristy        h=((b-r)/c)+2.0;
9609e2436a78bdabef900e018dc77c0cc497bf6fbafcristy      else
9619e2436a78bdabef900e018dc77c0cc497bf6fbafcristy        if (blue == max)
9629e2436a78bdabef900e018dc77c0cc497bf6fbafcristy          h=((r-g)/c)+4.0;
9639e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  *hue=(h/6.0);
9649e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  *chroma=QuantumScale*c;
9659e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
966722fc0cce634eb07588336accc3bb52979738a5ccristy}
967722fc0cce634eb07588336accc3bb52979738a5ccristy
968722fc0cce634eb07588336accc3bb52979738a5ccristy/*
969722fc0cce634eb07588336accc3bb52979738a5ccristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
970722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
971722fc0cce634eb07588336accc3bb52979738a5ccristy%                                                                             %
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9730a39a5c567fca70403bc431d18890e89fc253eefcristy%   C o n v e r t R G B T o H S B                                             %
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9790a39a5c567fca70403bc431d18890e89fc253eefcristy%  ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  brightness) triple.
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9820a39a5c567fca70403bc431d18890e89fc253eefcristy%  The format of the ConvertRGBToHSB method is:
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9840a39a5c567fca70403bc431d18890e89fc253eefcristy%      void ConvertRGBToHSB(const double red,const double green,
9853094b7f3243820cc5559d370412a9d406d074348cristy%        const double blue,double *hue,double *saturation,double *brightness)
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A Quantum value representing the red, green, and
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      blue component of a pixel..
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, saturation, brightness: A pointer to a double value representing a
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HSB color space.
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9960a39a5c567fca70403bc431d18890e89fc253eefcristyMagickPrivate void ConvertRGBToHSB(const double red,const double green,
9973094b7f3243820cc5559d370412a9d406d074348cristy  const double blue,double *hue,double *saturation,double *brightness)
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
999caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  double
1000caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    b,
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    delta,
1002caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    g,
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max,
1004caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    min,
1005caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    r;
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert RGB to HSB colorspace.
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(hue != (double *) NULL);
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(saturation != (double *) NULL);
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(brightness != (double *) NULL);
10133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *hue=0.0;
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *saturation=0.0;
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *brightness=0.0;
10160a39a5c567fca70403bc431d18890e89fc253eefcristy  r=red;
10170a39a5c567fca70403bc431d18890e89fc253eefcristy  g=green;
10180a39a5c567fca70403bc431d18890e89fc253eefcristy  b=blue;
1019caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  min=r < g ? r : g;
1020caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  if (b < min)
1021caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    min=b;
1022caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  max=r > g ? r : g;
1023caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  if (b > max)
1024caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    max=b;
10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (max == 0.0)
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return;
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  delta=max-min;
1028caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  *saturation=delta/max;
1029caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  *brightness=QuantumScale*max;
10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (delta == 0.0)
10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return;
1032caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  if (r == max)
1033caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    *hue=(g-b)/delta;
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
1035caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    if (g == max)
1036caf4580de0f80e561a5fcb59c89f2f8adac91006cristy      *hue=2.0+(b-r)/delta;
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
1038caf4580de0f80e561a5fcb59c89f2f8adac91006cristy      *hue=4.0+(r-g)/delta;
103918b17443128598500357da7bff2f01683cf32890cristy  *hue/=6.0;
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*hue < 0.0)
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *hue+=1.0;
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1049af64eb219382bdf6243c4b8dc589268b8934304acristy%   C o n v e r t R G B T o H S I                                             %
1050af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
1051af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
1052af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
1053af64eb219382bdf6243c4b8dc589268b8934304acristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1054af64eb219382bdf6243c4b8dc589268b8934304acristy%
1055af64eb219382bdf6243c4b8dc589268b8934304acristy%  ConvertRGBToHSI() transforms a (red, green, blue) to a (hue, saturation,
1056af64eb219382bdf6243c4b8dc589268b8934304acristy%  intensity) triple.
1057af64eb219382bdf6243c4b8dc589268b8934304acristy%
1058af64eb219382bdf6243c4b8dc589268b8934304acristy%  The format of the ConvertRGBToHSI method is:
1059af64eb219382bdf6243c4b8dc589268b8934304acristy%
1060af64eb219382bdf6243c4b8dc589268b8934304acristy%      void ConvertRGBToHSI(const double red,const double green,
1061af64eb219382bdf6243c4b8dc589268b8934304acristy%        const double blue,double *hue,double *saturation,double *intensity)
1062af64eb219382bdf6243c4b8dc589268b8934304acristy%
1063af64eb219382bdf6243c4b8dc589268b8934304acristy%  A description of each parameter follows:
1064af64eb219382bdf6243c4b8dc589268b8934304acristy%
1065af64eb219382bdf6243c4b8dc589268b8934304acristy%    o red, green, blue: A Quantum value representing the red, green, and
1066af64eb219382bdf6243c4b8dc589268b8934304acristy%      blue component of a pixel..
1067af64eb219382bdf6243c4b8dc589268b8934304acristy%
1068af64eb219382bdf6243c4b8dc589268b8934304acristy%    o hue, saturation, intensity: A pointer to a double value representing a
1069af64eb219382bdf6243c4b8dc589268b8934304acristy%      component of the HSI color space.
1070af64eb219382bdf6243c4b8dc589268b8934304acristy%
1071af64eb219382bdf6243c4b8dc589268b8934304acristy*/
1072af64eb219382bdf6243c4b8dc589268b8934304acristyMagickPrivate void ConvertRGBToHSI(const double red,const double green,
1073af64eb219382bdf6243c4b8dc589268b8934304acristy  const double blue,double *hue,double *saturation,double *intensity)
1074af64eb219382bdf6243c4b8dc589268b8934304acristy{
1075af64eb219382bdf6243c4b8dc589268b8934304acristy  double
1076af64eb219382bdf6243c4b8dc589268b8934304acristy    alpha,
1077af64eb219382bdf6243c4b8dc589268b8934304acristy    beta;
1078af64eb219382bdf6243c4b8dc589268b8934304acristy
1079af64eb219382bdf6243c4b8dc589268b8934304acristy  /*
1080af64eb219382bdf6243c4b8dc589268b8934304acristy    Convert RGB to HSI colorspace.
1081af64eb219382bdf6243c4b8dc589268b8934304acristy  */
1082af64eb219382bdf6243c4b8dc589268b8934304acristy  assert(hue != (double *) NULL);
1083af64eb219382bdf6243c4b8dc589268b8934304acristy  assert(saturation != (double *) NULL);
1084af64eb219382bdf6243c4b8dc589268b8934304acristy  assert(intensity != (double *) NULL);
1085af64eb219382bdf6243c4b8dc589268b8934304acristy  *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0;
1086af64eb219382bdf6243c4b8dc589268b8934304acristy  if (*intensity <= 0.0)
1087af64eb219382bdf6243c4b8dc589268b8934304acristy    {
1088af64eb219382bdf6243c4b8dc589268b8934304acristy      *hue=0.0;
1089af64eb219382bdf6243c4b8dc589268b8934304acristy      *saturation=0.0;
1090a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      return;
1091af64eb219382bdf6243c4b8dc589268b8934304acristy    }
1092a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1093a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    QuantumScale*blue))/(*intensity);
1094a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
1095be708af579eaa7bfae7d7ae760f3a8d177d3f79fcristy  beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue);
1096a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
1097a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  if (*hue < 0.0)
1098a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    *hue+=1.0;
1099af64eb219382bdf6243c4b8dc589268b8934304acristy}
1100af64eb219382bdf6243c4b8dc589268b8934304acristy
1101af64eb219382bdf6243c4b8dc589268b8934304acristy/*
1102af64eb219382bdf6243c4b8dc589268b8934304acristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1103af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
1104af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
1105af64eb219382bdf6243c4b8dc589268b8934304acristy%                                                                             %
11060a39a5c567fca70403bc431d18890e89fc253eefcristy%   C o n v e r t R G B T o H S L                                             %
11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11120a39a5c567fca70403bc431d18890e89fc253eefcristy%  ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  lightness) triple.
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11150a39a5c567fca70403bc431d18890e89fc253eefcristy%  The format of the ConvertRGBToHSL method is:
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11170a39a5c567fca70403bc431d18890e89fc253eefcristy%      void ConvertRGBToHSL(const double red,const double green,
11183094b7f3243820cc5559d370412a9d406d074348cristy%        const double blue,double *hue,double *saturation,double *lightness)
11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A Quantum value representing the red, green, and
11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      blue component of a pixel..
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, saturation, lightness: A pointer to a double value representing a
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HSL color space.
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
11290a39a5c567fca70403bc431d18890e89fc253eefcristyMagickExport void ConvertRGBToHSL(const double red,const double green,
11303094b7f3243820cc5559d370412a9d406d074348cristy  const double blue,double *hue,double *saturation,double *lightness)
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1132caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  double
1133a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    c,
11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max,
1135a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    min;
11363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert RGB to HSL colorspace.
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(hue != (double *) NULL);
11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(saturation != (double *) NULL);
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(lightness != (double *) NULL);
1143a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1144a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    QuantumScale*blue));
1145a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1146a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    QuantumScale*blue));
1147a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  c=max-min;
1148a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  *lightness=(max+min)/2.0;
1149a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  if (c <= 0.0)
11503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
11513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *hue=0.0;
11523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *saturation=0.0;
11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1155a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  if (max == (QuantumScale*red))
1156a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    {
1157a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *hue=(QuantumScale*green-QuantumScale*blue)/c;
1158a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      if ((QuantumScale*green) < (QuantumScale*blue))
1159a5a45a77350d84dcb9b38c02dca4c585c983888ccristy        *hue+=6.0;
1160a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    }
11613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
1162a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    if (max == (QuantumScale*green))
1163a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
11643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
1165a5a45a77350d84dcb9b38c02dca4c585c983888ccristy      *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1166a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  *hue*=60.0/360.0;
1167a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  if (*lightness <= 0.5)
1168a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    *saturation=c/(2.0*(*lightness));
1169a5a45a77350d84dcb9b38c02dca4c585c983888ccristy  else
1170a5a45a77350d84dcb9b38c02dca4c585c983888ccristy    *saturation=c/(2.0-2.0*(*lightness));
11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
11723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
11743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1177246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
1178246c3135a833b00ed2e42448c85cc2ea1269b177cristy%   C o n v e r t R G B T o H S V                                             %
1179246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
1180246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
1181246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
1182246c3135a833b00ed2e42448c85cc2ea1269b177cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
1184246c3135a833b00ed2e42448c85cc2ea1269b177cristy%  ConvertRGBToHSV() transforms a (red, green, blue) to a (hue, saturation,
1185246c3135a833b00ed2e42448c85cc2ea1269b177cristy%  value) triple.
1186246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
1187246c3135a833b00ed2e42448c85cc2ea1269b177cristy%  The format of the ConvertRGBToHSV method is:
1188246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
1189246c3135a833b00ed2e42448c85cc2ea1269b177cristy%      void ConvertRGBToHSV(const double red,const double green,
1190246c3135a833b00ed2e42448c85cc2ea1269b177cristy%        const double blue,double *hue,double *saturation,double *value)
1191246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
1192246c3135a833b00ed2e42448c85cc2ea1269b177cristy%  A description of each parameter follows:
1193246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
1194246c3135a833b00ed2e42448c85cc2ea1269b177cristy%    o red, green, blue: A Quantum value representing the red, green, and
1195246c3135a833b00ed2e42448c85cc2ea1269b177cristy%      blue component of a pixel..
1196246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
1197246c3135a833b00ed2e42448c85cc2ea1269b177cristy%    o hue, saturation, value: A pointer to a double value representing a
1198246c3135a833b00ed2e42448c85cc2ea1269b177cristy%      component of the HSV color space.
1199246c3135a833b00ed2e42448c85cc2ea1269b177cristy%
1200246c3135a833b00ed2e42448c85cc2ea1269b177cristy*/
1201246c3135a833b00ed2e42448c85cc2ea1269b177cristyMagickPrivate void ConvertRGBToHSV(const double red,const double green,
1202246c3135a833b00ed2e42448c85cc2ea1269b177cristy  const double blue,double *hue,double *saturation,double *value)
1203246c3135a833b00ed2e42448c85cc2ea1269b177cristy{
1204246c3135a833b00ed2e42448c85cc2ea1269b177cristy  double
1205246c3135a833b00ed2e42448c85cc2ea1269b177cristy    c,
1206246c3135a833b00ed2e42448c85cc2ea1269b177cristy    max,
1207246c3135a833b00ed2e42448c85cc2ea1269b177cristy    min;
1208246c3135a833b00ed2e42448c85cc2ea1269b177cristy
1209246c3135a833b00ed2e42448c85cc2ea1269b177cristy  /*
1210246c3135a833b00ed2e42448c85cc2ea1269b177cristy    Convert RGB to HSV colorspace.
1211246c3135a833b00ed2e42448c85cc2ea1269b177cristy  */
1212246c3135a833b00ed2e42448c85cc2ea1269b177cristy  assert(hue != (double *) NULL);
1213246c3135a833b00ed2e42448c85cc2ea1269b177cristy  assert(saturation != (double *) NULL);
1214246c3135a833b00ed2e42448c85cc2ea1269b177cristy  assert(value != (double *) NULL);
1215246c3135a833b00ed2e42448c85cc2ea1269b177cristy  max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1216246c3135a833b00ed2e42448c85cc2ea1269b177cristy    QuantumScale*blue));
1217246c3135a833b00ed2e42448c85cc2ea1269b177cristy  min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1218246c3135a833b00ed2e42448c85cc2ea1269b177cristy    QuantumScale*blue));
1219246c3135a833b00ed2e42448c85cc2ea1269b177cristy  c=max-min;
1220246c3135a833b00ed2e42448c85cc2ea1269b177cristy  *value=max;
1221246c3135a833b00ed2e42448c85cc2ea1269b177cristy  if (c <= 0.0)
1222246c3135a833b00ed2e42448c85cc2ea1269b177cristy    {
1223246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *hue=0.0;
1224246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *saturation=0.0;
1225246c3135a833b00ed2e42448c85cc2ea1269b177cristy      return;
1226246c3135a833b00ed2e42448c85cc2ea1269b177cristy    }
1227246c3135a833b00ed2e42448c85cc2ea1269b177cristy  if (max == (QuantumScale*red))
1228246c3135a833b00ed2e42448c85cc2ea1269b177cristy    {
1229246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *hue=(QuantumScale*green-QuantumScale*blue)/c;
1230246c3135a833b00ed2e42448c85cc2ea1269b177cristy      if ((QuantumScale*green) < (QuantumScale*blue))
1231246c3135a833b00ed2e42448c85cc2ea1269b177cristy        *hue+=6.0;
1232246c3135a833b00ed2e42448c85cc2ea1269b177cristy    }
1233246c3135a833b00ed2e42448c85cc2ea1269b177cristy  else
1234246c3135a833b00ed2e42448c85cc2ea1269b177cristy    if (max == (QuantumScale*green))
1235246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1236246c3135a833b00ed2e42448c85cc2ea1269b177cristy    else
1237246c3135a833b00ed2e42448c85cc2ea1269b177cristy      *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1238246c3135a833b00ed2e42448c85cc2ea1269b177cristy  *hue*=60.0/360.0;
1239246c3135a833b00ed2e42448c85cc2ea1269b177cristy  *saturation=c/max;
1240246c3135a833b00ed2e42448c85cc2ea1269b177cristy}
1241246c3135a833b00ed2e42448c85cc2ea1269b177cristy
1242246c3135a833b00ed2e42448c85cc2ea1269b177cristy/*
1243246c3135a833b00ed2e42448c85cc2ea1269b177cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1244246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
1245246c3135a833b00ed2e42448c85cc2ea1269b177cristy%                                                                             %
12463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
12470a39a5c567fca70403bc431d18890e89fc253eefcristy%   C o n v e r t R G B T o H W B                                             %
12483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
12493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
12503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
12513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
12530a39a5c567fca70403bc431d18890e89fc253eefcristy%  ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
12543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  blackness) triple.
12553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
12560a39a5c567fca70403bc431d18890e89fc253eefcristy%  The format of the ConvertRGBToHWB method is:
12573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
12580a39a5c567fca70403bc431d18890e89fc253eefcristy%      void ConvertRGBToHWB(const double red,const double green,
12593094b7f3243820cc5559d370412a9d406d074348cristy%        const double blue,double *hue,double *whiteness,double *blackness)
12603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
12613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
12623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
12633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A Quantum value representing the red, green, and
12643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      blue component of a pixel.
12653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
12663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, whiteness, blackness: A pointer to a double value representing a
12673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HWB color space.
12683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
12693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
12700a39a5c567fca70403bc431d18890e89fc253eefcristyMagickPrivate void ConvertRGBToHWB(const double red,const double green,
12713094b7f3243820cc5559d370412a9d406d074348cristy  const double blue,double *hue,double *whiteness,double *blackness)
12723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1273caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  double
1274caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    b,
12753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    f,
1276caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    g,
1277caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    p,
1278caf4580de0f80e561a5fcb59c89f2f8adac91006cristy    r,
12793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    v,
12803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    w;
12813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
12833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert RGB to HWB colorspace.
12843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
12853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(hue != (double *) NULL);
12863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(whiteness != (double *) NULL);
12873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(blackness != (double *) NULL);
12880a39a5c567fca70403bc431d18890e89fc253eefcristy  r=red;
12890a39a5c567fca70403bc431d18890e89fc253eefcristy  g=green;
12900a39a5c567fca70403bc431d18890e89fc253eefcristy  b=blue;
1291caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  w=MagickMin(r,MagickMin(g,b));
1292caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  v=MagickMax(r,MagickMax(g,b));
12933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *blackness=1.0-QuantumScale*v;
12943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *whiteness=QuantumScale*w;
12953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (v == w)
12963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
1297af10b112a3fe7f0ca502f9cf0f8de2873ff7b97ecristy      *hue=(-1.0);
12983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
12993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1300caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  f=(r == w) ? g-b : ((g == w) ? b-r : r-g);
1301caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  p=(r == w) ? 3.0 : ((g == w) ? 5.0 : 1.0);
1302caf4580de0f80e561a5fcb59c89f2f8adac91006cristy  *hue=(p-f/(v-1.0*w))/6.0;
13033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
13043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
13063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1310a83d4c0356b4f70fca3b6fb6c2ff9b52fa0e2ec5cristy%   C o n v e r t R G B T o L C H a b                                         %
1311b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
1312b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
1313b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
1314b285095a81498ca0f0b24a0591e02aa599065b12cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1315b285095a81498ca0f0b24a0591e02aa599065b12cristy%
1316df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  ConvertRGBToLCHab() transforms a (red, green, blue) to a (luma, chroma,
1317b285095a81498ca0f0b24a0591e02aa599065b12cristy%  hue) triple.
1318b285095a81498ca0f0b24a0591e02aa599065b12cristy%
1319df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  The format of the ConvertRGBToLCHab method is:
1320b285095a81498ca0f0b24a0591e02aa599065b12cristy%
1321df42b17380e9d59e0ef874a62e553c9390157b7dcristy%      void ConvertRGBToLCHab(const double red,const double green,
1322b285095a81498ca0f0b24a0591e02aa599065b12cristy%        const double blue,double *luma,double *chroma,double *hue)
1323b285095a81498ca0f0b24a0591e02aa599065b12cristy%
1324b285095a81498ca0f0b24a0591e02aa599065b12cristy%  A description of each parameter follows:
1325b285095a81498ca0f0b24a0591e02aa599065b12cristy%
1326b285095a81498ca0f0b24a0591e02aa599065b12cristy%    o red, green, blue: A Quantum value representing the red, green, and
1327b285095a81498ca0f0b24a0591e02aa599065b12cristy%      blue component of a pixel.
1328b285095a81498ca0f0b24a0591e02aa599065b12cristy%
1329b285095a81498ca0f0b24a0591e02aa599065b12cristy%    o luma, chroma, hue: A pointer to a double value representing a
1330b285095a81498ca0f0b24a0591e02aa599065b12cristy%      component of the LCH color space.
1331b285095a81498ca0f0b24a0591e02aa599065b12cristy%
1332b285095a81498ca0f0b24a0591e02aa599065b12cristy*/
1333c32cb02801af90aacf5ced4c59e246867078c912cristy
1334c32cb02801af90aacf5ced4c59e246867078c912cristystatic inline void ConvertXYZToLCHab(const double X,const double Y,
1335c32cb02801af90aacf5ced4c59e246867078c912cristy  const double Z,double *luma,double *chroma,double *hue)
1336c32cb02801af90aacf5ced4c59e246867078c912cristy{
1337c32cb02801af90aacf5ced4c59e246867078c912cristy  double
1338c32cb02801af90aacf5ced4c59e246867078c912cristy    a,
1339c32cb02801af90aacf5ced4c59e246867078c912cristy    b;
1340c32cb02801af90aacf5ced4c59e246867078c912cristy
1341c32cb02801af90aacf5ced4c59e246867078c912cristy  ConvertXYZToLab(X,Y,Z,luma,&a,&b);
13429db2dba5a8e6618bbec0971f1b3b12423f46401dcristy  *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5));
13439db2dba5a8e6618bbec0971f1b3b12423f46401dcristy  *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI;
13449db2dba5a8e6618bbec0971f1b3b12423f46401dcristy  *chroma=(*chroma)/255.0+0.5;
13459db2dba5a8e6618bbec0971f1b3b12423f46401dcristy  *hue=(*hue)/255.0+0.5;
134689106f86b28a27c7b7d9b07e13db58516ab8d01fcristy  if (*hue < 0.0)
134789106f86b28a27c7b7d9b07e13db58516ab8d01fcristy    *hue+=1.0;
1348c32cb02801af90aacf5ced4c59e246867078c912cristy}
1349c32cb02801af90aacf5ced4c59e246867078c912cristy
1350df42b17380e9d59e0ef874a62e553c9390157b7dcristyMagickPrivate void ConvertRGBToLCHab(const double red,const double green,
1351b285095a81498ca0f0b24a0591e02aa599065b12cristy  const double blue,double *luma,double *chroma,double *hue)
1352b285095a81498ca0f0b24a0591e02aa599065b12cristy{
1353b285095a81498ca0f0b24a0591e02aa599065b12cristy  double
1354b285095a81498ca0f0b24a0591e02aa599065b12cristy    X,
1355b285095a81498ca0f0b24a0591e02aa599065b12cristy    Y,
1356b285095a81498ca0f0b24a0591e02aa599065b12cristy    Z;
1357b285095a81498ca0f0b24a0591e02aa599065b12cristy
1358b285095a81498ca0f0b24a0591e02aa599065b12cristy  /*
13599427c42b6fe25470c57cbb224651080a7813e7cccristy    Convert RGB to LCHab colorspace.
1360b285095a81498ca0f0b24a0591e02aa599065b12cristy  */
1361b285095a81498ca0f0b24a0591e02aa599065b12cristy  assert(luma != (double *) NULL);
1362b285095a81498ca0f0b24a0591e02aa599065b12cristy  assert(chroma != (double *) NULL);
1363b285095a81498ca0f0b24a0591e02aa599065b12cristy  assert(hue != (double *) NULL);
1364b285095a81498ca0f0b24a0591e02aa599065b12cristy  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1365c32cb02801af90aacf5ced4c59e246867078c912cristy  ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue);
1366b285095a81498ca0f0b24a0591e02aa599065b12cristy}
1367b285095a81498ca0f0b24a0591e02aa599065b12cristy
1368b285095a81498ca0f0b24a0591e02aa599065b12cristy/*
1369b285095a81498ca0f0b24a0591e02aa599065b12cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1370b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
1371b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
1372b285095a81498ca0f0b24a0591e02aa599065b12cristy%                                                                             %
1373a83d4c0356b4f70fca3b6fb6c2ff9b52fa0e2ec5cristy%   C o n v e r t R G B T o L C H u v                                         %
1374df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
1375df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
1376df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
1377df42b17380e9d59e0ef874a62e553c9390157b7dcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1378df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
1379df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  ConvertRGBToLCHuv() transforms a (red, green, blue) to a (luma, chroma,
1380df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  hue) triple.
1381df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
1382df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  The format of the ConvertRGBToLCHuv method is:
1383df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
1384df42b17380e9d59e0ef874a62e553c9390157b7dcristy%      void ConvertRGBToLCHuv(const double red,const double green,
1385df42b17380e9d59e0ef874a62e553c9390157b7dcristy%        const double blue,double *luma,double *chroma,double *hue)
1386df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
1387df42b17380e9d59e0ef874a62e553c9390157b7dcristy%  A description of each parameter follows:
1388df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
1389df42b17380e9d59e0ef874a62e553c9390157b7dcristy%    o red, green, blue: A Quantum value representing the red, green, and
1390df42b17380e9d59e0ef874a62e553c9390157b7dcristy%      blue component of a pixel.
1391df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
1392df42b17380e9d59e0ef874a62e553c9390157b7dcristy%    o luma, chroma, hue: A pointer to a double value representing a
1393df42b17380e9d59e0ef874a62e553c9390157b7dcristy%      component of the LCHuv color space.
1394df42b17380e9d59e0ef874a62e553c9390157b7dcristy%
1395df42b17380e9d59e0ef874a62e553c9390157b7dcristy*/
1396c32cb02801af90aacf5ced4c59e246867078c912cristy
1397c32cb02801af90aacf5ced4c59e246867078c912cristystatic inline void ConvertXYZToLCHuv(const double X,const double Y,
1398c32cb02801af90aacf5ced4c59e246867078c912cristy  const double Z,double *luma,double *chroma,double *hue)
1399c32cb02801af90aacf5ced4c59e246867078c912cristy{
1400c32cb02801af90aacf5ced4c59e246867078c912cristy  double
14019db2dba5a8e6618bbec0971f1b3b12423f46401dcristy    u,
14029db2dba5a8e6618bbec0971f1b3b12423f46401dcristy    v;
1403c32cb02801af90aacf5ced4c59e246867078c912cristy
14049db2dba5a8e6618bbec0971f1b3b12423f46401dcristy  ConvertXYZToLuv(X,Y,Z,luma,&u,&v);
14059db2dba5a8e6618bbec0971f1b3b12423f46401dcristy  *chroma=hypot(354.0*u-134.0,262.0*v-140.0);
14069db2dba5a8e6618bbec0971f1b3b12423f46401dcristy  *hue=180.0*atan2(262.0*v-140.0,354.0*u-134.0)/MagickPI;
1407c32cb02801af90aacf5ced4c59e246867078c912cristy  if (*hue < 0.0)
1408c32cb02801af90aacf5ced4c59e246867078c912cristy    *hue+=360.0;
14099db2dba5a8e6618bbec0971f1b3b12423f46401dcristy  *chroma=(*chroma+134.0)/354.0;
14109db2dba5a8e6618bbec0971f1b3b12423f46401dcristy  *hue=(*hue+140.0)/262.0;
1411c32cb02801af90aacf5ced4c59e246867078c912cristy}
1412c32cb02801af90aacf5ced4c59e246867078c912cristy
1413df42b17380e9d59e0ef874a62e553c9390157b7dcristyMagickPrivate void ConvertRGBToLCHuv(const double red,const double green,
1414df42b17380e9d59e0ef874a62e553c9390157b7dcristy  const double blue,double *luma,double *chroma,double *hue)
1415df42b17380e9d59e0ef874a62e553c9390157b7dcristy{
1416df42b17380e9d59e0ef874a62e553c9390157b7dcristy  double
1417df42b17380e9d59e0ef874a62e553c9390157b7dcristy    X,
1418df42b17380e9d59e0ef874a62e553c9390157b7dcristy    Y,
1419df42b17380e9d59e0ef874a62e553c9390157b7dcristy    Z;
1420df42b17380e9d59e0ef874a62e553c9390157b7dcristy
1421df42b17380e9d59e0ef874a62e553c9390157b7dcristy  /*
14229427c42b6fe25470c57cbb224651080a7813e7cccristy    Convert RGB to LCHuv colorspace.
1423df42b17380e9d59e0ef874a62e553c9390157b7dcristy  */
1424df42b17380e9d59e0ef874a62e553c9390157b7dcristy  assert(luma != (double *) NULL);
1425df42b17380e9d59e0ef874a62e553c9390157b7dcristy  assert(chroma != (double *) NULL);
1426df42b17380e9d59e0ef874a62e553c9390157b7dcristy  assert(hue != (double *) NULL);
1427df42b17380e9d59e0ef874a62e553c9390157b7dcristy  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1428c32cb02801af90aacf5ced4c59e246867078c912cristy  ConvertXYZToLCHuv(X,Y,Z,luma,chroma,hue);
1429df42b17380e9d59e0ef874a62e553c9390157b7dcristy}
1430df42b17380e9d59e0ef874a62e553c9390157b7dcristy
1431df42b17380e9d59e0ef874a62e553c9390157b7dcristy/*
1432df42b17380e9d59e0ef874a62e553c9390157b7dcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
1434df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
1435df42b17380e9d59e0ef874a62e553c9390157b7dcristy%                                                                             %
14363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   E x p a n d A f f i n e                                                   %
14373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ExpandAffine() computes the affine's expansion factor, i.e. the square root
14433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  of the factor by which the affine transform affects area. In an affine
14443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  transform composed of scaling, rotation, shearing, and translation, returns
14453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the amount of scaling.
14463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ExpandAffine method is:
14483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      double ExpandAffine(const AffineMatrix *affine)
14503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
14523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14532d7ffbbeca07eeb37beb7e8a246a4160aa9f2825cristy%    o expansion: ExpandAffine returns the affine's expansion factor.
14543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o affine: A pointer the affine transform of type AffineMatrix.
14563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
14583ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport double ExpandAffine(const AffineMatrix *affine)
14593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
14603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(affine != (const AffineMatrix *) NULL);
14613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
14623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
14633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
14653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   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                         %
14703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
147582b1583d4ca9179180de2754e6c25eef115cc181cristy%  GenerateDifferentialNoise() generates differentual noise.
14763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GenerateDifferentialNoise method is:
14783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      double GenerateDifferentialNoise(RandomInfo *random_info,
14809ed1f810381187775960350780d4d619c111dc4bcristy%        const Quantum pixel,const NoiseType noise_type,const double attenuate)
14813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
14833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o random_info: the random info.
14853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o pixel: noise is relative to this pixel value.
14873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o noise_type: the type of noise.
14893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o attenuate:  attenuate the noise.
14913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
14938ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
14949ed1f810381187775960350780d4d619c111dc4bcristy  const Quantum pixel,const NoiseType noise_type,const double attenuate)
14953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
14967118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaUniform  (attenuate*0.015625)
14977118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaGaussian  (attenuate*0.015625)
14987118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaImpulse  (attenuate*0.1)
14997118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaLaplacian (attenuate*0.0390625)
15007118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaMultiplicativeGaussian  (attenuate*0.5)
15014ce9df6057fcca6de6a4bbf18958c85ad22b106dcristy#define SigmaPoisson  (attenuate*12.5)
1502785eb590c771f467d6635fce646e366a6a3a2754cristy#define SigmaRandom  (attenuate)
15037118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define TauGaussian  (attenuate*0.078125)
15043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1505adb41caab5f958d39a3466968df0be65ef2b1045cristy  double
15063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    alpha,
15073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    beta,
15083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    noise,
15093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sigma;
15103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  alpha=GetPseudoRandomValue(random_info);
15123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch (noise_type)
15133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
15143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case UniformNoise:
15153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default:
15163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
15176bbabe6bce89c2e8051ea16a47efd0cb42c708e2cristy      noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
15183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
15193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
15203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case GaussianNoise:
15213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
1522adb41caab5f958d39a3466968df0be65ef2b1045cristy      double
152362faa60a11bc656bbeb1b418a95de40815a4490ccristy        gamma,
15243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        tau;
15253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1526adb41caab5f958d39a3466968df0be65ef2b1045cristy      if (alpha == 0.0)
1527adb41caab5f958d39a3466968df0be65ef2b1045cristy        alpha=1.0;
15283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      beta=GetPseudoRandomValue(random_info);
152962faa60a11bc656bbeb1b418a95de40815a4490ccristy      gamma=sqrt(-2.0*log(alpha));
153055a91cddcdea3aa002893186a773e1704884a9dfcristy      sigma=gamma*cos((double) (2.0*MagickPI*beta));
153155a91cddcdea3aa002893186a773e1704884a9dfcristy      tau=gamma*sin((double) (2.0*MagickPI*beta));
15326bbabe6bce89c2e8051ea16a47efd0cb42c708e2cristy      noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
15336bbabe6bce89c2e8051ea16a47efd0cb42c708e2cristy        QuantumRange*TauGaussian*tau);
15343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
15353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
15363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case ImpulseNoise:
15373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
15383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (alpha < (SigmaImpulse/2.0))
15393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        noise=0.0;
154037c2407b40ceacf637731f133d9dbff27a39f669cristy      else
154137c2407b40ceacf637731f133d9dbff27a39f669cristy        if (alpha >= (1.0-(SigmaImpulse/2.0)))
154237c2407b40ceacf637731f133d9dbff27a39f669cristy          noise=(double) QuantumRange;
154337c2407b40ceacf637731f133d9dbff27a39f669cristy        else
154437c2407b40ceacf637731f133d9dbff27a39f669cristy          noise=(double) pixel;
15453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
15463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
15473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case LaplacianNoise:
15483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
15493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (alpha <= 0.5)
15503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
15517118edf0993ccec017e96e2172e6ac672d3e24cdcristy          if (alpha <= MagickEpsilon)
15526bbabe6bce89c2e8051ea16a47efd0cb42c708e2cristy            noise=(double) (pixel-QuantumRange);
15533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          else
1554785eb590c771f467d6635fce646e366a6a3a2754cristy            noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
1555785eb590c771f467d6635fce646e366a6a3a2754cristy              0.5);
15563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
15573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
15583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      beta=1.0-alpha;
15597118edf0993ccec017e96e2172e6ac672d3e24cdcristy      if (beta <= (0.5*MagickEpsilon))
1560adb41caab5f958d39a3466968df0be65ef2b1045cristy        noise=(double) (pixel+QuantumRange);
15613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
15626bbabe6bce89c2e8051ea16a47efd0cb42c708e2cristy        noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
15637118edf0993ccec017e96e2172e6ac672d3e24cdcristy      break;
15647118edf0993ccec017e96e2172e6ac672d3e24cdcristy    }
15657118edf0993ccec017e96e2172e6ac672d3e24cdcristy    case MultiplicativeGaussianNoise:
15667118edf0993ccec017e96e2172e6ac672d3e24cdcristy    {
15677118edf0993ccec017e96e2172e6ac672d3e24cdcristy      sigma=1.0;
15687118edf0993ccec017e96e2172e6ac672d3e24cdcristy      if (alpha > MagickEpsilon)
15697118edf0993ccec017e96e2172e6ac672d3e24cdcristy        sigma=sqrt(-2.0*log(alpha));
15707118edf0993ccec017e96e2172e6ac672d3e24cdcristy      beta=GetPseudoRandomValue(random_info);
15716bbabe6bce89c2e8051ea16a47efd0cb42c708e2cristy      noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
15726bbabe6bce89c2e8051ea16a47efd0cb42c708e2cristy        cos((double) (2.0*MagickPI*beta))/2.0);
15733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
15743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
15753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case PoissonNoise:
15763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
1577adb41caab5f958d39a3466968df0be65ef2b1045cristy      double
15783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        poisson;
15793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1580bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      register ssize_t
15813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        i;
15823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15837118edf0993ccec017e96e2172e6ac672d3e24cdcristy      poisson=exp(-SigmaPoisson*QuantumScale*pixel);
15843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; alpha > poisson; i++)
15853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
15863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        beta=GetPseudoRandomValue(random_info);
15873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha*=beta;
15883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
15896bbabe6bce89c2e8051ea16a47efd0cb42c708e2cristy      noise=(double) (QuantumRange*i/SigmaPoisson);
15903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
15913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
15923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case RandomNoise:
15933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
1594785eb590c771f467d6635fce646e366a6a3a2754cristy      noise=(double) (QuantumRange*SigmaRandom*alpha);
15953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
15963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
15973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
15983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(noise);
15993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
16003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
16023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   G e t O p t i m a l K e r n e l W i d t h                                 %
16073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
16103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
16133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  filter.  Start with the minimum value of 3 pixels and walk out until we drop
16143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  below the threshold of one pixel numerical accuracy.
16153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GetOptimalKernelWidth method is:
16173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1618bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t GetOptimalKernelWidth(const double radius,
16193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        const double sigma)
16203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
16223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16232d7ffbbeca07eeb37beb7e8a246a4160aa9f2825cristy%    o width: GetOptimalKernelWidth returns the optimal width of a
16242d7ffbbeca07eeb37beb7e8a246a4160aa9f2825cristy%      convolution kernel.
16253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o radius: the radius of the Gaussian, in pixels, not counting the center
16273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      pixel.
16283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o sigma: the standard deviation of the Gaussian, in pixels.
16303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
16313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
16328ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
1633e96405a0f45f803fb9c26f75e7bdee252437febbcristy  const double sigma)
16343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1635e96405a0f45f803fb9c26f75e7bdee252437febbcristy  double
1636e96405a0f45f803fb9c26f75e7bdee252437febbcristy    alpha,
1637e96405a0f45f803fb9c26f75e7bdee252437febbcristy    beta,
1638e96405a0f45f803fb9c26f75e7bdee252437febbcristy    gamma,
16393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    normalize,
1640e96405a0f45f803fb9c26f75e7bdee252437febbcristy    value;
16413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1642bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
164347e00508ba238041491b7e0daf628ae3f21ab91ecristy    i;
164447e00508ba238041491b7e0daf628ae3f21ab91ecristy
1645bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
164647e00508ba238041491b7e0daf628ae3f21ab91ecristy    width;
16473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16489d314ff2c17a77996c05413c2013880387e50f0ecristy  ssize_t
16499d314ff2c17a77996c05413c2013880387e50f0ecristy    j;
16509d314ff2c17a77996c05413c2013880387e50f0ecristy
16513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
165247e00508ba238041491b7e0daf628ae3f21ab91ecristy  if (radius > MagickEpsilon)
1653bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    return((size_t) (2.0*ceil(radius)+1.0));
1654e96405a0f45f803fb9c26f75e7bdee252437febbcristy  gamma=fabs(sigma);
1655e96405a0f45f803fb9c26f75e7bdee252437febbcristy  if (gamma <= MagickEpsilon)
1656c106172cd6da00b6c8fd6a4c06efdd4aa32c7f06anthony    return(3UL);
16573e3ec3afbb0782697f201cbe30a56794c10dc7efcristy  alpha=PerceptibleReciprocal(2.0*gamma*gamma);
16583e3ec3afbb0782697f201cbe30a56794c10dc7efcristy  beta=(double) PerceptibleReciprocal((double) MagickSQ2PI*gamma);
16593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (width=5; ; )
16603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
16613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    normalize=0.0;
166235faaa73b04611ce5419c2bf48903d71ffea9869cristy    j=(ssize_t) (width-1)/2;
166347e00508ba238041491b7e0daf628ae3f21ab91ecristy    for (i=(-j); i <= j; i++)
1664e96405a0f45f803fb9c26f75e7bdee252437febbcristy      normalize+=exp(-((double) (i*i))*alpha)*beta;
1665e96405a0f45f803fb9c26f75e7bdee252437febbcristy    value=exp(-((double) (j*j))*alpha)*beta/normalize;
166620908dac8b2f15a9c0289728e57698bde5b74094cristy    if ((value < QuantumScale) || (value < MagickEpsilon))
16673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
16683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width+=2;
16693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
1670bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  return((size_t) (width-2));
16713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
16723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16738ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
1674e96405a0f45f803fb9c26f75e7bdee252437febbcristy  const double sigma)
16753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
167647e00508ba238041491b7e0daf628ae3f21ab91ecristy  double
1677e96405a0f45f803fb9c26f75e7bdee252437febbcristy    alpha,
1678e96405a0f45f803fb9c26f75e7bdee252437febbcristy    beta,
1679e96405a0f45f803fb9c26f75e7bdee252437febbcristy    gamma,
16803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    normalize,
1681e96405a0f45f803fb9c26f75e7bdee252437febbcristy    value;
16823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16839d314ff2c17a77996c05413c2013880387e50f0ecristy  size_t
16849d314ff2c17a77996c05413c2013880387e50f0ecristy    width;
16859d314ff2c17a77996c05413c2013880387e50f0ecristy
1686bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  ssize_t
168747e00508ba238041491b7e0daf628ae3f21ab91ecristy    j,
16883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    u,
16893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    v;
16903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
169247e00508ba238041491b7e0daf628ae3f21ab91ecristy  if (radius > MagickEpsilon)
1693bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    return((size_t) (2.0*ceil(radius)+1.0));
1694e96405a0f45f803fb9c26f75e7bdee252437febbcristy  gamma=fabs(sigma);
1695e96405a0f45f803fb9c26f75e7bdee252437febbcristy  if (gamma <= MagickEpsilon)
1696c106172cd6da00b6c8fd6a4c06efdd4aa32c7f06anthony    return(3UL);
16973e3ec3afbb0782697f201cbe30a56794c10dc7efcristy  alpha=PerceptibleReciprocal(2.0*gamma*gamma);
16983e3ec3afbb0782697f201cbe30a56794c10dc7efcristy  beta=(double) PerceptibleReciprocal((double) Magick2PI*gamma*gamma);
16993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (width=5; ; )
17003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
17013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    normalize=0.0;
170235faaa73b04611ce5419c2bf48903d71ffea9869cristy    j=(ssize_t) (width-1)/2;
170347e00508ba238041491b7e0daf628ae3f21ab91ecristy    for (v=(-j); v <= j; v++)
170447e00508ba238041491b7e0daf628ae3f21ab91ecristy      for (u=(-j); u <= j; u++)
1705e96405a0f45f803fb9c26f75e7bdee252437febbcristy        normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
1706e96405a0f45f803fb9c26f75e7bdee252437febbcristy    value=exp(-((double) (j*j))*alpha)*beta/normalize;
170720908dac8b2f15a9c0289728e57698bde5b74094cristy    if ((value < QuantumScale) || (value < MagickEpsilon))
17083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
17093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width+=2;
17103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
1711bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  return((size_t) (width-2));
17123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
17133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17148ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate size_t  GetOptimalKernelWidth(const double radius,
17153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const double sigma)
17163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
17173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetOptimalKernelWidth1D(radius,sigma));
17183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1719