]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Fri, 5 Apr 2013 13:35:37 +0000 (13:35 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Fri, 5 Apr 2013 13:35:37 +0000 (13:35 +0000)
MagickCore/colorspace.c
MagickCore/colorspace.h
MagickCore/enhance.c
MagickCore/gem-private.h
MagickCore/gem.c
MagickCore/option.c

index 75d5a5ec9635631e9e6ec226fd6a6d33c55d5155..b9f237eed1e480c561e6046023426cb0ba461ce4 100644 (file)
@@ -137,27 +137,6 @@ static inline void ConvertXYZToLMS(const double x,const double y,
   *S=QuantumRange*s;
 }
 
-static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
-  double *L,double *u,double *v)
-{
-  double
-    alpha;
-
-  assert(L != (double *) NULL);
-  assert(u != (double *) NULL);
-  assert(v != (double *) NULL);
-  if ((Y/D65Y) > CIEEpsilon)
-    *L=(double) (116.0f*pow(Y/D65Y,1.0/3.0)-16.0f);
-  else
-    *L=CIEK*(Y/D65Y);
-  alpha=PerceptibleReciprocal(X+15.0f*Y+3.0f*Z);
-  *u=13.0f*(*L)*((4.0f*alpha*X)-(4.0f*D65X/(D65X+15.0f*D65Y+3.0f*D65Z)));
-  *v=13.0f*(*L)*((9.0f*alpha*Y)-(9.0f*D65Y/(D65X+15.0f*D65Y+3.0f*D65Z)));
-  *L/=100.0f;
-  *u=(*u+134.0f)/354.0f;
-  *v=(*v+140.0f)/262.0f;
-}
-
 static MagickBooleanType sRGBTransformImage(Image *image,
   const ColorspaceType colorspace,ExceptionInfo *exception)
 {
@@ -709,10 +688,76 @@ static MagickBooleanType sRGBTransformImage(Image *image,
         return(MagickFalse);
       return(status);
     }
+    case LCHabColorspace:
+    {
+      /*
+        Transform image from sRGB to LCHab.
+      */
+      if (image->storage_class == PseudoClass)
+        {
+          if (SyncImage(image,exception) == MagickFalse)
+            return(MagickFalse);
+          if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
+            return(MagickFalse);
+        }
+      image_view=AcquireAuthenticCacheView(image,exception);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+      #pragma omp parallel for schedule(static,4) shared(status) \
+        magick_threads(image,image,image->rows,1)
+#endif
+      for (y=0; y < (ssize_t) image->rows; y++)
+      {
+        MagickBooleanType
+          sync;
+
+        register ssize_t
+          x;
+
+        register Quantum
+          *restrict q;
+
+        if (status == MagickFalse)
+          continue;
+        q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
+          exception);
+        if (q == (Quantum *) NULL)
+          {
+            status=MagickFalse;
+            continue;
+          }
+        for (x=0; x < (ssize_t) image->columns; x++)
+        {
+          double
+            blue,
+            chroma,
+            green,
+            hue,
+            luma,
+            red;
+
+          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
+          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
+          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
+          ConvertRGBToLCHab(red,green,blue,&luma,&chroma,&hue);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*luma),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*chroma),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*hue),q);
+          q+=GetPixelChannels(image);
+        }
+        sync=SyncCacheViewAuthenticPixels(image_view,exception);
+        if (sync == MagickFalse)
+          status=MagickFalse;
+      }
+      image_view=DestroyCacheView(image_view);
+      if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
+        return(MagickFalse);
+      return(status);
+    }
     case LCHColorspace:
