]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/gem.c
(no commit message)
[imagemagick] / MagickCore / gem.c
index 7cabf3fb47cffa60a38462d5e904465e6c27056c..7085742e1137a56033a9274e6f1aeaa7c01935e0 100644 (file)
 %                    Graphic Gems - Graphic Support Methods                   %
 %                                                                             %
 %                               Software Design                               %
-%                                 John Cristy                                 %
+%                                    Cristy                                   %
 %                                 August 1996                                 %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
 %
 %  A description of each parameter follows:
 %
-%    o hue, chroma, luma: A double value representing a
-%      component of the HCL color space.
+%    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;
+
+  /*
+    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);
+  *red=QuantumRange*(r+m);
+  *green=QuantumRange*(g+m);
+  *blue=QuantumRange*(b+m);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   C o n v e r t H C L p T o R G B                                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ConvertHCLpToRGB() transforms a (hue, chroma, luma) to a (red, green,
+%  blue) triple.  Since HCL colorspace is wider than RGB, we instead choose a
+%  saturation strategy to project it on the RGB cube.
+%
+%  The format of the ConvertHCLpToRGBImage method is:
+%
+%      void ConvertHCLpToRGB(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 componenet of the
+%      HCLp color space.
+%
+%    o red, green, blue: A pointer to a pixel component of type Quantum.
+%
+*/
+MagickPrivate void ConvertHCLpToRGB(const double hue,const double chroma,
+  const double luma,double *red,double *green,double *blue)
 {
   double
     b,
@@ -99,7 +192,7 @@ MagickPrivate void ConvertHCLToRGB(const double hue,const double chroma,
     z;
 
   /*
-    Convert HCL to RGB colorspace.
+    Convert HCLp to RGB colorspace.
   */
   assert(red != (double *) NULL);
   assert(green != (double *) NULL);
@@ -145,7 +238,7 @@ MagickPrivate void ConvertHCLToRGB(const double hue,const double chroma,
                 r=c;
                 b=x;
               }
-  m=luma-(0.298839f*r+0.586811f*g+0.114350f*b);
+  m=luma-(0.298839*r+0.586811*g+0.114350*b);
   z=1.0;
   if (m < 0.0)
     {
@@ -297,7 +390,10 @@ MagickPrivate void ConvertHSIToRGB(const double hue,const double saturation,
   const double intensity,double *red,double *green,double *blue)
 {
   double
-    h;
+    b,
+    g,
+    h,
+    r;
 
   /*
     Convert HSI to RGB colorspace.
@@ -309,31 +405,31 @@ MagickPrivate void ConvertHSIToRGB(const double hue,const double saturation,
   h-=360.0*floor(h/360.0);
   if (h < 120.0)
     {
-      *blue=intensity*(1.0-saturation);
-      *red=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
+      b=intensity*(1.0-saturation);
+      r=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
         (MagickPI/180.0)));
-      *green=3.0*intensity-*red-*blue;
+      g=3.0*intensity-r-b;
     }
   else
     if (h < 240.0)
       {
         h-=120.0;
-        *red=intensity*(1.0-saturation);
-        *green=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
+        r=intensity*(1.0-saturation);
+        g=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
           (MagickPI/180.0)));
-        *blue=3.0*intensity-*red-*green;
+        b=3.0*intensity-r-g;
       }
     else
       {
         h-=240.0;
-        *green=intensity*(1.0-saturation);
-        *blue=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
+        g=intensity*(1.0-saturation);
+        b=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
           (MagickPI/180.0)));
-        *red=3.0*intensity-*green-*blue;
+        r=3.0*intensity-g-b;
       }
-  *red*=QuantumRange;
-  *green*=QuantumRange;
-  *blue*=QuantumRange;
+  *red=QuantumRange*r;
+  *green=QuantumRange*g;
+  *blue=QuantumRange*b;
 }
 \f
 /*
@@ -644,15 +740,18 @@ MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
 %    o red, green, blue: A pointer to a pixel component of type Quantum.
 %
 */
+
+static inline void ConvertLCHabToXYZ(const double luma,const double chroma,
+  const double hue,double *X,double *Y,double *Z)
+{
+  ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
+    sin(hue*MagickPI/180.0),X,Y,Z);
+}
+
 MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
   const double hue,double *red,double *green,double *blue)
 {
   double
-    a,
-    b,
-    C,
-    H,
-    L,
     X,
     Y,
     Z;
@@ -663,13 +762,7 @@ MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
   assert(red != (double *) NULL);
   assert(green != (double *) NULL);
   assert(blue != (double *) NULL);
-  L=luma;
-  C=chroma;
-  H=hue;
-  a=C*cos(360.0*H*MagickPI/180.0);
-  b=C*sin(360.0*H*MagickPI/180.0);
-  ConvertLabToXYZ(((116.0*L)-16.0)/100.0,(500.0*a)/255.0+0.5,(200.0*b)/255.0+
-    0.5,&X,&Y,&Z);
+  ConvertLCHabToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z);
   ConvertXYZToRGB(X,Y,Z,red,green,blue);
 }
 \f
@@ -700,15 +793,18 @@ MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
 %    o red, green, blue: A pointer to a pixel component of type Quantum.
 %
 */
+
+static inline void ConvertLCHuvToXYZ(const double luma,const double chroma,
+  const double hue,double *X,double *Y,double *Z)
+{
+  ConvertLuvToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
+    sin(hue*MagickPI/180.0),X,Y,Z);
+}
+
 MagickPrivate void ConvertLCHuvToRGB(const double luma,const double chroma,
   const double hue,double *red,double *green,double *blue)
 {
   double
-    C,
-    H,
-    L,
-    u,
-    v,
     X,
     Y,
     Z;
@@ -719,12 +815,7 @@ MagickPrivate void ConvertLCHuvToRGB(const double luma,const double chroma,
   assert(red != (double *) NULL);
   assert(green != (double *) NULL);
   assert(blue != (double *) NULL);
-  L=luma;
-  C=chroma;
-  H=hue;
-  u=C*cos(360.0*H*MagickPI/180.0);
-  v=C*sin(360.0*H*MagickPI/180.0);
-  ConvertLuvToXYZ(L,(u+1.34)/3.54,(v+1.4)/2.62,&X,&Y,&Z);
+  ConvertLCHuvToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z);
   ConvertXYZToRGB(X,Y,Z,red,green,blue);
 }
 \f
