]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/gem.c
(no commit message)
[imagemagick] / MagickCore / gem.c
index 8f6a6ced0b35024db948ed28209188f1eead2f64..64608bc357b787c3ac8b966f821624ab5259a734 100644 (file)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   C o n v e r t H S B T o s R G B                                           %
+%   C o n v e r t H C L T o R G B                                             %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ConvertHSBTosRGB() transforms a (hue, saturation, brightness) to a (red,
+%  ConvertHCLToRGB() transforms a (hue, chroma, luma) to a (red, green,
+%  blue) triple.
+%
+%  The format of the ConvertHCLToRGBImage method is:
+%
+%      void ConvertHCLToRGB(const double hue,const double chroma,
+%        const double luma,double *red,double *green,double *blue)
+%
+%  A description of each parameter follows:
+%
+%    o hue, chroma, luma: A double value representing a
+%      component of the HCL color space.
+%
+%    o red, green, blue: A pointer to a pixel component of type Quantum.
+%
+*/
+MagickPrivate void ConvertHCLToRGB(const double hue,const double chroma,
+  const double luma,double *red,double *green,double *blue)
+{
+  double
+    b,
+    c,
+    g,
+    h,
+    m,
+    r,
+    x,
+    z;
+
+  /*
+    Convert HCL to RGB colorspace.
+  */
+  assert(red != (double *) NULL);
+  assert(green != (double *) NULL);
+  assert(blue != (double *) NULL);
+  h=6.0*hue;
+  c=chroma;
+  x=c*(1.0-fabs(fmod(h,2.0)-1.0));
+  r=0.0;
+  g=0.0;
+  b=0.0;
+  if ((0.0 <= h) && (h < 1.0))
+    {
+      r=c;
+      g=x;
+    }
+  else
+    if ((1.0 <= h) && (h < 2.0))
+      {
+        r=x;
+        g=c;
+      }
+    else
+      if ((2.0 <= h) && (h < 3.0))
+        {
+          g=c;
+          b=x;
+        }
+      else
+        if ((3.0 <= h) && (h < 4.0))
+          {
+            g=x;
+            b=c;
+          }
+        else
+          if ((4.0 <= h) && (h < 5.0))
+            {
+              r=x;
+              b=c;
+            }
+          else
+            if ((5.0 <= h) && (h < 6.0))
+              {
+                r=c;
+                b=x;
+              }
+  m=luma-(0.298839*r+0.586811*g+0.114350*b);
+  /*
+    Choose saturation strategy to clip it into the RGB cube; hue and luma are
+    preserved and chroma may be changed.
+  */
+  z=1.0;
+  if (m < 0.0)
+    {
+      z=luma/(luma-m);
+      m=0.0;
+    }
+  else
+    if ((m+c) > 1.0)
+      {
+        z=(1.0-luma)/(m+c-luma);
+        m=1.0-z*c;
+      }
+  *red=QuantumRange*(z*r+m);
+  *green=QuantumRange*(z*g+m);
+  *blue=QuantumRange*(z*b+m);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   C o n v e r t H S B T o R G B                                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
 %  green, blue) triple.
 %
-%  The format of the ConvertHSBTosRGBImage method is:
+%  The format of the ConvertHSBToRGBImage method is:
 %
-%      void ConvertHSBTosRGB(const double hue,const double saturation,
+%      void ConvertHSBToRGB(const double hue,const double saturation,
 %        const double brightness,double *red,double *green,double *blue)
 %
 %  A description of each parameter follows:
 %    o red, green, blue: A pointer to a pixel component of type Quantum.
 %
 */
-MagickPrivate void ConvertHSBTosRGB(const double hue,const double saturation,
+MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
   const double brightness,double *red,double *green,double *blue)
 {
   double
@@ -118,44 +227,44 @@ MagickPrivate void ConvertHSBTosRGB(const double hue,const double saturation,
     case 0:
     default:
     {
-      *red=QuantumRange*sRGBCompanding(brightness);
-      *green=QuantumRange*sRGBCompanding(t);
-      *blue=QuantumRange*sRGBCompanding(p);
+      *red=QuantumRange*brightness;
+      *green=QuantumRange*t;
+      *blue=QuantumRange*p;
       break;
     }
     case 1:
     {
-      *red=QuantumRange*sRGBCompanding(q);
-      *green=QuantumRange*sRGBCompanding(brightness);
-      *blue=QuantumRange*sRGBCompanding(p);
+      *red=QuantumRange*q;
+      *green=QuantumRange*brightness;
+      *blue=QuantumRange*p;
       break;
     }
     case 2:
     {
-      *red=QuantumRange*sRGBCompanding(p);
-      *green=QuantumRange*sRGBCompanding(brightness);
-      *blue=QuantumRange*sRGBCompanding(t);
+      *red=QuantumRange*p;
+      *green=QuantumRange*brightness;
+      *blue=QuantumRange*t;
       break;
     }
     case 3:
     {
-      *red=QuantumRange*sRGBCompanding(p);
-      *green=QuantumRange*sRGBCompanding(q);
-      *blue=QuantumRange*sRGBCompanding(brightness);
+      *red=QuantumRange*p;
+      *green=QuantumRange*q;
+      *blue=QuantumRange*brightness;
       break;
     }
     case 4:
     {
-      *red=QuantumRange*sRGBCompanding(t);
-      *green=QuantumRange*sRGBCompanding(p);
-      *blue=QuantumRange*sRGBCompanding(brightness);
+      *red=QuantumRange*t;
+      *green=QuantumRange*p;
+      *blue=QuantumRange*brightness;
       break;
     }
     case 5:
     {
-      *red=QuantumRange*sRGBCompanding(brightness);
-      *green=QuantumRange*sRGBCompanding(p);
-      *blue=QuantumRange*sRGBCompanding(q);
+      *red=QuantumRange*brightness;
+      *green=QuantumRange*p;
+      *blue=QuantumRange*q;
       break;
     }
   }
@@ -166,18 +275,18 @@ MagickPrivate void ConvertHSBTosRGB(const double hue,const double saturation,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   C o n v e r t H S L T o s R G B                                           %
+%   C o n v e r t H S L T o R G B                                             %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ConvertHSLTosRGB() transforms a (hue, saturation, lightness) to a (red,
+%  ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
 %  green, blue) triple.
 %
-%  The format of the ConvertHSLTosRGBImage method is:
+%  The format of the ConvertHSLToRGBImage method is:
 %
-%      void ConvertHSLTosRGB(const double hue,const double saturation,
+%      void ConvertHSLToRGB(const double hue,const double saturation,
 %        const double lightness,double *red,double *green,double *blue)
 %
 %  A description of each parameter follows:
@@ -189,7 +298,7 @@ MagickPrivate void ConvertHSBTosRGB(const double hue,const double saturation,
 %
 */
 
-static inline double ConvertHueTosRGB(double m1,double m2,double hue)
+static inline double ConvertHueToRGB(double m1,double m2,double hue)
 {
   if (hue < 0.0)
     hue+=1.0;
@@ -204,7 +313,7 @@ static inline double ConvertHueTosRGB(double m1,double m2,double hue)
   return(m1);
 }
 
-MagickExport void ConvertHSLTosRGB(const double hue,const double saturation,
+MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
   const double lightness,double *red,double *green,double *blue)
 {
   double
@@ -232,12 +341,12 @@ MagickExport void ConvertHSLTosRGB(const double hue,const double saturation,
   else
     m2=(lightness+saturation)-(lightness*saturation);
   m1=2.0*lightness-m2;
-  r=ConvertHueTosRGB(m1,m2,hue+1.0/3.0);
-  g=ConvertHueTosRGB(m1,m2,hue);
-  b=ConvertHueTosRGB(m1,m2,hue-1.0/3.0);
-  *red=QuantumRange*sRGBCompanding(r);
-  *green=QuantumRange*sRGBCompanding(g);
-  *blue=QuantumRange*sRGBCompanding(b);
+  r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
+  g=ConvertHueToRGB(m1,m2,hue);
+  b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
+  *red=QuantumRange*r;
+  *green=QuantumRange*g;
+  *blue=QuantumRange*b;
 }
 \f
 /*
@@ -245,18 +354,18 @@ MagickExport void ConvertHSLTosRGB(const double hue,const double saturation,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   C o n v e r t H W B T o s R G B                                           %
+%   C o n v e r t H W B T o R G B                                             %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ConvertHWBTosRGB() transforms a (hue, whiteness, blackness) to a (red, green,
+%  ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
 %  blue) triple.
 %
-%  The format of the ConvertHWBTosRGBImage method is:
+%  The format of the ConvertHWBToRGBImage method is:
 %
-%      void ConvertHWBTosRGB(const double hue,const double whiteness,
+%      void ConvertHWBToRGB(const double hue,const double whiteness,
 %        const double blackness,double *red,double *green,double *blue)
 %
 %  A description of each parameter follows:
@@ -267,7 +376,7 @@ MagickExport void ConvertHSLTosRGB(const double hue,const double saturation,
 %    o red, green, blue: A pointer to a pixel component of type Quantum.
 %
 */
-MagickPrivate void ConvertHWBTosRGB(const double hue,const double whiteness,
+MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
   const double blackness,double *red,double *green,double *blue)
 {
   double
@@ -290,9 +399,9 @@ MagickPrivate void ConvertHWBTosRGB(const double hue,const double whiteness,
   v=1.0-blackness;
   if (hue == -1.0)
     {
-      *red=QuantumRange*sRGBCompanding(v);
-      *green=QuantumRange*sRGBCompanding(v);
-      *blue=QuantumRange*sRGBCompanding(v);
+      *red=QuantumRange*v;
+      *green=QuantumRange*v;
+      *blue=QuantumRange*v;
       return;
     }
   i=(ssize_t) floor(6.0*hue);
@@ -311,9 +420,9 @@ MagickPrivate void ConvertHWBTosRGB(const double hue,const double whiteness,
     case 4: r=n; g=whiteness; b=v; break;
     case 5: r=v; g=whiteness; b=n; break;
   }
-  *red=QuantumRange*sRGBCompanding(r);
-  *green=QuantumRange*sRGBCompanding(g);
-  *blue=QuantumRange*sRGBCompanding(b);
+  *red=QuantumRange*r;
+  *green=QuantumRange*g;
+  *blue=QuantumRange*b;
 }
 \f
 /*
@@ -321,18 +430,100 @@ MagickPrivate void ConvertHWBTosRGB(const double hue,const double whiteness,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   C o n v e r t s R G B T o H S B                                           %
+%   C o n v e r t R G B T o H C L                                             %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ConvertsRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
+%  ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
+%  luma) triple.
+%
+%  The format of the ConvertRGBToHCL method is:
+%
+%      void ConvertRGBToHCL(const double red,const double green,
+%        const double blue,double *hue,double *chroma,double *luma)
+%
+%  A description of each parameter follows:
+%
+%    o red, green, blue: A Quantum value representing the red, green, and
+%      blue component of a pixel.
+%
+%    o hue, chroma, luma: A pointer to a double value representing a
+%      component of the HCL color space.
+%
+*/
+
+static inline double MagickMax(const double x,const double y)
+{
+  if (x > y)
+    return(x);
+  return(y);
+}
+
+static inline double MagickMin(const double x,const double y)
+{
+  if (x < y)
+    return(x);
+  return(y);
+}
+
+MagickPrivate void ConvertRGBToHCL(const double red,const double green,
+  const double blue,double *hue,double *chroma,double *luma)
+{
+  double
+    b,
+    c,
+    g,
+    h,
+    max,
+    r;
+
+  /*
+    Convert RGB to HCL colorspace.
+  */
+  assert(hue != (double *) NULL);
+  assert(chroma != (double *) NULL);
+  assert(luma != (double *) NULL);
+  r=red;
+  g=green;
+  b=blue;
+  max=MagickMax(r,MagickMax(g,b));
+  c=max-(double) MagickMin(r,MagickMin(g,b));
+  h=0.0;
+  if (c == 0.0)
+    h=0.0;
+  else
+    if (red == max)
+      h=fmod((g-b)/c+6.0,6.0);
+    else
+      if (green == max)
+        h=((b-r)/c)+2.0;
+      else
+        if (blue == max)
+          h=((r-g)/c)+4.0;
+  *hue=(h/6.0);
+  *chroma=QuantumScale*c;
+  *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   C o n v e r t R G B T o H S B                                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
 %  brightness) triple.
 %
-%  The format of the ConvertsRGBToHSB method is:
+%  The format of the ConvertRGBToHSB method is:
 %
-%      void ConvertsRGBToHSB(const double red,const double green,
+%      void ConvertRGBToHSB(const double red,const double green,
 %        const double blue,double *hue,double *saturation,double *brightness)
 %
 %  A description of each parameter follows:
@@ -344,7 +535,7 @@ MagickPrivate void ConvertHWBTosRGB(const double hue,const double whiteness,
 %      component of the HSB color space.
 %
 */
-MagickPrivate void ConvertsRGBToHSB(const double red,const double green,
+MagickPrivate void ConvertRGBToHSB(const double red,const double green,
   const double blue,double *hue,double *saturation,double *brightness)
 {
   double
@@ -364,9 +555,9 @@ MagickPrivate void ConvertsRGBToHSB(const double red,const double green,
   *hue=0.0;
   *saturation=0.0;
   *brightness=0.0;
-  r=QuantumRange*sRGBDecompanding(QuantumScale*red);
-  g=QuantumRange*sRGBDecompanding(QuantumScale*green);
-  b=QuantumRange*sRGBDecompanding(QuantumScale*blue);
+  r=red;
+  g=green;
+  b=blue;
   min=r < g ? r : g;
   if (b < min)
     min=b;
@@ -397,18 +588,18 @@ MagickPrivate void ConvertsRGBToHSB(const double red,const double green,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   C o n v e r t s R G B T o H S L                                           %
+%   C o n v e r t R G B T o H S L                                             %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ConvertsRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
+%  ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
 %  lightness) triple.
 %
-%  The format of the ConvertsRGBToHSL method is:
+%  The format of the ConvertRGBToHSL method is:
 %
-%      void ConvertsRGBToHSL(const double red,const double green,
+%      void ConvertRGBToHSL(const double red,const double green,
 %        const double blue,double *hue,double *saturation,double *lightness)
 %
 %  A description of each parameter follows:
@@ -420,22 +611,7 @@ MagickPrivate void ConvertsRGBToHSB(const double red,const double green,
 %      component of the HSL color space.
 %
 */
-
-static inline double MagickMax(const double x,const double y)
-{
-  if (x > y)
-    return(x);
-  return(y);
-}
-
-static inline double MagickMin(const double x,const double y)
-{
-  if (x < y)
-    return(x);
-  return(y);
-}
-
-MagickExport void ConvertsRGBToHSL(const double red,const double green,
+MagickExport void ConvertRGBToHSL(const double red,const double green,
   const double blue,double *hue,double *saturation,double *lightness)
 {
   double
@@ -452,9 +628,9 @@ MagickExport void ConvertsRGBToHSL(const double red,const double green,
   assert(hue != (double *) NULL);
   assert(saturation != (double *) NULL);
   assert(lightness != (double *) NULL);
-  r=sRGBDecompanding(QuantumScale*red);
-  g=sRGBDecompanding(QuantumScale*green);
-  b=sRGBDecompanding(QuantumScale*blue);
+  r=QuantumScale*red;
+  g=QuantumScale*green;
+  b=QuantumScale*blue;
   max=MagickMax(r,MagickMax(g,b));
   min=MagickMin(r,MagickMin(g,b));
   *lightness=(double) ((min+max)/2.0);
@@ -490,18 +666,18 @@ MagickExport void ConvertsRGBToHSL(const double red,const double green,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   C o n v e r t s R G B T o H W B                                           %
+%   C o n v e r t R G B T o H W B                                             %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ConvertsRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
+%  ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
 %  blackness) triple.
 %
-%  The format of the ConvertsRGBToHWB method is:
+%  The format of the ConvertRGBToHWB method is:
 %
-%      void ConvertsRGBToHWB(const double red,const double green,
+%      void ConvertRGBToHWB(const double red,const double green,
 %        const double blue,double *hue,double *whiteness,double *blackness)
 %
 %  A description of each parameter follows:
@@ -513,7 +689,7 @@ MagickExport void ConvertsRGBToHSL(const double red,const double green,
 %      component of the HWB color space.
 %
 */
-MagickPrivate void ConvertsRGBToHWB(const double red,const double green,
+MagickPrivate void ConvertRGBToHWB(const double red,const double green,
   const double blue,double *hue,double *whiteness,double *blackness)
 {
   double
@@ -531,9 +707,9 @@ MagickPrivate void ConvertsRGBToHWB(const double red,const double green,
   assert(hue != (double *) NULL);
   assert(whiteness != (double *) NULL);
   assert(blackness != (double *) NULL);
-  r=QuantumRange*sRGBDecompanding(QuantumScale*red);
-  g=QuantumRange*sRGBDecompanding(QuantumScale*green);
-  b=QuantumRange*sRGBDecompanding(QuantumScale*blue);
+  r=red;
+  g=green;
+  b=blue;
   w=MagickMin(r,MagickMin(g,b));
   v=MagickMax(r,MagickMax(g,b));
   *blackness=1.0-QuantumScale*v;
@@ -619,6 +795,7 @@ MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
 #define SigmaLaplacian (attenuate*0.0390625)
 #define SigmaMultiplicativeGaussian  (attenuate*0.5)
 #define SigmaPoisson  (attenuate*12.5)
+#define SigmaRandom  (attenuate)
 #define TauGaussian  (attenuate*0.078125)
 
   double
@@ -670,8 +847,8 @@ MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
           if (alpha <= MagickEpsilon)
             noise=(double) (pixel-QuantumRange);
           else
-            noise=(double) (pixel+QuantumRange*SigmaLaplacian*
-              log(2.0*alpha)+0.5);
+            noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
+              0.5);
           break;
         }
       beta=1.0-alpha;
@@ -710,7 +887,7 @@ MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
     }
     case RandomNoise:
     {
-      noise=(double) (QuantumRange*alpha);
+      noise=(double) (QuantumRange*SigmaRandom*alpha);
       break;
     }
   }
@@ -774,7 +951,7 @@ MagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
   if (gamma <= MagickEpsilon)
     return(3UL);
   alpha=MagickEpsilonReciprocal(2.0*gamma*gamma);
-  beta=(double) MagickEpsilonReciprocal((MagickRealType) MagickSQ2PI*gamma);
+  beta=(double) MagickEpsilonReciprocal((double) MagickSQ2PI*gamma);
   for (width=5; ; )
   {
     normalize=0.0;
@@ -814,7 +991,7 @@ MagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
   if (gamma <= MagickEpsilon)
     return(3UL);
   alpha=MagickEpsilonReciprocal(2.0*gamma*gamma);
-  beta=(double) MagickEpsilonReciprocal((MagickRealType) Magick2PI*gamma*gamma);
+  beta=(double) MagickEpsilonReciprocal((double) Magick2PI*gamma*gamma);
   for (width=5; ; )
   {
     normalize=0.0;