+    case LCHuvColorspace:
     {
       /*
-        Transform image from sRGB to LCH.
+        Transform image from sRGB to LCHuv.
       */
       if (image->storage_class == PseudoClass)
         {
@@ -759,7 +804,7 @@ static MagickBooleanType sRGBTransformImage(Image *image,
           red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
           green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
           blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          ConvertRGBToLCH(red,green,blue,&luma,&chroma,&hue);
+          ConvertRGBToLCHuv(red,green,blue,&luma,&chroma,&hue);
           SetPixelRed(image,ClampToQuantum(QuantumRange*luma),q);
           SetPixelGreen(image,ClampToQuantum(QuantumRange*chroma),q);
           SetPixelBlue(image,ClampToQuantum(QuantumRange*hue),q);
@@ -1729,24 +1774,6 @@ static inline void ConvertLMSToXYZ(const double L,const double M,const double S,
   *Z=(-0.009627608738429)*l-0.005698031216113*m+1.015325639954543*s;
 }
 
-static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
-  double *X,double *Y,double *Z)
-{
-  assert(X != (double *) NULL);
-  assert(Y != (double *) NULL);
-  assert(Z != (double *) NULL);
-  if ((100.0f*L) > (CIEK*CIEEpsilon))
-    *Y=(double) pow(((100.0*L)+16.0)/116.0,3.0);
-  else
-    *Y=(100.0f*L)/CIEK;
-  *X=((*Y*((39.0f*(100.0f*L)/((262.0f*v-140.0f)+13.0f*(100.0f*L)*(9.0f*D65Y/
-    (D65X+15.0f*D65Y+3.0f*D65Z))))-5.0f))+5.0f*(*Y))/((((52.0f*(100.0f*L)/
-    ((354.0f*u-134.0f)+13.0f*(100.0f*L)*(4.0f*D65X/(D65X+15.0f*D65Y+3.0f*
-    D65Z))))-1.0f)/3.0f)-(-1.0f/3.0f));
-  *Z=(*X*(((52.0f*(100.0f*L)/((354.0f*u-134.0f)+13.0f*(100.0f*L)*(4.0f*D65X/
-    (D65X+15.0f*D65Y+3.0f*D65Z))))-1.0f)/3.0f))-5.0f*(*Y);
-}
-
 static inline ssize_t RoundToYCC(const double value)
 {
   if (value <= 0.0f)
@@ -2602,7 +2629,7 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           luma=(double) (QuantumScale*GetPixelRed(image,q));
           chroma=(double) (QuantumScale*GetPixelGreen(image,q));
           hue=(double) (QuantumScale*GetPixelBlue(image,q));
-          ConvertLCHToRGB(luma,chroma,hue,&red,&green,&blue);
+          ConvertLCHabToRGB(luma,chroma,hue,&red,&green,&blue);
           SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
           SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
           SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),q);
index fc7e9a83971f2b4e0f8d6ed15ba945ab33ebba2d..625480477562fccce19ce76ef91f28572ed683e8 100644 (file)
@@ -34,6 +34,8 @@ typedef enum
   HWBColorspace,
   LabColorspace,
   LCHColorspace,
+  LCHabColorspace,
+  LCHuvColorspace,
   LogColorspace,
   LMSColorspace,
   LuvColorspace,
index 4c873f40b192cb4a741195520ee5094effd514e9..54f5f08e58786be7ef750bf6772b9002a4d54e88 100644 (file)
@@ -2966,7 +2966,7 @@ static inline void ModulateLCH(const double percent_luma,
   /*
     Increase or decrease color luma, chroma, or hue.
   */
-  ConvertRGBToLCH(*red,*green,*blue,&luma,&chroma,&hue);
+  ConvertRGBToLCHuv(*red,*green,*blue,&luma,&chroma,&hue);
   luma*=0.01*percent_luma;
   chroma*=0.01*percent_chroma;
   hue+=0.5*(0.01*percent_hue-1.0);
@@ -2974,7 +2974,7 @@ static inline void ModulateLCH(const double percent_luma,
     hue+=1.0;
   while (hue >= 1.0)
     hue-=1.0;
-  ConvertLCHToRGB(luma,chroma,hue,red,green,blue);
+  ConvertLCHuvToRGB(luma,chroma,hue,red,green,blue);
 }
 
 MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
index d51e7c9ba388f146de30a8788d23fef32bdfccd3..f2f844318804b751a8f54379d63d006beaa87fcc 100644 (file)
@@ -22,6 +22,8 @@
 extern "C" {
 #endif
 
+#include "MagickCore/pixel-private.h"
+
 #define D65X  (0.950456f)
 #define D65Y  (1.0f)
 #define D65Z  (1.088754f)
@@ -44,7 +46,9 @@ extern MagickPrivate void
     double *),
   ConvertHWBToRGB(const double,const double,const double,double *,double *,
     double *),
-  ConvertLCHToRGB(const double,const double,const double,double *,double *,
+  ConvertLCHabToRGB(const double,const double,const double,double *,double *,
+    double *),
+  ConvertLCHuvToRGB(const double,const double,const double,double *,double *,
     double *),
   ConvertRGBToHCL(const double,const double,const double,double *,double *,
     double *),
@@ -52,7 +56,9 @@ extern MagickPrivate void
     double *),
   ConvertRGBToHWB(const double,const double,const double,double *,double *,
     double *),
-  ConvertRGBToLCH(const double,const double,const double,double *,double *,
+  ConvertRGBToLCHab(const double,const double,const double,double *,double *,
+    double *),
+  ConvertRGBToLCHuv(const double,const double,const double,double *,double *,
     double *);
 
 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
@@ -86,6 +92,24 @@ static inline void ConvertLabToXYZ(const double L,const double a,const double b,
   *Z=D65Z*z;
 }
 
+static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
+  double *X,double *Y,double *Z)
+{
+  assert(X != (double *) NULL);
+  assert(Y != (double *) NULL);
+  assert(Z != (double *) NULL);
+  if ((100.0f*L) > (CIEK*CIEEpsilon))
+    *Y=(double) pow(((100.0*L)+16.0)/116.0,3.0);
+  else
+    *Y=(100.0f*L)/CIEK;
+  *X=((*Y*((39.0f*(100.0f*L)/((262.0f*v-140.0f)+13.0f*(100.0f*L)*(9.0f*D65Y/
+    (D65X+15.0f*D65Y+3.0f*D65Z))))-5.0f))+5.0f*(*Y))/((((52.0f*(100.0f*L)/
+    ((354.0f*u-134.0f)+13.0f*(100.0f*L)*(4.0f*D65X/(D65X+15.0f*D65Y+3.0f*
+    D65Z))))-1.0f)/3.0f)-(-1.0f/3.0f));
+  *Z=(*X*(((52.0f*(100.0f*L)/((354.0f*u-134.0f)+13.0f*(100.0f*L)*(4.0f*D65X/
+    (D65X+15.0f*D65Y+3.0f*D65Z))))-1.0f)/3.0f))-5.0f*(*Y);
+}
+
 static inline void ConvertRGBToXYZ(const double red,const double green,
   const double blue,double *X,double *Y,double *Z)
 {
@@ -132,6 +156,27 @@ static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
   *b=(200.0f*(y-z))/255.0f+0.5f;
 }
 
+static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
+  double *L,double *u,double *v)
+{
+  double
+    alpha;
+
+  assert(L != (double *) NULL);
+  assert(u != (double *) NULL);
+  assert(v != (double *) NULL);
+  if ((Y/D65Y) > CIEEpsilon)
+    *L=(double) (116.0f*pow(Y/D65Y,1.0/3.0)-16.0f);
+  else
+    *L=CIEK*(Y/D65Y);
+  alpha=PerceptibleReciprocal(X+15.0f*Y+3.0f*Z);
+  *u=13.0f*(*L)*((4.0f*alpha*X)-(4.0f*D65X/(D65X+15.0f*D65Y+3.0f*D65Z)));
+  *v=13.0f*(*L)*((9.0f*alpha*Y)-(9.0f*D65Y/(D65X+15.0f*D65Y+3.0f*D65Z)));
+  *L/=100.0f;
+  *u=(*u+134.0f)/354.0f;
+  *v=(*v+140.0f)/262.0f;
+}
+
 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
   double *red,double *green,double *blue)
 {
index 821cd17c0be6308a1bbb190aaeb14b431a8a6197..85f30ffb49a525e18e9cd2b9161fa4e6c9e3e403 100644 (file)
@@ -413,29 +413,29 @@ MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   C o n v e r t L C H T o R G B                                             %
+%   C o n v e r t L C H a b T o R G B                                         %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ConvertLCHToRGB() transforms a (luma, chroma, hue) to a (red, green,
+%  ConvertLCHabToRGB() transforms a (luma, chroma, hue) to a (red, green,
 %  blue) triple.
 %
-%  The format of the ConvertLCHToRGBImage method is:
+%  The format of the ConvertLCHabToRGBImage method is:
 %
-%      void ConvertLCHToRGB(const double luma,const double chroma,
+%      void ConvertLCHabToRGB(const double luma,const double chroma,
 %        const double hue,double *red,double *green,double *blue)
 %
 %  A description of each parameter follows:
 %
-%    o luma, chroma, hue: A double value representing a
-%      component of the LCH color space.
+%    o luma, chroma, hue: A double value representing a component of the
+%      LCHab color space.
 %
 %    o red, green, blue: A pointer to a pixel component of type Quantum.
 %
 */
-MagickPrivate void ConvertLCHToRGB(const double luma,const double chroma,
+MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
   const double hue,double *red,double *green,double *blue)
 {
   double
@@ -449,7 +449,7 @@ MagickPrivate void ConvertLCHToRGB(const double luma,const double chroma,
     Z;
 
   /*
-    Convert LCH to RGB colorspace.
+    Convert LCHab to RGB colorspace.
   */
   assert(red != (double *) NULL);
   assert(green != (double *) NULL);
@@ -468,6 +468,61 @@ MagickPrivate void ConvertLCHToRGB(const double luma,const double chroma,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   C o n v e r t L C H u v T o R G B                                         %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ConvertLCHuvToRGB() transforms a (luma, chroma, hue) to a (red, green,
+%  blue) triple.
+%
+%  The format of the ConvertLCHuvToRGBImage method is:
+%
+%      void ConvertLCHuvToRGB(const double luma,const double chroma,
+%        const double hue,double *red,double *green,double *blue)
+%
+%  A description of each parameter follows:
+%
+%    o luma, chroma, hue: A double value representing a component of the
+%      LCHuv color space.
+%
+%    o red, green, blue: A pointer to a pixel component of type Quantum.
+%
+*/
+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;
+
+  /*
+    Convert LCHuv to RGB colorspace.
+  */
+  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,v,&X,&Y,&Z);
+  ConvertXYZToRGB(X,Y,Z,red,green,blue);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   C o n v e r t R G B T o H C L                                             %
 %                                                                             %
 %                                                                             %
@@ -767,18 +822,18 @@ MagickPrivate void ConvertRGBToHWB(const double red,const double green,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   C o n v e r t R G B T o L C H                                             %
+%   C o n v e r t R G B a b T o L C H                                         %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ConvertRGBToLCH() transforms a (red, green, blue) to a (luma, chroma,
+%  ConvertRGBToLCHab() transforms a (red, green, blue) to a (luma, chroma,
 %  hue) triple.
 %
-%  The format of the ConvertRGBToLCH method is:
+%  The format of the ConvertRGBToLCHab method is:
 %
-%      void ConvertRGBToLCH(const double red,const double green,
+%      void ConvertRGBToLCHab(const double red,const double green,
 %        const double blue,double *luma,double *chroma,double *hue)
 %
 %  A description of each parameter follows:
@@ -790,7 +845,7 @@ MagickPrivate void ConvertRGBToHWB(const double red,const double green,
 %      component of the LCH color space.
 %
 */
-MagickPrivate void ConvertRGBToLCH(const double red,const double green,
+MagickPrivate void ConvertRGBToLCHab(const double red,const double green,
   const double blue,double *luma,double *chroma,double *hue)
 {
   double
@@ -827,6 +882,66 @@ MagickPrivate void ConvertRGBToLCH(const double red,const double green,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   C o n v e r t R G B u v T o L C H                                         %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ConvertRGBToLCHuv() transforms a (red, green, blue) to a (luma, chroma,
+%  hue) triple.
+%
+%  The format of the ConvertRGBToLCHuv method is:
+%
+%      void ConvertRGBToLCHuv(const double red,const double green,
+%        const double blue,double *luma,double *chroma,double *hue)
+%
+%  A description of each parameter follows:
+%
+%    o red, green, blue: A Quantum value representing the red, green, and
+%      blue component of a pixel.
+%
+%    o luma, chroma, hue: A pointer to a double value representing a
+%      component of the LCHuv color space.
+%
+*/
+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;
+
+  /*
+    Convert RGB to LCH colorspace.
+  */
+  assert(luma != (double *) NULL);
+  assert(chroma != (double *) NULL);
+  assert(hue != (double *) NULL);
+  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+  ConvertXYZToLuv(X,Y,Z,&L,&u,&v);
+  C=hypot(u,v);
+  H=180.0*atan2(v,u)/MagickPI/360.0;
+  if (H < 0.0)
+    H+=1.0;
+  if (H >= 1.0)
+    H-=1.0;
+  *luma=L;
+  *chroma=C;
+  *hue=H;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   E x p a n d A f f i n e                                                   %
 %                                                                             %
 %                                                                             %
index 3b6fedd8ac2665965cefec1387f660f49f726d85..defde313256b48fcf9386366238a8cecbb4a6145 100644 (file)
@@ -891,6 +891,8 @@ static const OptionInfo
     { "HWB", HWBColorspace, UndefinedOptionFlag, MagickFalse },
     { "Lab", LabColorspace, UndefinedOptionFlag, MagickFalse },
     { "LCH", LCHColorspace, UndefinedOptionFlag, MagickFalse },
+    { "LCHab", LCHabColorspace, UndefinedOptionFlag, MagickFalse },
+    { "LCHuv", LCHuvColorspace, UndefinedOptionFlag, MagickFalse },
     { "LMS", LMSColorspace, UndefinedOptionFlag, MagickFalse },
     { "Log", LogColorspace, UndefinedOptionFlag, MagickFalse },
     { "Luv", LuvColorspace, UndefinedOptionFlag, MagickFalse },