@@ -807,7 +898,74 @@ MagickPrivate void ConvertRGBToHCL(const double red,const double green,
           h=((r-g)/c)+4.0;
   *hue=(h/6.0);
   *chroma=QuantumScale*c;
-  *luma=QuantumScale*(0.298839f*r+0.586811f*g+0.114350f*b);
+  *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 C L p                                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ConvertRGBToHCLp() transforms a (red, green, blue) to a (hue, chroma,
+%  luma) triple.
+%
+%  The format of the ConvertRGBToHCLp method is:
+%
+%      void ConvertRGBToHCLp(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.
+%
+*/
+MagickPrivate void ConvertRGBToHCLp(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
 /*
@@ -937,7 +1095,7 @@ MagickPrivate void ConvertRGBToHSI(const double red,const double green,
   *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
     QuantumScale*blue))/(*intensity);
   alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
-  beta=0.866025403784439*(QuantumScale*green-QuantumScale*blue);
+  beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue);
   *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
   if (*hue < 0.0)
     *hue+=1.0;
@@ -1175,15 +1333,25 @@ MagickPrivate void ConvertRGBToHWB(const double red,const double green,
 %      component of the LCH color space.
 %
 */
+
+static inline void ConvertXYZToLCHab(const double X,const double Y,
+  const double Z,double *luma,double *chroma,double *hue)
+{
+  double
+    a,
+    b;
+
+  ConvertXYZToLab(X,Y,Z,luma,&a,&b);
+  *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5))/255.0+0.5;
+  *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI/360.0;
+  if (*hue < 0.0)
+    *hue+=1.0;
+}
+
 MagickPrivate void ConvertRGBToLCHab(const double red,const double green,
   const double blue,double *luma,double *chroma,double *hue)
 {
   double
-    a,
-    b,
-    C,
-    H,
-    L,
     X,
     Y,
     Z;
@@ -1195,16 +1363,7 @@ MagickPrivate void ConvertRGBToLCHab(const double red,const double green,
   assert(chroma != (double *) NULL);
   assert(hue != (double *) NULL);
   ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
-  ConvertXYZToLab(X,Y,Z,&L,&a,&b);
-  C=hypot(255.0*(a-0.5)/500.0,255.0*(b-0.5)/200.0);
-  H=180.0*atan2(255.0*(b-0.5)/200.0,255.0*(a-0.5)/500.0)/MagickPI/360.0;
-  if (H < 0.0)
-    H+=1.0;
-  if (H >= 1.0)
-    H-=1.0;
-  *luma=(100.0*L+16.0)/116.0;
-  *chroma=C;
-  *hue=H;
+  ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue);
 }
 \f
 /*
@@ -1235,15 +1394,25 @@ MagickPrivate void ConvertRGBToLCHab(const double red,const double green,
 %      component of the LCHuv color space.
 %
 */
+
+static inline void ConvertXYZToLCHuv(const double X,const double Y,
+  const double Z,double *luma,double *chroma,double *hue)
+{
+  double
+    u,
+    v;
+
+  ConvertXYZToLuv(X,Y,Z,luma,&u,&v);
+  *chroma=hypot(354.0*u-134.0,262.0*v-140.0)/255.0+0.5;
+  *hue=180.0*atan2(262.0*v-140.0,354.0*u-134.0)/MagickPI/360.0;
+  if (*hue < 0.0)
+    *hue+=1.0;
+}
+
 MagickPrivate void ConvertRGBToLCHuv(const double red,const double green,
   const double blue,double *luma,double *chroma,double *hue)
 {
   double
-    C,
-    H,
-    L,
-    u,
-    v,
     X,
     Y,
     Z;
@@ -1255,16 +1424,7 @@ MagickPrivate void ConvertRGBToLCHuv(const double red,const double green,
   assert(chroma != (double *) NULL);
   assert(hue != (double *) NULL);
   ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
-  ConvertXYZToLuv(X,Y,Z,&L,&u,&v);
-  C=hypot(3.54*u-1.34,2.62*v-1.4);
-  H=180.0*atan2(2.62*v-1.4,3.54*u-1.34)/MagickPI/360.0;
-  if (H < 0.0)
-    H+=1.0;
-  if (H >= 1.0)
-    H-=1.0;
-  *luma=L;
-  *chroma=C;
-  *hue=H;
+  ConvertXYZToLCHuv(X,Y,Z,luma,chroma,hue);
 }
 \f
 /*