]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/colorspace.c
(no commit message)
[imagemagick] / MagickCore / colorspace.c
index 61cc59ece3237ba21eb98017122114f9a52564f2..0ea8c8a502bede2baccbd1afd5cec51ff66e6722 100644 (file)
 %                     MagickCore Image Colorspace Methods                     %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  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  %
@@ -118,9 +118,6 @@ static MagickBooleanType
 static inline void ConvertRGBToCMY(const double red,const double green,
   const double blue,double *cyan,double *magenta,double *yellow)
 {
-  /*
-    Convert RGB to CMY colorspace.
-  */
   *cyan=QuantumScale*(QuantumRange-red);
   *magenta=QuantumScale*(QuantumRange-green);
   *yellow=QuantumScale*(QuantumRange-blue);
@@ -129,9 +126,6 @@ static inline void ConvertRGBToCMY(const double red,const double green,
 static inline void ConvertXYZToLMS(const double x,const double y,
   const double z,double *L,double *M,double *S)
 {
-  /*
-    Convert XYZ to LMS colorspace.
-  */
   *L=0.7328*x+0.4296*y-0.1624*z;
   *M=(-0.7036*x+1.6975*y+0.0061*z);
   *S=0.0030*x+0.0136*y+0.9834*z;
@@ -173,12 +167,17 @@ static void ConvertRGBToLuv(const double red,const double green,
   ConvertXYZToLuv(X,Y,Z,L,u,v);
 }
 
+static void ConvertRGBToYDbDr(const double red,const double green,
+  const double blue,double *Y,double *Db,double *Dr)
+{
+  *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
+  *Db=QuantumScale*(-0.450*red-0.883*green+1.333*blue)+0.5;
+  *Dr=QuantumScale*(-1.333*red+1.116*green+0.217*blue)+0.5;
+}
+
 static void ConvertRGBToYIQ(const double red,const double green,
   const double blue,double *Y,double *I,double *Q)
 {
-  /*
-    Convert RGB to YIQ colorspace.
-  */
   *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
   *I=QuantumScale*(0.595716*red-0.274453*green-0.321263*blue)+0.5;
   *Q=QuantumScale*(0.211456*red-0.522591*green+0.311135*blue)+0.5;
@@ -187,9 +186,6 @@ static void ConvertRGBToYIQ(const double red,const double green,
 static void ConvertRGBToYPbPr(const double red,const double green,
   const double blue,double *Y,double *Pb,double *Pr)
 {
-  /*
-    Convert RGB to YPbPr colorspace.
-  */
   *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
   *Pb=QuantumScale*((-0.1687367)*red-0.331264*green+0.5*blue)+0.5;
   *Pr=QuantumScale*(0.5*red-0.418688*green-0.081312*blue)+0.5;
@@ -198,18 +194,12 @@ static void ConvertRGBToYPbPr(const double red,const double green,
 static void ConvertRGBToYCbCr(const double red,const double green,
   const double blue,double *Y,double *Cb,double *Cr)
 {
-  /*
-    Convert RGB to YCbCr colorspace.
-  */
   ConvertRGBToYPbPr(red,green,blue,Y,Cb,Cr);
 }
 
 static void ConvertRGBToYUV(const double red,const double green,
   const double blue,double *Y,double *U,double *V)
 {
-  /*
-    Convert RGB to YUV colorspace.
-  */
   *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
   *U=QuantumScale*((-0.147)*red-0.289*green+0.436*blue)+0.5;
   *V=QuantumScale*(0.615*red-0.515*green-0.100*blue)+0.5;
@@ -387,6 +377,7 @@ static MagickBooleanType sRGBTransformImage(Image *image,
     case LuvColorspace:
     case XYZColorspace:
     case YCbCrColorspace:
+    case YDbDrColorspace:
     case YIQColorspace:
     case YPbPrColorspace:
     case YUVColorspace:
@@ -517,6 +508,11 @@ static MagickBooleanType sRGBTransformImage(Image *image,
               ConvertRGBToYCbCr(red,green,blue,&X,&Y,&Z);
               break;
             }
+            case YDbDrColorspace:
+            {
+              ConvertRGBToYDbDr(red,green,blue,&X,&Y,&Z);
+              break;
+            }
             case YIQColorspace:
             {
               ConvertRGBToYIQ(red,green,blue,&X,&Y,&Z);
@@ -533,7 +529,12 @@ static MagickBooleanType sRGBTransformImage(Image *image,
               break;
             }
             default:
+            {
+              X=QuantumScale*red;
+              Y=QuantumScale*green;
+              Z=QuantumScale*blue;
               break;
+            }
           }
           SetPixelRed(image,ClampToQuantum(QuantumRange*X),q);
           SetPixelGreen(image,ClampToQuantum(QuantumRange*Y),q);
@@ -637,9 +638,12 @@ static MagickBooleanType sRGBTransformImage(Image *image,
             green,
             red;
 
-          red=(double) GetPixelRed(image,q);
-          green=(double) GetPixelGreen(image,q);
-          blue=(double) GetPixelBlue(image,q);
+          red=(double) DecodePixelGamma((MagickRealType)
+            GetPixelRed(image,q));
+          green=(double) DecodePixelGamma((MagickRealType)
+            GetPixelGreen(image,q));
+          blue=(double) DecodePixelGamma((MagickRealType)
+            GetPixelBlue(image,q));
           SetPixelRed(image,logmap[ScaleQuantumToMap(ClampToQuantum(red))],q);
           SetPixelGreen(image,logmap[ScaleQuantumToMap(ClampToQuantum(green))],
             q);
@@ -807,7 +811,7 @@ static MagickBooleanType sRGBTransformImage(Image *image,
       /*
         Initialize YCbCr tables (ITU-R BT.709):
 
-          Y =  0.212600*R+0.715200*G+0.072200*B
+          Y =  0.212656*R+0.715158*G+0.072186*B
           Cb= -0.114572*R-0.385428*G+0.500000*B
           Cr=  0.500000*R-0.454153*G-0.045847*B
 
@@ -822,9 +826,9 @@ static MagickBooleanType sRGBTransformImage(Image *image,
 #endif
       for (i=0; i <= (ssize_t) MaxMap; i++)
       {
-        x_map[i].x=(MagickRealType) (0.212600*(double) i);
-        y_map[i].x=(MagickRealType) (0.715200*(double) i);
-        z_map[i].x=(MagickRealType) (0.072200*(double) i);
+        x_map[i].x=(MagickRealType) (0.212656*(double) i);
+        y_map[i].x=(MagickRealType) (0.715158*(double) i);
+        z_map[i].x=(MagickRealType) (0.072186*(double) i);
         x_map[i].y=(MagickRealType) (-0.114572*(double) i);
         y_map[i].y=(MagickRealType) (-0.385428*(double) i);
         z_map[i].y=(MagickRealType) (0.500000*(double) i);
@@ -1050,43 +1054,49 @@ static MagickBooleanType sRGBTransformImage(Image *image,
 MagickExport MagickBooleanType SetImageColorspace(Image *image,
   const ColorspaceType colorspace,ExceptionInfo *exception)
 {
+  ImageType
+    type;
+
+  MagickBooleanType
+    status;
+
   if (image->colorspace == colorspace)
     return(MagickTrue);
   image->colorspace=colorspace;
   image->rendering_intent=UndefinedIntent;
-  image->gamma=1.000;
+  image->gamma=1.000/2.200;
   (void) ResetMagickMemory(&image->chromaticity,0,sizeof(image->chromaticity));
+  type=image->type;
   if (IsGrayColorspace(colorspace) != MagickFalse)
     {
-      if ((image->intensity != Rec601LuminancePixelIntensityMethod) &&
-          (image->intensity != Rec709LuminancePixelIntensityMethod) &&
-          (image->intensity != UndefinedPixelIntensityMethod))
-        image->gamma=1.000/2.200;
-      image->type=GrayscaleType;
+      if ((image->intensity == Rec601LuminancePixelIntensityMethod) ||
+          (image->intensity == Rec709LuminancePixelIntensityMethod))
+        image->gamma=1.000;
+      type=GrayscaleType;
     }
   else
-    if (IssRGBColorspace(colorspace) != MagickFalse)
-      image->gamma=1.000/2.200;
-  if (image->gamma == (1.000/2.200))
-    {
-      image->rendering_intent=PerceptualIntent;
-      image->gamma=1.000/2.200;
-      image->chromaticity.red_primary.x=0.6400;
-      image->chromaticity.red_primary.y=0.3300;
-      image->chromaticity.red_primary.z=0.0300;
-      image->chromaticity.green_primary.x=0.3000;
-      image->chromaticity.green_primary.y=0.6000;
-      image->chromaticity.green_primary.z=0.1000;
-      image->chromaticity.blue_primary.x=0.1500;
-      image->chromaticity.blue_primary.y=0.0600;
-      image->chromaticity.blue_primary.z=0.7900;
-      image->chromaticity.white_point.x=0.3127;
-      image->chromaticity.white_point.y=0.3290;
-      image->chromaticity.white_point.z=0.3583;
-    }
-  if (IsGrayColorspace(colorspace) != MagickFalse)
-    image->type=GrayscaleType;
-  return(SyncImagePixelCache(image,exception));
+    if ((IsRGBColorspace(colorspace) != MagickFalse) ||
+        (colorspace == XYZColorspace))
+      image->gamma=1.000;
+    else
+      {
+        image->rendering_intent=PerceptualIntent;
+        image->chromaticity.red_primary.x=0.6400;
+        image->chromaticity.red_primary.y=0.3300;
+        image->chromaticity.red_primary.z=0.0300;
+        image->chromaticity.green_primary.x=0.3000;
+        image->chromaticity.green_primary.y=0.6000;
+        image->chromaticity.green_primary.z=0.1000;
+        image->chromaticity.blue_primary.x=0.1500;
+        image->chromaticity.blue_primary.y=0.0600;
+        image->chromaticity.blue_primary.z=0.7900;
+        image->chromaticity.white_point.x=0.3127;
+        image->chromaticity.white_point.y=0.3290;
+        image->chromaticity.white_point.z=0.3583;
+      }
+  status=SyncImagePixelCache(image,exception);
+  image->type=type;
+  return(status);
 }
 \f
 /*
@@ -1127,10 +1137,13 @@ MagickExport MagickBooleanType TransformImageColorspace(Image *image,
   assert(image->signature == MagickSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  if (image->colorspace == colorspace)
+    return(MagickTrue);
+  if ((image->colorspace == GRAYColorspace) && (image->gamma != 1.0) &&
+      (colorspace == sRGBColorspace))
+    return(MagickTrue);
   if (colorspace == UndefinedColorspace)
     return(SetImageColorspace(image,colorspace,exception));
-  if (image->colorspace == colorspace)
-    return(MagickTrue);  /* same colorspace: no op */
   /*
     Convert the reference image from an alternate colorspace to sRGB.
   */
@@ -1183,9 +1196,6 @@ MagickExport MagickBooleanType TransformImageColorspace(Image *image,
 static inline void ConvertCMYToRGB(const double cyan,const double magenta,
   const double yellow,double *red,double *green,double *blue)
 {
-  /*
-    Convert CMY to RGB colorspace.
-  */
   *red=QuantumRange*(1.0-cyan);
   *green=QuantumRange*(1.0-magenta);
   *blue=QuantumRange*(1.0-yellow);
@@ -1219,7 +1229,7 @@ static inline void ConvertLuvToRGB(const double L,const double u,
     Y,
     Z;
 
-  ConvertLuvToXYZ(L,u,v,&X,&Y,&Z);
+  ConvertLuvToXYZ(100.0*L,354.0*u-134.0,262.0*v-140.0,&X,&Y,&Z);
   ConvertXYZToRGB(X,Y,Z,red,green,blue);
 }
 
@@ -1257,9 +1267,6 @@ static inline void ConvertLabToRGB(const double L,const double a,
 static void ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr,
   double *red,double *green,double *blue)
 {
-  /*
-    Convert YPbPr to RGB colorspace.
-  */
   *red=QuantumRange*(0.99999999999914679361*Y-1.2188941887145875e-06*(Pb-0.5)+
     1.4019995886561440468*(Pr-0.5));
   *green=QuantumRange*(0.99999975910502514331*Y-0.34413567816504303521*(Pb-0.5)-
@@ -1271,18 +1278,12 @@ static void ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr,
 static void ConvertYCbCrToRGB(const double Y,const double Cb,
   const double Cr,double *red,double *green,double *blue)
 {
-  /*
-    Convert YCbCr to RGB colorspace.
-  */
   ConvertYPbPrToRGB(Y,Cb,Cr,red,green,blue);
 }
 
 static void ConvertYIQToRGB(const double Y,const double I,const double Q,
   double *red,double *green,double *blue)
 {
-  /*
-    Convert YIQ to RGB colorspace.
-  */
   *red=QuantumRange*(Y+0.9562957197589482261*(I-0.5)+0.6210244164652610754*
     (Q-0.5));
   *green=QuantumRange*(Y-0.2721220993185104464*(I-0.5)-0.6473805968256950427*
@@ -1291,12 +1292,20 @@ static void ConvertYIQToRGB(const double Y,const double I,const double Q,
     (Q-0.5));
 }
 
+static void ConvertYDbDrToRGB(const double Y,const double Db,const double Dr,
+  double *red,double *green,double *blue)
+{
+  *red=QuantumRange*(Y+9.2303716147657e-05*(Db-0.5)-
+    0.52591263066186533*(Dr-0.5));
+  *green=QuantumRange*(Y-0.12913289889050927*(Db-0.5)+
+    0.26789932820759876*(Dr-0.5));
+  *blue=QuantumRange*(Y+0.66467905997895482*(Db-0.5)-
+    7.9202543533108e-05*(Dr-0.5));
+}
+
 static void ConvertYUVToRGB(const double Y,const double U,const double V,
   double *red,double *green,double *blue)
 {
-  /*
-    Convert YUV to RGB colorspace.
-  */
   *red=QuantumRange*(Y-3.945707070708279e-05*(U-0.5)+1.1398279671717170825*
     (V-0.5));
   *green=QuantumRange*(Y-0.3946101641414141437*(U-0.5)-0.5805003156565656797*
@@ -1677,10 +1686,13 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           }
         for (x=(ssize_t) image->columns; x != 0; x--)
         {
-          double
+          MagickRealType
             gray;
 
-          gray=EncodePixelGamma((MagickRealType) GetPixelGray(image,q));
+          gray=(MagickRealType) GetPixelGray(image,q);
+          if ((image->intensity == Rec601LuminancePixelIntensityMethod) ||
+              (image->intensity == Rec709LuminancePixelIntensityMethod))
+            gray=EncodePixelGamma(gray);
           SetPixelRed(image,ClampToQuantum(gray),q);
           SetPixelGreen(image,ClampToQuantum(gray),q);
           SetPixelBlue(image,ClampToQuantum(gray),q);
@@ -1711,6 +1723,7 @@ static MagickBooleanType TransformsRGBImage(Image *image,
     case LuvColorspace:
     case XYZColorspace:
     case YCbCrColorspace:
+    case YDbDrColorspace:
     case YIQColorspace:
     case YPbPrColorspace:
     case YUVColorspace:
@@ -1841,6 +1854,11 @@ static MagickBooleanType TransformsRGBImage(Image *image,
               ConvertYCbCrToRGB(X,Y,Z,&red,&green,&blue);
               break;
             }
+            case YDbDrColorspace:
+            {
+              ConvertYDbDrToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
             case YIQColorspace:
             {
               ConvertYIQToRGB(X,Y,Z,&red,&green,&blue);
@@ -1857,7 +1875,12 @@ static MagickBooleanType TransformsRGBImage(Image *image,
               break;
             }
             default:
+            {
+              red=QuantumRange*X;
+              green=QuantumRange*Y;
+              blue=QuantumRange*Z;
               break;
+            }
           }
           SetPixelRed(image,ClampToQuantum(red),q);
           SetPixelGreen(image,ClampToQuantum(green),q);
@@ -1966,9 +1989,12 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           red=(double) logmap[ScaleQuantumToMap(GetPixelRed(image,q))];
           green=(double) logmap[ScaleQuantumToMap(GetPixelGreen(image,q))];
           blue=(double) logmap[ScaleQuantumToMap(GetPixelBlue(image,q))];
-          SetPixelRed(image,ClampToQuantum(red),q);
-          SetPixelGreen(image,ClampToQuantum(green),q);
-          SetPixelBlue(image,ClampToQuantum(blue),q);
+          SetPixelRed(image,ClampToQuantum(EncodePixelGamma((MagickRealType)
+            red)),q);
+          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma((MagickRealType)
+            green)),q);
+          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma((MagickRealType)
+            blue)),q);
           q+=GetPixelChannels(image);
         }
         sync=SyncCacheViewAuthenticPixels(image_view,exception);