gem.c revision 7118edf0993ccec017e96e2172e6ac672d3e24cd
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%                                                                             %
207e41fe84a841d7b9d7b36b245b65e9dcb3314943cristy%  Copyright 1999-2011 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"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/random_.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resize.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/transform.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/signature-private.h"
593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   C o n v e r t H S B T o R G B                                             %
663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  green, blue) triple.
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ConvertHSBToRGBImage method is:
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      void ConvertHSBToRGB(const double hue,const double saturation,
773094b7f3243820cc5559d370412a9d406d074348cristy%        const double brightness,double *red,double *green,double *blue)
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, saturation, brightness: A double value representing a
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HSB color space.
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
87d1dd6e4fefa0810b9893e6ac9418f79c97c1b39acristyMagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
883094b7f3243820cc5559d370412a9d406d074348cristy  const double brightness,double *red,double *green,double *blue)
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickRealType
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    f,
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    h,
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p,
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q,
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    t;
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert HSB to RGB colorspace.
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1003094b7f3243820cc5559d370412a9d406d074348cristy  assert(red != (double *) NULL);
1013094b7f3243820cc5559d370412a9d406d074348cristy  assert(green != (double *) NULL);
1023094b7f3243820cc5559d370412a9d406d074348cristy  assert(blue != (double *) NULL);
10398a65d5565159ce59b24013f0e3d148428af50d6cristy  if (saturation == 0.0)
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
105bcfb0439a92607a9f340b846b4c4147753059e62cristy      *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *green=(*red);
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *blue=(*red);
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11098a65d5565159ce59b24013f0e3d148428af50d6cristy  h=6.0*(hue-floor(hue));
11198a65d5565159ce59b24013f0e3d148428af50d6cristy  f=h-floor((double) h);
11298a65d5565159ce59b24013f0e3d148428af50d6cristy  p=brightness*(1.0-saturation);
11398a65d5565159ce59b24013f0e3d148428af50d6cristy  q=brightness*(1.0-saturation*f);
11498a65d5565159ce59b24013f0e3d148428af50d6cristy  t=brightness*(1.0-(saturation*(1.0-f)));
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch ((int) h)
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 0:
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default:
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
120bcfb0439a92607a9f340b846b4c4147753059e62cristy      *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
121bcfb0439a92607a9f340b846b4c4147753059e62cristy      *green=ClampToQuantum((MagickRealType) QuantumRange*t);
122bcfb0439a92607a9f340b846b4c4147753059e62cristy      *blue=ClampToQuantum((MagickRealType) QuantumRange*p);
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 1:
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
127bcfb0439a92607a9f340b846b4c4147753059e62cristy      *red=ClampToQuantum((MagickRealType) QuantumRange*q);
128bcfb0439a92607a9f340b846b4c4147753059e62cristy      *green=ClampToQuantum((MagickRealType) QuantumRange*brightness);
129bcfb0439a92607a9f340b846b4c4147753059e62cristy      *blue=ClampToQuantum((MagickRealType) QuantumRange*p);
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 2:
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
134bcfb0439a92607a9f340b846b4c4147753059e62cristy      *red=ClampToQuantum((MagickRealType) QuantumRange*p);
135bcfb0439a92607a9f340b846b4c4147753059e62cristy      *green=ClampToQuantum((MagickRealType) QuantumRange*brightness);
136bcfb0439a92607a9f340b846b4c4147753059e62cristy      *blue=ClampToQuantum((MagickRealType) QuantumRange*t);
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 3:
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
141bcfb0439a92607a9f340b846b4c4147753059e62cristy      *red=ClampToQuantum((MagickRealType) QuantumRange*p);
142bcfb0439a92607a9f340b846b4c4147753059e62cristy      *green=ClampToQuantum((MagickRealType) QuantumRange*q);
143bcfb0439a92607a9f340b846b4c4147753059e62cristy      *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 4:
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
148bcfb0439a92607a9f340b846b4c4147753059e62cristy      *red=ClampToQuantum((MagickRealType) QuantumRange*t);
149bcfb0439a92607a9f340b846b4c4147753059e62cristy      *green=ClampToQuantum((MagickRealType) QuantumRange*p);
150bcfb0439a92607a9f340b846b4c4147753059e62cristy      *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 5:
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
155bcfb0439a92607a9f340b846b4c4147753059e62cristy      *red=ClampToQuantum((MagickRealType) QuantumRange*brightness);
156bcfb0439a92607a9f340b846b4c4147753059e62cristy      *green=ClampToQuantum((MagickRealType) QuantumRange*p);
157bcfb0439a92607a9f340b846b4c4147753059e62cristy      *blue=ClampToQuantum((MagickRealType) QuantumRange*q);
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   C o n v e r t H S L T o R G B                                             %
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  green, blue) triple.
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ConvertHSLToRGBImage method is:
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      void ConvertHSLToRGB(const double hue,const double saturation,
1803094b7f3243820cc5559d370412a9d406d074348cristy%        const double lightness,double *red,double *green,double *blue)
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, saturation, lightness: A double value representing a
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HSL color space.
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline MagickRealType ConvertHueToRGB(MagickRealType m1,
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickRealType m2,MagickRealType hue)
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (hue < 0.0)
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    hue+=1.0;
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (hue > 1.0)
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    hue-=1.0;
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((6.0*hue) < 1.0)
199a163b0c302844472b6f8e028b25ed090aa9bf84acristy    return(m1+6.0*(m2-m1)*hue);
200a163b0c302844472b6f8e028b25ed090aa9bf84acristy  if ((2.0*hue) < 1.0)
201a163b0c302844472b6f8e028b25ed090aa9bf84acristy    return(m2);
202a163b0c302844472b6f8e028b25ed090aa9bf84acristy  if ((3.0*hue) < 2.0)
203a163b0c302844472b6f8e028b25ed090aa9bf84acristy    return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
204a163b0c302844472b6f8e028b25ed090aa9bf84acristy  return(m1);
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport void ConvertHSLToRGB(const double hue,const double saturation,
2083094b7f3243820cc5559d370412a9d406d074348cristy  const double lightness,double *red,double *green,double *blue)
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickRealType
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    b,
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    g,
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r,
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    m1,
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    m2;
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert HSL to RGB colorspace.
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2203094b7f3243820cc5559d370412a9d406d074348cristy  assert(red != (double *) NULL);
2213094b7f3243820cc5559d370412a9d406d074348cristy  assert(green != (double *) NULL);
2223094b7f3243820cc5559d370412a9d406d074348cristy  assert(blue != (double *) NULL);
22398a65d5565159ce59b24013f0e3d148428af50d6cristy  if (saturation == 0)
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
225bcfb0439a92607a9f340b846b4c4147753059e62cristy      *red=ClampToQuantum((MagickRealType) QuantumRange*lightness);
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *green=(*red);
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *blue=(*red);
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
23027cabb8cf0354e5570dce70b226165433d8d5585cristy  if (lightness < 0.5)
23198a65d5565159ce59b24013f0e3d148428af50d6cristy    m2=lightness*(saturation+1.0);
23298a65d5565159ce59b24013f0e3d148428af50d6cristy  else
23398a65d5565159ce59b24013f0e3d148428af50d6cristy    m2=(lightness+saturation)-(lightness*saturation);
23498a65d5565159ce59b24013f0e3d148428af50d6cristy  m1=2.0*lightness-m2;
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  g=ConvertHueToRGB(m1,m2,hue);
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
238bcfb0439a92607a9f340b846b4c4147753059e62cristy  *red=ClampToQuantum((MagickRealType) QuantumRange*r);
239bcfb0439a92607a9f340b846b4c4147753059e62cristy  *green=ClampToQuantum((MagickRealType) QuantumRange*g);
240bcfb0439a92607a9f340b846b4c4147753059e62cristy  *blue=ClampToQuantum((MagickRealType) QuantumRange*b);
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   C o n v e r t H W B T o R G B                                             %
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  blue) triple.
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ConvertHWBToRGBImage method is:
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      void ConvertHWBToRGB(const double hue,const double whiteness,
2603094b7f3243820cc5559d370412a9d406d074348cristy%        const double blackness,double *red,double *green,double *blue)
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, whiteness, blackness: A double value representing a
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HWB color space.
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A pointer to a pixel component of type Quantum.
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
270d1dd6e4fefa0810b9893e6ac9418f79c97c1b39acristyMagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
2713094b7f3243820cc5559d370412a9d406d074348cristy  const double blackness,double *red,double *green,double *blue)
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickRealType
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    b,
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    f,
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    g,
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    n,
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r,
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    v;
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
281bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert HWB to RGB colorspace.
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2873094b7f3243820cc5559d370412a9d406d074348cristy  assert(red != (double *) NULL);
2883094b7f3243820cc5559d370412a9d406d074348cristy  assert(green != (double *) NULL);
2893094b7f3243820cc5559d370412a9d406d074348cristy  assert(blue != (double *) NULL);
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  v=1.0-blackness;
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (hue == 0.0)
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
293bcfb0439a92607a9f340b846b4c4147753059e62cristy      *red=ClampToQuantum((MagickRealType) QuantumRange*v);
294bcfb0439a92607a9f340b846b4c4147753059e62cristy      *green=ClampToQuantum((MagickRealType) QuantumRange*v);
295bcfb0439a92607a9f340b846b4c4147753059e62cristy      *blue=ClampToQuantum((MagickRealType) QuantumRange*v);
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
298bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  i=(ssize_t) floor(6.0*hue);
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  f=6.0*hue-i;
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((i & 0x01) != 0)
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    f=1.0-f;
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  n=whiteness+f*(v-whiteness);  /* linear interpolation */
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch (i)
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default:
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 6:
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 0: r=v; g=n; b=whiteness; break;
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 1: r=n; g=v; b=whiteness; break;
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 2: r=whiteness; g=v; b=n; break;
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 3: r=whiteness; g=n; b=v; break;
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 4: r=n; g=whiteness; b=v; break;
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case 5: r=v; g=whiteness; b=n; break;
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
314bcfb0439a92607a9f340b846b4c4147753059e62cristy  *red=ClampToQuantum((MagickRealType) QuantumRange*r);
315bcfb0439a92607a9f340b846b4c4147753059e62cristy  *green=ClampToQuantum((MagickRealType) QuantumRange*g);
316bcfb0439a92607a9f340b846b4c4147753059e62cristy  *blue=ClampToQuantum((MagickRealType) QuantumRange*b);
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   C o n v e r t R G B T o H S B                                             %
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  brightness) triple.
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ConvertRGBToHSB method is:
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3353094b7f3243820cc5559d370412a9d406d074348cristy%      void ConvertRGBToHSB(const double red,const double green,
3363094b7f3243820cc5559d370412a9d406d074348cristy%        const double blue,double *hue,double *saturation,double *brightness)
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A Quantum value representing the red, green, and
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      blue component of a pixel..
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, saturation, brightness: A pointer to a double value representing a
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HSB color space.
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3473094b7f3243820cc5559d370412a9d406d074348cristyMagickPrivate void ConvertRGBToHSB(const double red,const double green,
3483094b7f3243820cc5559d370412a9d406d074348cristy  const double blue,double *hue,double *saturation,double *brightness)
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickRealType
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    delta,
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max,
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    min;
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert RGB to HSB colorspace.
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(hue != (double *) NULL);
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(saturation != (double *) NULL);
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(brightness != (double *) NULL);
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *hue=0.0;
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *saturation=0.0;
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *brightness=0.0;
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  min=(MagickRealType) (red < green ? red : green);
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((MagickRealType) blue < min)
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    min=(MagickRealType) blue;
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  max=(MagickRealType) (red > green ? red : green);
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((MagickRealType) blue > max)
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max=(MagickRealType) blue;
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (max == 0.0)
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return;
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  delta=max-min;
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *saturation=(double) (delta/max);
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *brightness=(double) (QuantumScale*max);
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (delta == 0.0)
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return;
37718b17443128598500357da7bff2f01683cf32890cristy  if ((MagickRealType) red == max)
37818b17443128598500357da7bff2f01683cf32890cristy    *hue=(double) ((green-(MagickRealType) blue)/delta);
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
38018b17443128598500357da7bff2f01683cf32890cristy    if ((MagickRealType) green == max)
38118b17443128598500357da7bff2f01683cf32890cristy      *hue=(double) (2.0+(blue-(MagickRealType) red)/delta);
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
38318b17443128598500357da7bff2f01683cf32890cristy      *hue=(double) (4.0+(red-(MagickRealType) green)/delta);
38418b17443128598500357da7bff2f01683cf32890cristy  *hue/=6.0;
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*hue < 0.0)
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *hue+=1.0;
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   C o n v e r t R G B T o H S L                                             %
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  lightness) triple.
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ConvertRGBToHSL method is:
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4053094b7f3243820cc5559d370412a9d406d074348cristy%      void ConvertRGBToHSL(const double red,const double green,
4063094b7f3243820cc5559d370412a9d406d074348cristy%        const double blue,double *hue,double *saturation,double *lightness)
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A Quantum value representing the red, green, and
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      blue component of a pixel..
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, saturation, lightness: A pointer to a double value representing a
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HSL color space.
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline double MagickMax(const double x,const double y)
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x > y)
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline double MagickMin(const double x,const double y)
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x < y)
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4323094b7f3243820cc5559d370412a9d406d074348cristyMagickExport void ConvertRGBToHSL(const double red,const double green,
4333094b7f3243820cc5559d370412a9d406d074348cristy  const double blue,double *hue,double *saturation,double *lightness)
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickRealType
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    b,
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    delta,
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    g,
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max,
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    min,
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r;
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert RGB to HSL colorspace.
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(hue != (double *) NULL);
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(saturation != (double *) NULL);
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(lightness != (double *) NULL);
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  r=QuantumScale*red;
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  g=QuantumScale*green;
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  b=QuantumScale*blue;
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  max=MagickMax(r,MagickMax(g,b));
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  min=MagickMin(r,MagickMin(g,b));
4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *lightness=(double) ((min+max)/2.0);
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  delta=max-min;
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (delta == 0.0)
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *hue=0.0;
4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *saturation=0.0;
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*lightness < 0.5)
4633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *saturation=(double) (delta/(min+max));
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *saturation=(double) (delta/(2.0-max-min));
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (r == max)
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (g == max)
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        delta;
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (b == max)
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (delta/2.0)))/delta;
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*hue < 0.0)
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *hue+=1.0;
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*hue > 1.0)
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *hue-=1.0;
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   C o n v e r t R G B T o H W B                                             %
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  blackness) triple.
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ConvertRGBToHWB method is:
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
4983094b7f3243820cc5559d370412a9d406d074348cristy%      void ConvertRGBToHWB(const double red,const double green,
4993094b7f3243820cc5559d370412a9d406d074348cristy%        const double blue,double *hue,double *whiteness,double *blackness)
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o red, green, blue: A Quantum value representing the red, green, and
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      blue component of a pixel.
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o hue, whiteness, blackness: A pointer to a double value representing a
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      component of the HWB color space.
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5103094b7f3243820cc5559d370412a9d406d074348cristyMagickPrivate void ConvertRGBToHWB(const double red,const double green,
5113094b7f3243820cc5559d370412a9d406d074348cristy  const double blue,double *hue,double *whiteness,double *blackness)
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
513bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  long
514bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    i;
515bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickRealType
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    f,
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    v,
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    w;
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert RGB to HWB colorspace.
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(hue != (double *) NULL);
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(whiteness != (double *) NULL);
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(blackness != (double *) NULL);
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  w=(MagickRealType) MagickMin((double) red,MagickMin((double) green,(double)
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    blue));
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  v=(MagickRealType) MagickMax((double) red,MagickMax((double) green,(double)
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    blue));
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *blackness=1.0-QuantumScale*v;
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *whiteness=QuantumScale*w;
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (v == w)
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *hue=0.0;
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  f=((MagickRealType) red == w) ? green-(MagickRealType) blue :
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (((MagickRealType) green == w) ? blue-(MagickRealType) red : red-
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (MagickRealType) green);
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  i=((MagickRealType) red == w) ? 3 : (((MagickRealType) green == w) ? 5 : 1);
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *hue=((double) i-f/(v-1.0*w))/6.0;
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   E x p a n d A f f i n e                                                   %
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ExpandAffine() computes the affine's expansion factor, i.e. the square root
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  of the factor by which the affine transform affects area. In an affine
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  transform composed of scaling, rotation, shearing, and translation, returns
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the amount of scaling.
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ExpandAffine method is:
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      double ExpandAffine(const AffineMatrix *affine)
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o expansion: Method ExpandAffine returns the affine's expansion factor.
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o affine: A pointer the affine transform of type AffineMatrix.
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport double ExpandAffine(const AffineMatrix *affine)
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(affine != (const AffineMatrix *) NULL);
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   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                         %
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
58982b1583d4ca9179180de2754e6c25eef115cc181cristy%  GenerateDifferentialNoise() generates differentual noise.
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GenerateDifferentialNoise method is:
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      double GenerateDifferentialNoise(RandomInfo *random_info,
5949ed1f810381187775960350780d4d619c111dc4bcristy%        const Quantum pixel,const NoiseType noise_type,const double attenuate)
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o random_info: the random info.
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o pixel: noise is relative to this pixel value.
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o noise_type: the type of noise.
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o attenuate:  attenuate the noise.
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
6078ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
6089ed1f810381187775960350780d4d619c111dc4bcristy  const Quantum pixel,const NoiseType noise_type,const double attenuate)
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
6107118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaUniform  (attenuate*0.015625)
6117118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaGaussian  (attenuate*0.015625)
6127118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaImpulse  (attenuate*0.1)
6137118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaLaplacian (attenuate*0.0390625)
6147118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaMultiplicativeGaussian  (attenuate*0.5)
6157118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaPoisson  (attenuate*0.05/0.0001953125)
6167118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define TauGaussian  (attenuate*0.078125)
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
618adb41caab5f958d39a3466968df0be65ef2b1045cristy  double
6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    alpha,
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    beta,
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    noise,
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sigma;
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  alpha=GetPseudoRandomValue(random_info);
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch (noise_type)
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case UniformNoise:
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default:
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6307118edf0993ccec017e96e2172e6ac672d3e24cdcristy      noise=(double) pixel+QuantumRange*SigmaUniform*(alpha-0.5);
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case GaussianNoise:
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
635adb41caab5f958d39a3466968df0be65ef2b1045cristy      double
63662faa60a11bc656bbeb1b418a95de40815a4490ccristy        gamma,
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        tau;
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
639adb41caab5f958d39a3466968df0be65ef2b1045cristy      if (alpha == 0.0)
640adb41caab5f958d39a3466968df0be65ef2b1045cristy        alpha=1.0;
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      beta=GetPseudoRandomValue(random_info);
64262faa60a11bc656bbeb1b418a95de40815a4490ccristy      gamma=sqrt(-2.0*log(alpha));
64355a91cddcdea3aa002893186a773e1704884a9dfcristy      sigma=gamma*cos((double) (2.0*MagickPI*beta));
64455a91cddcdea3aa002893186a773e1704884a9dfcristy      tau=gamma*sin((double) (2.0*MagickPI*beta));
6457118edf0993ccec017e96e2172e6ac672d3e24cdcristy      noise=(double) pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
6467118edf0993ccec017e96e2172e6ac672d3e24cdcristy        QuantumRange*TauGaussian*tau;
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case ImpulseNoise:
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (alpha < (SigmaImpulse/2.0))
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        noise=0.0;
65337c2407b40ceacf637731f133d9dbff27a39f669cristy      else
65437c2407b40ceacf637731f133d9dbff27a39f669cristy        if (alpha >= (1.0-(SigmaImpulse/2.0)))
65537c2407b40ceacf637731f133d9dbff27a39f669cristy          noise=(double) QuantumRange;
65637c2407b40ceacf637731f133d9dbff27a39f669cristy        else
65737c2407b40ceacf637731f133d9dbff27a39f669cristy          noise=(double) pixel;
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case LaplacianNoise:
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (alpha <= 0.5)
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6647118edf0993ccec017e96e2172e6ac672d3e24cdcristy          if (alpha <= MagickEpsilon)
665adb41caab5f958d39a3466968df0be65ef2b1045cristy            noise=(double) pixel-(double) QuantumRange;
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          else
66737c2407b40ceacf637731f133d9dbff27a39f669cristy            noise=(double) pixel+QuantumRange*SigmaLaplacian*
6687118edf0993ccec017e96e2172e6ac672d3e24cdcristy              log(2.0*alpha)+0.5;
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      beta=1.0-alpha;
6727118edf0993ccec017e96e2172e6ac672d3e24cdcristy      if (beta <= (0.5*MagickEpsilon))
673adb41caab5f958d39a3466968df0be65ef2b1045cristy        noise=(double) (pixel+QuantumRange);
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
6757118edf0993ccec017e96e2172e6ac672d3e24cdcristy        noise=(double) pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5;
6767118edf0993ccec017e96e2172e6ac672d3e24cdcristy      break;
6777118edf0993ccec017e96e2172e6ac672d3e24cdcristy    }
6787118edf0993ccec017e96e2172e6ac672d3e24cdcristy    case MultiplicativeGaussianNoise:
6797118edf0993ccec017e96e2172e6ac672d3e24cdcristy    {
6807118edf0993ccec017e96e2172e6ac672d3e24cdcristy      sigma=1.0;
6817118edf0993ccec017e96e2172e6ac672d3e24cdcristy      if (alpha > MagickEpsilon)
6827118edf0993ccec017e96e2172e6ac672d3e24cdcristy        sigma=sqrt(-2.0*log(alpha));
6837118edf0993ccec017e96e2172e6ac672d3e24cdcristy      beta=GetPseudoRandomValue(random_info);
6847118edf0993ccec017e96e2172e6ac672d3e24cdcristy      noise=(double) pixel+pixel*SigmaMultiplicativeGaussian*sigma*
6857118edf0993ccec017e96e2172e6ac672d3e24cdcristy        cos((double) (2.0*MagickPI*beta))/2.0;
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case PoissonNoise:
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
690adb41caab5f958d39a3466968df0be65ef2b1045cristy      double
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        poisson;
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
693bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      register ssize_t
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        i;
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6967118edf0993ccec017e96e2172e6ac672d3e24cdcristy      poisson=exp(-SigmaPoisson*QuantumScale*pixel);
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; alpha > poisson; i++)
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        beta=GetPseudoRandomValue(random_info);
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha*=beta;
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
7027118edf0993ccec017e96e2172e6ac672d3e24cdcristy      noise=(double) QuantumRange*i/SigmaPoisson;
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case RandomNoise:
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7072a42b1b23d5468cc276418f2cb7c786be39d7339cristy      noise=(double) QuantumRange*alpha;
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(noise);
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   G e t O p t i m a l K e r n e l W i d t h                                 %
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  filter.  Start with the minimum value of 3 pixels and walk out until we drop
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  below the threshold of one pixel numerical accuracy.
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GetOptimalKernelWidth method is:
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
731bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t GetOptimalKernelWidth(const double radius,
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        const double sigma)
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o width: Method GetOptimalKernelWidth returns the optimal width of
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      a convolution kernel.
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o radius: the radius of the Gaussian, in pixels, not counting the center
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      pixel.
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o sigma: the standard deviation of the Gaussian, in pixels.
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
7458ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
746e96405a0f45f803fb9c26f75e7bdee252437febbcristy  const double sigma)
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
748e96405a0f45f803fb9c26f75e7bdee252437febbcristy  double
749e96405a0f45f803fb9c26f75e7bdee252437febbcristy    alpha,
750e96405a0f45f803fb9c26f75e7bdee252437febbcristy    beta,
751e96405a0f45f803fb9c26f75e7bdee252437febbcristy    gamma,
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    normalize,
753e96405a0f45f803fb9c26f75e7bdee252437febbcristy    value;
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
755bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
75647e00508ba238041491b7e0daf628ae3f21ab91ecristy    i;
75747e00508ba238041491b7e0daf628ae3f21ab91ecristy
758bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
75947e00508ba238041491b7e0daf628ae3f21ab91ecristy    width;
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7619d314ff2c17a77996c05413c2013880387e50f0ecristy  ssize_t
7629d314ff2c17a77996c05413c2013880387e50f0ecristy    j;
7639d314ff2c17a77996c05413c2013880387e50f0ecristy
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
76547e00508ba238041491b7e0daf628ae3f21ab91ecristy  if (radius > MagickEpsilon)
766bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    return((size_t) (2.0*ceil(radius)+1.0));
767e96405a0f45f803fb9c26f75e7bdee252437febbcristy  gamma=fabs(sigma);
768e96405a0f45f803fb9c26f75e7bdee252437febbcristy  if (gamma <= MagickEpsilon)
769c106172cd6da00b6c8fd6a4c06efdd4aa32c7f06anthony    return(3UL);
770e96405a0f45f803fb9c26f75e7bdee252437febbcristy  alpha=1.0/(2.0*gamma*gamma);
77155a91cddcdea3aa002893186a773e1704884a9dfcristy  beta=(double) (1.0/(MagickSQ2PI*gamma));
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (width=5; ; )
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    normalize=0.0;
775bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    j=(ssize_t) width/2;
77647e00508ba238041491b7e0daf628ae3f21ab91ecristy    for (i=(-j); i <= j; i++)
777e96405a0f45f803fb9c26f75e7bdee252437febbcristy      normalize+=exp(-((double) (i*i))*alpha)*beta;
778e96405a0f45f803fb9c26f75e7bdee252437febbcristy    value=exp(-((double) (j*j))*alpha)*beta/normalize;
77920908dac8b2f15a9c0289728e57698bde5b74094cristy    if ((value < QuantumScale) || (value < MagickEpsilon))
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width+=2;
7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
783bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  return((size_t) (width-2));
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7868ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
787e96405a0f45f803fb9c26f75e7bdee252437febbcristy  const double sigma)
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
78947e00508ba238041491b7e0daf628ae3f21ab91ecristy  double
790e96405a0f45f803fb9c26f75e7bdee252437febbcristy    alpha,
791e96405a0f45f803fb9c26f75e7bdee252437febbcristy    beta,
792e96405a0f45f803fb9c26f75e7bdee252437febbcristy    gamma,
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    normalize,
794e96405a0f45f803fb9c26f75e7bdee252437febbcristy    value;
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7969d314ff2c17a77996c05413c2013880387e50f0ecristy  size_t
7979d314ff2c17a77996c05413c2013880387e50f0ecristy    width;
7989d314ff2c17a77996c05413c2013880387e50f0ecristy
799bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  ssize_t
80047e00508ba238041491b7e0daf628ae3f21ab91ecristy    j,
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    u,
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    v;
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
80547e00508ba238041491b7e0daf628ae3f21ab91ecristy  if (radius > MagickEpsilon)
806bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    return((size_t) (2.0*ceil(radius)+1.0));
807e96405a0f45f803fb9c26f75e7bdee252437febbcristy  gamma=fabs(sigma);
808e96405a0f45f803fb9c26f75e7bdee252437febbcristy  if (gamma <= MagickEpsilon)
809c106172cd6da00b6c8fd6a4c06efdd4aa32c7f06anthony    return(3UL);
810e96405a0f45f803fb9c26f75e7bdee252437febbcristy  alpha=1.0/(2.0*gamma*gamma);
81155a91cddcdea3aa002893186a773e1704884a9dfcristy  beta=(double) (1.0/(Magick2PI*gamma*gamma));
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (width=5; ; )
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    normalize=0.0;
815bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    j=(ssize_t) width/2;
81647e00508ba238041491b7e0daf628ae3f21ab91ecristy    for (v=(-j); v <= j; v++)
81747e00508ba238041491b7e0daf628ae3f21ab91ecristy      for (u=(-j); u <= j; u++)
818e96405a0f45f803fb9c26f75e7bdee252437febbcristy        normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
819e96405a0f45f803fb9c26f75e7bdee252437febbcristy    value=exp(-((double) (j*j))*alpha)*beta/normalize;
82020908dac8b2f15a9c0289728e57698bde5b74094cristy    if ((value < QuantumScale) || (value < MagickEpsilon))
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width+=2;
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
824bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  return((size_t) (width-2));
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8278ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate size_t  GetOptimalKernelWidth(const double radius,
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const double sigma)
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetOptimalKernelWidth1D(radius,sigma));
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
832