]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/colorspace.c
(no commit message)
[imagemagick] / MagickCore / colorspace.c
index 4aa5996b8042c9de4f9bc22e364f273f3ac7c030..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  %
@@ -82,7 +82,7 @@ typedef struct _TransformPacket
   Forward declarations.
 */
 static MagickBooleanType
-  TransformsRGBImage(Image *,const ColorspaceType,ExceptionInfo *);
+  TransformsRGBImage(Image *,ExceptionInfo *);
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -115,100 +115,94 @@ static MagickBooleanType
 %
 */
 
+static inline void ConvertRGBToCMY(const double red,const double green,
+  const double blue,double *cyan,double *magenta,double *yellow)
+{
+  *cyan=QuantumScale*(QuantumRange-red);
+  *magenta=QuantumScale*(QuantumRange-green);
+  *yellow=QuantumScale*(QuantumRange-blue);
+}
+
 static inline void ConvertXYZToLMS(const double x,const double y,
   const double z,double *L,double *M,double *S)
+{
+  *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;
+}
+
+static void ConvertRGBToLMS(const double red,const double green,
+  const double blue,double *L,double *M,double *S)
 {
   double
-    l,
-    m,
-    s;
+    X,
+    Y,
+    Z;
 
-  /*
-    Convert XYZ to LMS colorspace.
-  */
-  assert(L != (double *) NULL);
-  assert(M != (double *) NULL);
-  assert(S != (double *) NULL);
-  l=0.7328f*x+0.4296f*y-0.1624f*z;
-  m=(-0.7036f*x+1.6975f*y+0.0415f*z);
-  s=0.0030f*x+0.0136f*y+0.9834f*z;
-  *L=QuantumRange*l;
-  *M=QuantumRange*m;
-  *S=QuantumRange*s;
+  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+  ConvertXYZToLMS(X,Y,Z,L,M,S);
 }
 
-static inline void ConvertRGBToXYZ(const double red,const double green,
-  const double blue,double *X,double *Y,double *Z)
+static void ConvertRGBToLab(const double red,const double green,
+  const double blue,double *L,double *a,double *b)
 {
   double
-    b,
-    g,
-    r;
-
-  assert(X != (double *) NULL);
-  assert(Y != (double *) NULL);
-  assert(Z != (double *) NULL);
-  r=QuantumScale*red;
-  g=QuantumScale*green;
-  b=QuantumScale*blue;
-  *X=0.41239558896741421610*r+0.35758343076371481710*g+0.18049264738170157350*b;
-  *Y=0.21258623078559555160*r+0.71517030370341084990*g+0.07220049864333622685*b;
-  *Z=0.01929721549174694484*r+0.11918386458084853180*g+0.95049712513157976600*b;
+    X,
+    Y,
+    Z;
+
+  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+  ConvertXYZToLab(X,Y,Z,L,a,b);
 }
 
-static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
-  double *L,double *a,double *b)
+static void ConvertRGBToLuv(const double red,const double green,
+  const double blue,double *L,double *u,double *v)
 {
-#define D65X  (0.950456f)
-#define D65Y  (1.0f)
-#define D65Z  (1.088754f)
-#define CIEEpsilon  (216.0f/24389.0f)
-#define CIEK  (24389.0f/27.0f)
-
   double
-    x,
-    y,
-    z;
+    X,
+    Y,
+    Z;
 
-  assert(L != (double *) NULL);
-  assert(a != (double *) NULL);
-  assert(b != (double *) NULL);
-  if ((X/D65X) > CIEEpsilon)
-    x=pow(X/D65X,1.0/3.0);
-  else
-    x=(CIEK*X/D65X+16.0f)/116.0f;
-  if ((Y/D65Y) > CIEEpsilon)
-    y=pow(Y/D65Y,1.0/3.0);
-  else
-    y=(CIEK*Y/D65Y+16.0f)/116.0f;
-  if ((Z/D65Z) > CIEEpsilon)
-    z=pow(Z/D65Z,1.0/3.0);
-  else
-    z=(CIEK*Z/D65Z+16.0f)/116.0f;
-  *L=((116.0f*y)-16.0f)/100.0f;
-  *a=(500.0f*(x-y))/255.0f+0.5f;
-  *b=(200.0f*(y-z))/255.0f+0.5f;
+  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+  ConvertXYZToLuv(X,Y,Z,L,u,v);
 }
 
-static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
-  double *L,double *u,double *v)
+static void ConvertRGBToYDbDr(const double red,const double green,
+  const double blue,double *Y,double *Db,double *Dr)
 {
-  double
-    alpha;
+  *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;
+}
 
-  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 void ConvertRGBToYIQ(const double red,const double green,
+  const double blue,double *Y,double *I,double *Q)
+{
+  *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;
+}
+
+static void ConvertRGBToYPbPr(const double red,const double green,
+  const double blue,double *Y,double *Pb,double *Pr)
+{
+  *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;
+}
+
+static void ConvertRGBToYCbCr(const double red,const double green,
+  const double blue,double *Y,double *Cb,double *Cr)
+{
+  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)
+{
+  *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;
 }
 
 static MagickBooleanType sRGBTransformImage(Image *image,
@@ -250,69 +244,6 @@ static MagickBooleanType sRGBTransformImage(Image *image,
   progress=0;
   switch (colorspace)
   {
-    case CMYColorspace:
-    {
-      /*
-        Convert RGB to CMY colorspace.
-      */
-      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
-            cyan,
-            magenta,
-            yellow;
-
-          cyan=DecodePixelGamma((MagickRealType) GetPixelCyan(image,q));
-          magenta=DecodePixelGamma((MagickRealType) GetPixelMagenta(image,q));
-          yellow=DecodePixelGamma((MagickRealType) GetPixelYellow(image,q));
-          SetPixelCyan(image,ClampToQuantum(QuantumRange-cyan),q);
-          SetPixelMagenta(image,ClampToQuantum(QuantumRange-magenta),q);
-          SetPixelYellow(image,ClampToQuantum(QuantumRange-yellow),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      image->type=image->alpha_trait != BlendPixelTrait ? ColorSeparationType :
-        ColorSeparationMatteType;
-      if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
     case CMYKColorspace:
     {
       PixelInfo
@@ -363,9 +294,6 @@ static MagickBooleanType sRGBTransformImage(Image *image,
         for (x=0; x < (ssize_t) image->columns; x++)
         {
           GetPixelInfoPixel(image,q,&pixel);
-          pixel.red=DecodePixelGamma(pixel.red);
-          pixel.green=DecodePixelGamma(pixel.green);
-          pixel.blue=DecodePixelGamma(pixel.blue);
           ConvertRGBToCMYK(&pixel);
           SetPixelInfoPixel(image,&pixel,q);
           q+=GetPixelChannels(image);
@@ -433,10 +361,29 @@ static MagickBooleanType sRGBTransformImage(Image *image,
       image->type=GrayscaleType;
       return(status);
     }
+    case CMYColorspace:
     case HCLColorspace:
+    case HCLpColorspace:
+    case HSBColorspace:
+    case HSIColorspace:
+    case HSLColorspace:
+    case HSVColorspace:
+    case HWBColorspace:
+    case LabColorspace:
+    case LCHColorspace:
+    case LCHabColorspace:
+    case LCHuvColorspace:
+    case LMSColorspace:
+    case LuvColorspace:
+    case XYZColorspace:
+    case YCbCrColorspace:
+    case YDbDrColorspace:
+    case YIQColorspace:
+    case YPbPrColorspace:
+    case YUVColorspace:
     {
       /*
-        Transform image from sRGB to HCL.
+        Transform image from sRGB to target colorspace.
       */
       if (image->storage_class == PseudoClass)
         {
@@ -474,19 +421,124 @@ static MagickBooleanType sRGBTransformImage(Image *image,
         {
           double
             blue,
-            chroma,
             green,
-            hue,
-            luma,
-            red;
+            red,
+            X,
+            Y,
+            Z;
 
-          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          ConvertRGBToHCL(red,green,blue,&hue,&chroma,&luma);
-          SetPixelRed(image,ClampToQuantum(QuantumRange*hue),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*chroma),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*luma),q);
+          red=(double) GetPixelRed(image,q);
+          green=(double) GetPixelGreen(image,q);
+          blue=(double) GetPixelBlue(image,q);
+          switch (colorspace)
+          {
+            case CMYColorspace:
+            {
+              ConvertRGBToCMY(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case HCLColorspace:
+            {
+              ConvertRGBToHCL(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case HCLpColorspace:
+            {
+              ConvertRGBToHCLp(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case HSBColorspace:
+            {
+              ConvertRGBToHSB(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case HSIColorspace:
+            {
+              ConvertRGBToHSI(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case HSLColorspace:
+            {
+              ConvertRGBToHSL(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case HSVColorspace:
+            {
+              ConvertRGBToHSV(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case HWBColorspace:
+            {
+              ConvertRGBToHWB(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case LabColorspace:
+            {
+              ConvertRGBToLab(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case LCHColorspace:
+            case LCHabColorspace:
+            {
+              ConvertRGBToLCHab(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case LCHuvColorspace:
+            {
+              ConvertRGBToLCHuv(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case LMSColorspace:
+            {
+              ConvertRGBToLMS(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case LuvColorspace:
+            {
+              ConvertRGBToLuv(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case XYZColorspace:
+            {
+              ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case YCbCrColorspace:
+            {
+              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);
+              break;
+            }
+            case YPbPrColorspace:
+            {
+              ConvertRGBToYPbPr(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            case YUVColorspace:
+            {
+              ConvertRGBToYUV(red,green,blue,&X,&Y,&Z);
+              break;
+            }
+            default:
+            {
+              X=QuantumScale*red;
+              Y=QuantumScale*green;
+              Z=QuantumScale*blue;
+              break;
+            }
+          }
+          SetPixelRed(image,ClampToQuantum(QuantumRange*X),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*Y),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*Z),q);
           q+=GetPixelChannels(image);
         }
         sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -498,18 +550,62 @@ static MagickBooleanType sRGBTransformImage(Image *image,
         return(MagickFalse);
       return(status);
     }
-    case HSBColorspace:
+    case LogColorspace:
     {
+#define DisplayGamma  (1.0/1.7)
+#define FilmGamma  0.6
+#define ReferenceBlack  95.0
+#define ReferenceWhite  685.0
+
+      const char
+        *value;
+
+      double
+        black,
+        density,
+        film_gamma,
+        gamma,
+        reference_black,
+        reference_white;
+
+      Quantum
+        *logmap;
+
       /*
-        Transform image from sRGB to HSB.
+        Transform RGB to Log colorspace.
       */
-      if (image->storage_class == PseudoClass)
-        {
-          if (SyncImage(image,exception) == MagickFalse)
-            return(MagickFalse);
-          if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
-            return(MagickFalse);
-        }
+      density=DisplayGamma;
+      gamma=DisplayGamma;
+      value=GetImageProperty(image,"gamma",exception);
+      if (value != (const char *) NULL)
+        gamma=PerceptibleReciprocal(StringToDouble(value,(char **) NULL));
+      film_gamma=FilmGamma;
+      value=GetImageProperty(image,"film-gamma",exception);
+      if (value != (const char *) NULL)
+        film_gamma=StringToDouble(value,(char **) NULL);
+      reference_black=ReferenceBlack;
+      value=GetImageProperty(image,"reference-black",exception);
+      if (value != (const char *) NULL)
+        reference_black=StringToDouble(value,(char **) NULL);
+      reference_white=ReferenceWhite;
+      value=GetImageProperty(image,"reference-white",exception);
+      if (value != (const char *) NULL)
+        reference_white=StringToDouble(value,(char **) NULL);
+      logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
+        sizeof(*logmap));
+      if (logmap == (Quantum *) NULL)
+        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
+          image->filename);
+      black=pow(10.0,(reference_black-reference_white)*(gamma/density)*0.002/
+        film_gamma);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+      #pragma omp parallel for schedule(static,4) \
+        magick_threads(image,image,1,1)
+#endif
+      for (i=0; i <= (ssize_t) MaxMap; i++)
+        logmap[i]=ScaleMapToQuantum((double) (MaxMap*(reference_white+
+          log10(black+(1.0*i/MaxMap)*(1.0-black))/((gamma/density)*0.002/
+          film_gamma))/1024.0));
       image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
       #pragma omp parallel for schedule(static,4) shared(status) \
@@ -535,23 +631,23 @@ static MagickBooleanType sRGBTransformImage(Image *image,
             status=MagickFalse;
             continue;
           }
-        for (x=0; x < (ssize_t) image->columns; x++)
+        for (x=(ssize_t) image->columns; x != 0; x--)
         {
           double
             blue,
-            brightness,
             green,
-            hue,
-            red,
-            saturation;
+            red;
 
-          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          ConvertRGBToHSB(red,green,blue,&hue,&saturation,&brightness);
-          SetPixelRed(image,ClampToQuantum(QuantumRange*hue),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*saturation),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*brightness),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);
+          SetPixelBlue(image,logmap[ScaleQuantumToMap(ClampToQuantum(blue))],q);
           q+=GetPixelChannels(image);
         }
         sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -559,14 +655,16 @@ static MagickBooleanType sRGBTransformImage(Image *image,
           status=MagickFalse;
       }
       image_view=DestroyCacheView(image_view);
+      logmap=(Quantum *) RelinquishMagickMemory(logmap);
       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
         return(MagickFalse);
       return(status);
     }
-    case HSLColorspace:
+    case RGBColorspace:
+    case scRGBColorspace:
     {
       /*
-        Transform image from sRGB to HSL.
+        Transform image from sRGB to linear RGB.
       */
       if (image->storage_class == PseudoClass)
         {
@@ -605,18 +703,14 @@ static MagickBooleanType sRGBTransformImage(Image *image,
           double
             blue,
             green,
-            hue,
-            lightness,
-            red,
-            saturation;
+            red;
 
           red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
           green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
           blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          ConvertRGBToHSL(red,green,blue,&hue,&saturation,&lightness);
-          SetPixelRed(image,ClampToQuantum(QuantumRange*hue),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*saturation),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*lightness),q);
+          SetPixelRed(image,ClampToQuantum(red),q);
+          SetPixelGreen(image,ClampToQuantum(green),q);
+          SetPixelBlue(image,ClampToQuantum(blue),q);
           q+=GetPixelChannels(image);
         }
         sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -628,152 +722,196 @@ static MagickBooleanType sRGBTransformImage(Image *image,
         return(MagickFalse);
       return(status);
     }
-    case HWBColorspace:
+    default:
+      break;
+  }
+  /*
+    Allocate the tables.
+  */
+  x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
+    sizeof(*x_map));
+  y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
+    sizeof(*y_map));
+  z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
+    sizeof(*z_map));
+  if ((x_map == (TransformPacket *) NULL) ||
+      (y_map == (TransformPacket *) NULL) ||
+      (z_map == (TransformPacket *) NULL))
+    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
+      image->filename);
+  (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
+  switch (colorspace)
+  {
+    case OHTAColorspace:
     {
       /*
-        Transform image from sRGB to HWB.
+        Initialize OHTA tables:
+
+          I1 = 0.33333*R+0.33334*G+0.33333*B
+          I2 = 0.50000*R+0.00000*G-0.50000*B
+          I3 =-0.25000*R+0.50000*G-0.25000*B
+
+        I and Q, normally -0.5 through 0.5, are normalized to the range 0
+        through QuantumRange.
       */
-      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);
+      primary_info.y=(double) (MaxMap+1.0)/2.0;
+      primary_info.z=(double) (MaxMap+1.0)/2.0;
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) shared(status) \
-        magick_threads(image,image,image->rows,1)
+      #pragma omp parallel for schedule(static,4) \
+        magick_threads(image,image,1,1)
 #endif
-      for (y=0; y < (ssize_t) image->rows; y++)
+      for (i=0; i <= (ssize_t) MaxMap; i++)
       {
-        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
-            blackness,
-            blue,
-            green,
-            hue,
-            red,
-            whiteness;
-
-          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          ConvertRGBToHWB(red,green,blue,&hue,&whiteness,&blackness);
-          SetPixelRed(image,ClampToQuantum(QuantumRange*hue),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*whiteness),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*blackness),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
+        x_map[i].x=(MagickRealType) (0.33333*(double) i);
+        y_map[i].x=(MagickRealType) (0.33334*(double) i);
+        z_map[i].x=(MagickRealType) (0.33333*(double) i);
+        x_map[i].y=(MagickRealType) (0.50000*(double) i);
+        y_map[i].y=(MagickRealType) (0.00000*(double) i);
+        z_map[i].y=(MagickRealType) (-0.50000*(double) i);
+        x_map[i].z=(MagickRealType) (-0.25000*(double) i);
+        y_map[i].z=(MagickRealType) (0.50000*(double) i);
+        z_map[i].z=(MagickRealType) (-0.25000*(double) i);
       }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
+      break;
     }
-    case LabColorspace:
+    case Rec601YCbCrColorspace:
     {
       /*
-        Transform image from sRGB to Lab.
+        Initialize YCbCr tables (ITU-R BT.601):
+
+          Y =  0.2988390*R+0.5868110*G+0.1143500*B
+          Cb= -0.1687367*R-0.3312640*G+0.5000000*B
+          Cr=  0.5000000*R-0.4186880*G-0.0813120*B
+
+        Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
+        through QuantumRange.
       */
-      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);
+      primary_info.y=(double) (MaxMap+1.0)/2.0;
+      primary_info.z=(double) (MaxMap+1.0)/2.0;
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) shared(status) \
-        magick_threads(image,image,image->rows,1)
+      #pragma omp parallel for schedule(static,4) \
+        magick_threads(image,image,1,1)
 #endif
-      for (y=0; y < (ssize_t) image->rows; y++)
+      for (i=0; i <= (ssize_t) MaxMap; i++)
       {
-        MagickBooleanType
-          sync;
+        x_map[i].x=(MagickRealType) (0.298839*(double) i);
+        y_map[i].x=(MagickRealType) (0.586811*(double) i);
+        z_map[i].x=(MagickRealType) (0.114350*(double) i);
+        x_map[i].y=(MagickRealType) (-0.1687367*(double) i);
+        y_map[i].y=(MagickRealType) (-0.331264*(double) i);
+        z_map[i].y=(MagickRealType) (0.500000*(double) i);
+        x_map[i].z=(MagickRealType) (0.500000*(double) i);
+        y_map[i].z=(MagickRealType) (-0.418688*(double) i);
+        z_map[i].z=(MagickRealType) (-0.081312*(double) i);
+      }
+      break;
+    }
+    case Rec709YCbCrColorspace:
+    {
+      /*
+        Initialize YCbCr tables (ITU-R BT.709):
 
-        register ssize_t
-          x;
+          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
 
-        register Quantum
-          *restrict q;
+        Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
+        through QuantumRange.
+      */
+      primary_info.y=(double) (MaxMap+1.0)/2.0;
+      primary_info.z=(double) (MaxMap+1.0)/2.0;
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+      #pragma omp parallel for schedule(static,4) \
+        magick_threads(image,image,1,1)
+#endif
+      for (i=0; i <= (ssize_t) MaxMap; 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);
+        x_map[i].z=(MagickRealType) (0.500000*(double) i);
+        y_map[i].z=(MagickRealType) (-0.454153*(double) i);
+        z_map[i].z=(MagickRealType) (-0.045847*(double) i);
+      }
+      break;
+    }
+    case YCCColorspace:
+    {
+      /*
+        Initialize YCC tables:
 
-        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
-            a,
-            b,
-            blue,
-            green,
-            L,
-            red,
-            X,
-            Y,
-            Z;
+          Y =  0.298839*R+0.586811*G+0.114350*B
+          C1= -0.298839*R-0.586811*G+0.88600*B
+          C2=  0.70100*R-0.586811*G-0.114350*B
 
-          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
-          ConvertXYZToLab(X,Y,Z,&L,&a,&b);
-          SetPixelRed(image,ClampToQuantum(QuantumRange*L),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*a),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*b),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
+        YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
+      */
+      primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
+      primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
+      for (i=0; i <= (ssize_t) (0.018*MaxMap); i++)
+      {
+        x_map[i].x=0.003962014134275617*i;
+        y_map[i].x=0.007778268551236748*i;
+        z_map[i].x=0.001510600706713781*i;
+        x_map[i].y=(-0.002426619775463276)*i;
+        y_map[i].y=(-0.004763965913702149)*i;
+        z_map[i].y=0.007190585689165425*i;
+        x_map[i].z=0.006927257754597858*i;
+        y_map[i].z=(-0.005800713697502058)*i;
+        z_map[i].z=(-0.0011265440570958)*i;
       }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
+      for ( ; i <= (ssize_t) MaxMap; i++)
+      {
+        x_map[i].x=0.2201118963486454*(1.099*i-0.099);
+        y_map[i].x=0.4321260306242638*(1.099*i-0.099);
+        z_map[i].x=0.08392226148409894*(1.099*i-0.099);
+        x_map[i].y=(-0.1348122097479598)*(1.099*i-0.099);
+        y_map[i].y=(-0.2646647729834528)*(1.099*i-0.099);
+        z_map[i].y=0.3994769827314126*(1.099*i-0.099);
+        x_map[i].z=0.3848476530332144*(1.099*i-0.099);
+        y_map[i].z=(-0.3222618720834477)*(1.099*i-0.099);
+        z_map[i].z=(-0.06258578094976668)*(1.099*i-0.099);
+      }
+      break;
     }
-    case LCHColorspace:
+    default:
     {
       /*
-        Transform image from sRGB to LCH.
+        Linear conversion tables.
+      */
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+      #pragma omp parallel for schedule(static,4) \
+        magick_threads(image,image,1,1)
+#endif
+      for (i=0; i <= (ssize_t) MaxMap; i++)
+      {
+        x_map[i].x=(MagickRealType) (1.0*(double) i);
+        y_map[i].x=(MagickRealType) 0.0;
+        z_map[i].x=(MagickRealType) 0.0;
+        x_map[i].y=(MagickRealType) 0.0;
+        y_map[i].y=(MagickRealType) (1.0*(double) i);
+        z_map[i].y=(MagickRealType) 0.0;
+        x_map[i].z=(MagickRealType) 0.0;
+        y_map[i].z=(MagickRealType) 0.0;
+        z_map[i].z=(MagickRealType) (1.0*(double) i);
+      }
+      break;
+    }
+  }
+  /*
+    Convert from sRGB.
+  */
+  switch (image->storage_class)
+  {
+    case DirectClass:
+    default:
+    {
+      /*
+        Convert DirectClass image.
       */
-      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) \
@@ -784,12 +922,20 @@ static MagickBooleanType sRGBTransformImage(Image *image,
         MagickBooleanType
           sync;
 
-        register ssize_t
-          x;
+        PixelInfo
+          pixel;
 
         register Quantum
           *restrict q;
 
+        register ssize_t
+          x;
+
+        register unsigned int
+          blue,
+          green,
+          red;
+
         if (status == MagickFalse)
           continue;
         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
@@ -801,843 +947,61 @@ static MagickBooleanType sRGBTransformImage(Image *image,
           }
         for (x=0; x < (ssize_t) image->columns; x++)
         {
-          double
-            a,
-            b,
-            blue,
-            C,
-            green,
-            H,
-            L,
-            red,
-            X,
-            Y,
-            Z;
-
-          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
-          ConvertXYZToLab(X,Y,Z,&L,&a,&b);
-          C=sqrt(a*a+b*b);
-          H=atan2(b,a)*180.0f/MagickPI;
-          if (H < 0.0f)
-            H+=1.0f;
-          SetPixelRed(image,ClampToQuantum(QuantumRange*L),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*C),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*H),q);
+          red=ScaleQuantumToMap(ClampToQuantum((MagickRealType)
+            GetPixelRed(image,q)));
+          green=ScaleQuantumToMap(ClampToQuantum((MagickRealType)
+            GetPixelGreen(image,q)));
+          blue=ScaleQuantumToMap(ClampToQuantum((MagickRealType)
+            GetPixelBlue(image,q)));
+          pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
+            primary_info.x;
+          pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
+            primary_info.y;
+          pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
+            primary_info.z;
+          SetPixelRed(image,ScaleMapToQuantum(pixel.red),q);
+          SetPixelGreen(image,ScaleMapToQuantum(pixel.green),q);
+          SetPixelBlue(image,ScaleMapToQuantum(pixel.blue),q);
           q+=GetPixelChannels(image);
         }
         sync=SyncCacheViewAuthenticPixels(image_view,exception);
         if (sync == MagickFalse)
           status=MagickFalse;
+        if (image->progress_monitor != (MagickProgressMonitor) NULL)
+          {
+            MagickBooleanType
+              proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+            #pragma omp critical (MagickCore_sRGBTransformImage)
+#endif
+            proceed=SetImageProgress(image,sRGBTransformImageTag,progress++,
+              image->rows);
+            if (proceed == MagickFalse)
+              status=MagickFalse;
+          }
       }
       image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
+      break;
     }
-    case LMSColorspace:
+    case PseudoClass:
     {
+      register unsigned int
+        blue,
+        green,
+        red;
+
       /*
-        Transform image from sRGB to LMS.
-      */
-      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,
-            green,
-            L,
-            M,
-            red,
-            S,
-            X,
-            Y,
-            Z;
-
-          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
-          ConvertXYZToLMS(X,Y,Z,&L,&M,&S);
-          SetPixelRed(image,ClampToQuantum(QuantumRange*L),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*M),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*S),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 LogColorspace:
-    {
-#define DisplayGamma  (1.0f/1.7f)
-#define FilmGamma  0.6f
-#define ReferenceBlack  95.0f
-#define ReferenceWhite  685.0f
-
-      const char
-        *value;
-
-      double
-        black,
-        density,
-        film_gamma,
-        gamma,
-        reference_black,
-        reference_white;
-
-      Quantum
-        *logmap;
-
-      /*
-        Transform RGB to Log colorspace.
-      */
-      density=DisplayGamma;
-      gamma=DisplayGamma;
-      value=GetImageProperty(image,"gamma",exception);
-      if (value != (const char *) NULL)
-        gamma=PerceptibleReciprocal(StringToDouble(value,(char **) NULL));
-      film_gamma=FilmGamma;
-      value=GetImageProperty(image,"film-gamma",exception);
-      if (value != (const char *) NULL)
-        film_gamma=StringToDouble(value,(char **) NULL);
-      reference_black=ReferenceBlack;
-      value=GetImageProperty(image,"reference-black",exception);
-      if (value != (const char *) NULL)
-        reference_black=StringToDouble(value,(char **) NULL);
-      reference_white=ReferenceWhite;
-      value=GetImageProperty(image,"reference-white",exception);
-      if (value != (const char *) NULL)
-        reference_white=StringToDouble(value,(char **) NULL);
-      logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
-        sizeof(*logmap));
-      if (logmap == (Quantum *) NULL)
-        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
-          image->filename);
-      black=pow(10.0,(reference_black-reference_white)*(gamma/density)*0.002f/
-        film_gamma);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-        logmap[i]=ScaleMapToQuantum((double) (MaxMap*(reference_white+
-          log10(black+(1.0*i/MaxMap)*(1.0-black))/((gamma/density)*0.002f/
-          film_gamma))/1024.0));
-      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=(ssize_t) image->columns; x != 0; x--)
-        {
-          double
-            blue,
-            green,
-            red;
-
-          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          SetPixelRed(image,logmap[ScaleQuantumToMap(
-            ClampToQuantum(red))],q);
-          SetPixelGreen(image,logmap[ScaleQuantumToMap(
-            ClampToQuantum(green))],q);
-          SetPixelBlue(image,logmap[ScaleQuantumToMap(
-            ClampToQuantum(blue))],q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      logmap=(Quantum *) RelinquishMagickMemory(logmap);
-      if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
-    case LuvColorspace:
-    {
-      /*
-        Transform image from sRGB to Luv.
-      */
-      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,
-            green,
-            L,
-            red,
-            u,
-            v,
-            X,
-            Y,
-            Z;
-
-          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
-          ConvertXYZToLuv(X,Y,Z,&L,&u,&v);
-          SetPixelRed(image,ClampToQuantum(QuantumRange*L),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*u),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*v),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 RGBColorspace:
-    {
-      /*
-        Transform image from sRGB to linear RGB.
-      */
-      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,
-            green,
-            red;
-
-          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          SetPixelRed(image,ClampToQuantum(red),q);
-          SetPixelGreen(image,ClampToQuantum(green),q);
-          SetPixelBlue(image,ClampToQuantum(blue),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 XYZColorspace:
-    {
-      /*
-        Transform image from sRGB to XYZ.
-      */
-      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,
-            green,
-            red,
-            X,
-            Y,
-            Z;
-
-          red=DecodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=DecodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=DecodePixelGamma((MagickRealType) GetPixelBlue(image,q));
-          ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
-          SetPixelRed(image,ClampToQuantum(QuantumRange*X),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*Y),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*Z),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);
-    }
-    default:
-      break;
-  }
-  /*
-    Allocate the tables.
-  */
-  x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
-    sizeof(*x_map));
-  y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
-    sizeof(*y_map));
-  z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
-    sizeof(*z_map));
-  if ((x_map == (TransformPacket *) NULL) ||
-      (y_map == (TransformPacket *) NULL) ||
-      (z_map == (TransformPacket *) NULL))
-    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
-      image->filename);
-  (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
-  switch (colorspace)
-  {
-    case OHTAColorspace:
-    {
-      /*
-        Initialize OHTA tables:
-
-          I1 = 0.33333*R+0.33334*G+0.33333*B
-          I2 = 0.50000*R+0.00000*G-0.50000*B
-          I3 =-0.25000*R+0.50000*G-0.25000*B
-
-        I and Q, normally -0.5 through 0.5, are normalized to the range 0
-        through QuantumRange.
-      */
-      primary_info.y=(double) (MaxMap+1.0f)/2.0f;
-      primary_info.z=(double) (MaxMap+1.0f)/2.0f;
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=(MagickRealType) (0.33333f*(float) i);
-        y_map[i].x=(MagickRealType) (0.33334f*(float) i);
-        z_map[i].x=(MagickRealType) (0.33333f*(float) i);
-        x_map[i].y=(MagickRealType) (0.50000f*(float) i);
-        y_map[i].y=(MagickRealType) (0.00000f*(float) i);
-        z_map[i].y=(MagickRealType) (-0.50000f*(float) i);
-        x_map[i].z=(MagickRealType) (-0.25000f*(float) i);
-        y_map[i].z=(MagickRealType) (0.50000f*(float) i);
-        z_map[i].z=(MagickRealType) (-0.25000f*(float) i);
-      }
-      break;
-    }
-    case Rec601LumaColorspace:
-    {
-      /*
-        Initialize Rec601 luma tables:
-
-          G = 0.298839*R+0.586811*G+0.114350*B
-      */
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=(MagickRealType) (0.298839f*(float) i);
-        y_map[i].x=(MagickRealType) (0.586811f*(float) i);
-        z_map[i].x=(MagickRealType) (0.114350f*(float) i);
-        x_map[i].y=(MagickRealType) (0.298839f*(float) i);
-        y_map[i].y=(MagickRealType) (0.586811f*(float) i);
-        z_map[i].y=(MagickRealType) (0.114350f*(float) i);
-        x_map[i].z=(MagickRealType) (0.298839f*(float) i);
-        y_map[i].z=(MagickRealType) (0.586811f*(float) i);
-        z_map[i].z=(MagickRealType) (0.114350f*(float) i);
-      }
-      break;
-    }
-    case Rec601YCbCrColorspace:
-    case YCbCrColorspace:
-    {
-      /*
-        Initialize YCbCr tables (ITU-R BT.601):
-
-          Y =  0.298839f0*R+0.586811f0*G+0.114350f0*B
-          Cb= -0.1687367*R-0.3312640*G+0.5000000*B
-          Cr=  0.5000000*R-0.4186880*G-0.0813120*B
-
-        Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
-        through QuantumRange.
-      */
-      primary_info.y=(double) (MaxMap+1.0f)/2.0f;
-      primary_info.z=(double) (MaxMap+1.0f)/2.0f;
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=(MagickRealType) (0.298839f*(float) i);
-        y_map[i].x=(MagickRealType) (0.586811f*(float) i);
-        z_map[i].x=(MagickRealType) (0.114350f*(float) i);
-        x_map[i].y=(MagickRealType) (-0.1687367f*(float) i);
-        y_map[i].y=(MagickRealType) (-0.331264f*(float) i);
-        z_map[i].y=(MagickRealType) (0.500000f*(float) i);
-        x_map[i].z=(MagickRealType) (0.500000f*(float) i);
-        y_map[i].z=(MagickRealType) (-0.418688f*(float) i);
-        z_map[i].z=(MagickRealType) (-0.081312f*(float) i);
-      }
-      break;
-    }
-    case Rec709LumaColorspace:
-    {
-      /*
-        Initialize Rec709 luma tables:
-
-          G = 0.21260*R+0.71520*G+0.07220*B
-      */
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=(MagickRealType) (0.21260f*(float) i);
-        y_map[i].x=(MagickRealType) (0.71520f*(float) i);
-        z_map[i].x=(MagickRealType) (0.07220f*(float) i);
-        x_map[i].y=(MagickRealType) (0.21260f*(float) i);
-        y_map[i].y=(MagickRealType) (0.71520f*(float) i);
-        z_map[i].y=(MagickRealType) (0.07220f*(float) i);
-        x_map[i].z=(MagickRealType) (0.21260f*(float) i);
-        y_map[i].z=(MagickRealType) (0.71520f*(float) i);
-        z_map[i].z=(MagickRealType) (0.07220f*(float) i);
-      }
-      break;
-    }
-    case Rec709YCbCrColorspace:
-    {
-      /*
-        Initialize YCbCr tables (ITU-R BT.709):
-
-          Y =  0.212600*R+0.715200*G+0.072200*B
-          Cb= -0.114572*R-0.385428*G+0.500000*B
-          Cr=  0.500000*R-0.454153*G-0.045847*B
-
-        Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
-        through QuantumRange.
-      */
-      primary_info.y=(double) (MaxMap+1.0f)/2.0f;
-      primary_info.z=(double) (MaxMap+1.0f)/2.0f;
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=(MagickRealType) (0.212600f*(float) i);
-        y_map[i].x=(MagickRealType) (0.715200f*(float) i);
-        z_map[i].x=(MagickRealType) (0.072200f*(float) i);
-        x_map[i].y=(MagickRealType) (-0.114572f*(float) i);
-        y_map[i].y=(MagickRealType) (-0.385428f*(float) i);
-        z_map[i].y=(MagickRealType) (0.500000f*(float) i);
-        x_map[i].z=(MagickRealType) (0.500000f*(float) i);
-        y_map[i].z=(MagickRealType) (-0.454153f*(float) i);
-        z_map[i].z=(MagickRealType) (-0.045847f*(float) i);
-      }
-      break;
-    }
-    case YCCColorspace:
-    {
-      /*
-        Initialize YCC tables:
-
-          Y =  0.298839f*R+0.586811f*G+0.114350f*B
-          C1= -0.298839f*R-0.586811f*G+0.88600*B
-          C2=  0.70100*R-0.586811f*G-0.114350f*B
-
-        YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
-      */
-      primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
-      primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
-      for (i=0; i <= (ssize_t) (0.018f*MaxMap); i++)
-      {
-        x_map[i].x=0.003962014134275617*i;
-        y_map[i].x=0.007778268551236748*i;
-        z_map[i].x=0.001510600706713781*i;
-        x_map[i].y=(-0.002426619775463276)*i;
-        y_map[i].y=(-0.004763965913702149)*i;
-        z_map[i].y=0.007190585689165425*i;
-        x_map[i].z=0.006927257754597858*i;
-        y_map[i].z=(-0.005800713697502058)*i;
-        z_map[i].z=(-0.0011265440570958)*i;
-      }
-      for ( ; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=0.2201118963486454*(1.099*i-0.099);
-        y_map[i].x=0.4321260306242638*(1.099*i-0.099);
-        z_map[i].x=0.08392226148409894*(1.099*i-0.099);
-        x_map[i].y=(-0.1348122097479598)*(1.099*i-0.099);
-        y_map[i].y=(-0.2646647729834528)*(1.099*i-0.099);
-        z_map[i].y=0.3994769827314126*(1.099*i-0.099);
-        x_map[i].z=0.3848476530332144*(1.099*i-0.099);
-        y_map[i].z=(-0.3222618720834477)*(1.099*i-0.099);
-        z_map[i].z=(-0.06258578094976668)*(1.099*i-0.099);
-      }
-      break;
-    }
-    case YIQColorspace:
-    {
-      /*
-        Initialize YIQ tables:
-
-          Y = 0.298839f*R+0.586811f*G+0.114350f*B
-          I = 0.595716*R-0.274453*G-0.321263*B
-          Q = 0.211456*R-0.522591*G+0.311135*B
-
-        I and Q, normally -0.5 through 0.5, are normalized to the range 0
-        through QuantumRange.
-      */
-      primary_info.y=(double) (MaxMap+1.0f)/2.0f;
-      primary_info.z=(double) (MaxMap+1.0f)/2.0f;
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=(MagickRealType) (0.298839f*(float) i);
-        y_map[i].x=(MagickRealType) (0.586811f*(float) i);
-        z_map[i].x=(MagickRealType) (0.114350f*(float) i);
-        x_map[i].y=(MagickRealType) (0.595716*(float) i);
-        y_map[i].y=(MagickRealType) (-0.274453f*(float) i);
-        z_map[i].y=(MagickRealType) (-0.321263f*(float) i);
-        x_map[i].z=(MagickRealType) (0.211456f*(float) i);
-        y_map[i].z=(MagickRealType) (-0.522591f*(float) i);
-        z_map[i].z=(MagickRealType) (0.311135f*(float) i);
-      }
-      break;
-    }
-    case YPbPrColorspace:
-    {
-      /*
-        Initialize YPbPr tables (ITU-R BT.601):
-
-          Y =  0.298839f0*R+0.586811f0*G+0.114350f0*B
-          Pb= -0.1687367*R-0.3312640*G+0.5000000*B
-          Pr=  0.5000000*R-0.4186880*G-0.0813120*B
-
-        Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0
-        through QuantumRange.
-      */
-      primary_info.y=(double) (MaxMap+1.0f)/2.0f;
-      primary_info.z=(double) (MaxMap+1.0f)/2.0f;
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=(MagickRealType) (0.298839f*(float) i);
-        y_map[i].x=(MagickRealType) (0.586811f*(float) i);
-        z_map[i].x=(MagickRealType) (0.114350f*(float) i);
-        x_map[i].y=(MagickRealType) (-0.1687367f*(float) i);
-        y_map[i].y=(MagickRealType) (-0.331264*(float) i);
-        z_map[i].y=(MagickRealType) (0.500000f*(float) i);
-        x_map[i].z=(MagickRealType) (0.500000f*(float) i);
-        y_map[i].z=(MagickRealType) (-0.418688f*(float) i);
-        z_map[i].z=(MagickRealType) (-0.081312f*(float) i);
-      }
-      break;
-    }
-    case YUVColorspace:
-    {
-      /*
-        Initialize YUV tables:
-
-          Y =  0.298839f*R+0.586811f*G+0.114350f*B
-          U = -0.147130*R-0.288860*G+0.436000*B
-          V =  0.615000*R-0.514990*G-0.100010*B
-
-        U and V, normally -0.5 through 0.5, are normalized to the range 0
-        through QuantumRange.  Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
-      */
-      primary_info.y=(double) (MaxMap+1.0f)/2.0f;
-      primary_info.z=(double) (MaxMap+1.0f)/2.0f;
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=(MagickRealType) (0.298839f*(float) i);
-        y_map[i].x=(MagickRealType) (0.586811f*(float) i);
-        z_map[i].x=(MagickRealType) (0.114350f*(float) i);
-        x_map[i].y=(MagickRealType) (-0.147130f*(float) i);
-        y_map[i].y=(MagickRealType) (-0.288860f*(float) i);
-        z_map[i].y=(MagickRealType) (0.436000f*(float) i);
-        x_map[i].z=(MagickRealType) (0.615000f*(float) i);
-        y_map[i].z=(MagickRealType) (-0.514990f*(float) i);
-        z_map[i].z=(MagickRealType) (-0.100001f*(float) i);
-      }
-      break;
-    }
-    default:
-    {
-      /*
-        Linear conversion tables.
-      */
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=(MagickRealType) (1.0*(float) i);
-        y_map[i].x=(MagickRealType) 0.0f;
-        z_map[i].x=(MagickRealType) 0.0f;
-        x_map[i].y=(MagickRealType) 0.0f;
-        y_map[i].y=(MagickRealType) (1.0*(float) i);
-        z_map[i].y=(MagickRealType) 0.0f;
-        x_map[i].z=(MagickRealType) 0.0f;
-        y_map[i].z=(MagickRealType) 0.0f;
-        z_map[i].z=(MagickRealType) (1.0*(float) i);
-      }
-      break;
-    }
-  }
-  /*
-    Convert from sRGB.
-  */
-  switch (image->storage_class)
-  {
-    case DirectClass:
-    default:
-    {
-      /*
-        Convert DirectClass image.
-      */
-      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;
-
-        PixelInfo
-          pixel;
-
-        register Quantum
-          *restrict q;
-
-        register ssize_t
-          x;
-
-        register unsigned int
-          blue,
-          green,
-          red;
-
-        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++)
-        {
-          red=ScaleQuantumToMap(ClampToQuantum(DecodePixelGamma(
-            (MagickRealType) GetPixelRed(image,q))));
-          green=ScaleQuantumToMap(ClampToQuantum(DecodePixelGamma(
-            (MagickRealType) GetPixelGreen(image,q))));
-          blue=ScaleQuantumToMap(ClampToQuantum(DecodePixelGamma(
-            (MagickRealType) GetPixelBlue(image,q))));
-          pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
-            primary_info.x;
-          pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
-            primary_info.y;
-          pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
-            primary_info.z;
-          SetPixelRed(image,ScaleMapToQuantum(pixel.red),q);
-          SetPixelGreen(image,ScaleMapToQuantum(pixel.green),q);
-          SetPixelBlue(image,ScaleMapToQuantum(pixel.blue),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-        if (image->progress_monitor != (MagickProgressMonitor) NULL)
-          {
-            MagickBooleanType
-              proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-            #pragma omp critical (MagickCore_sRGBTransformImage)
-#endif
-            proceed=SetImageProgress(image,sRGBTransformImageTag,progress++,
-              image->rows);
-            if (proceed == MagickFalse)
-              status=MagickFalse;
-          }
-      }
-      image_view=DestroyCacheView(image_view);
-      break;
-    }
-    case PseudoClass:
-    {
-      register unsigned int
-        blue,
-        green,
-        red;
-
-      /*
-        Convert PseudoClass image.
+        Convert PseudoClass image.
       */
       for (i=0; i < (ssize_t) image->colors; i++)
       {
         PixelInfo
           pixel;
 
-        red=ScaleQuantumToMap(ClampToQuantum(DecodePixelGamma(
-          image->colormap[i].red)));
-        green=ScaleQuantumToMap(ClampToQuantum(DecodePixelGamma(
-          image->colormap[i].green)));
-        blue=ScaleQuantumToMap(ClampToQuantum(DecodePixelGamma(
-          image->colormap[i].blue)));
+        red=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red));
+        green=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green));
+        blue=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue));
         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
@@ -1690,32 +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.000f;
+  image->gamma=1.000/2.200;
   (void) ResetMagickMemory(&image->chromaticity,0,sizeof(image->chromaticity));
-  if (IssRGBColorspace(colorspace) != MagickFalse)
+  type=image->type;
+  if (IsGrayColorspace(colorspace) != MagickFalse)
     {
-      image->rendering_intent=PerceptualIntent;
-      image->gamma=1.000f/2.200f;
-      image->chromaticity.red_primary.x=0.6400f;
-      image->chromaticity.red_primary.y=0.3300f;
-      image->chromaticity.red_primary.z=0.0300f;
-      image->chromaticity.green_primary.x=0.3000f;
-      image->chromaticity.green_primary.y=0.6000f;
-      image->chromaticity.green_primary.z=0.1000f;
-      image->chromaticity.blue_primary.x=0.1500f;
-      image->chromaticity.blue_primary.y=0.0600f;
-      image->chromaticity.blue_primary.z=0.7900f;
-      image->chromaticity.white_point.x=0.3127f;
-      image->chromaticity.white_point.y=0.3290f;
-      image->chromaticity.white_point.z=0.3583f;
+      if ((image->intensity == Rec601LuminancePixelIntensityMethod) ||
+          (image->intensity == Rec709LuminancePixelIntensityMethod))
+        image->gamma=1.000;
+      type=GrayscaleType;
     }
-  if (IsGrayColorspace(colorspace) != MagickFalse)
-    image->type=GrayscaleType;
-  return(SyncImagePixelCache(image,exception));
+  else
+    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
 /*
@@ -1756,20 +1137,23 @@ 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.
   */
   (void) DeleteImageProfile(image,"icc");
   (void) DeleteImageProfile(image,"icm");
   if (IssRGBColorspace(colorspace) != MagickFalse)
-    return(TransformsRGBImage(image,colorspace,exception));
+    return(TransformsRGBImage(image,exception));
   status=MagickTrue;
   if (IssRGBColorspace(image->colorspace) == MagickFalse)
-    status=TransformsRGBImage(image,image->colorspace,exception);
+    status=TransformsRGBImage(image,exception);
   if (status == MagickFalse)
     return(status);
   /*
@@ -1799,115 +1183,63 @@ MagickExport MagickBooleanType TransformImageColorspace(Image *image,
 %  The format of the TransformsRGBImage method is:
 %
 %      MagickBooleanType TransformsRGBImage(Image *image,
-%        const ColorspaceType colorspace,ExceptionInfo *exception)
+%        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
 %    o image: the image.
 %
-%    o colorspace: the colorspace to transform the image to.
-%
 %   o exception: return any errors or warnings in this structure.
 %
 */
 
+static inline void ConvertCMYToRGB(const double cyan,const double magenta,
+  const double yellow,double *red,double *green,double *blue)
+{
+  *red=QuantumRange*(1.0-cyan);
+  *green=QuantumRange*(1.0-magenta);
+  *blue=QuantumRange*(1.0-yellow);
+}
+
 static inline void ConvertLMSToXYZ(const double L,const double M,const double S,
   double *X,double *Y,double *Z)
 {
-  double
-    l,
-    m,
-    s;
-
-  assert(X != (double *) NULL);
-  assert(Y != (double *) NULL);
-  assert(Z != (double *) NULL);
-  l=QuantumScale*L;
-  m=QuantumScale*M;
-  s=QuantumScale*S;
-  *X=1.096123820835514*l-0.278869000218287*m+0.182745179382773*s;
-  *Y=0.454369041975359*l+0.473533154307412*m+0.072097803717229*s;
-  *Z=(-0.009627608738429)*l-0.005698031216113*m+1.015325639954543*s;
+  *X=1.096123820835514*L-0.278869000218287*M+0.182745179382773*S;
+  *Y=0.454369041975359*L+0.473533154307412*M+0.072097803717229*S;
+  *Z=(-0.009627608738429)*L-0.005698031216113*M+1.015325639954543*S;
 }
 
-static inline void ConvertLabToXYZ(const double L,const double a,const double b,
-  double *X,double *Y,double *Z)
+static inline void ConvertLMSToRGB(const double L,const double M,
+  const double S,double *red,double *green,double *blue)
 {
   double
-    x,
-    y,
-    z;
+    X,
+    Y,
+    Z;
 
-  assert(X != (double *) NULL);
-  assert(Y != (double *) NULL);
-  assert(Z != (double *) NULL);
-  y=(100.0f*L+16.0f)/116.0f;
-  x=y+255.0f*(a-0.5f)/500.0f;
-  z=y-255.0f*(b-0.5f)/200.0f;
-  if ((x*x*x) > CIEEpsilon)
-    x=(x*x*x);
-  else
-    x=(116.0f*x-16.0f)/CIEK;
-  if ((y*y*y) > CIEEpsilon)
-    y=(y*y*y);
-  else
-    y=(100.0f*L)/CIEK;
-  if ((z*z*z) > CIEEpsilon)
-    z=(z*z*z);
-  else
-    z=(116.0f*z-16.0f)/CIEK;
-  *X=D65X*x;
-  *Y=D65Y*y;
-  *Z=D65Z*z;
+  ConvertLMSToXYZ(L,M,S,&X,&Y,&Z);
+  ConvertXYZToRGB(X,Y,Z,red,green,blue);
 }
 
-static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
-  double *X,double *Y,double *Z)
+static inline void ConvertLuvToRGB(const double L,const double u,
+  const double v,double *red,double *green,double *blue)
 {
-  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);
+  double
+    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);
 }
 
 static inline ssize_t RoundToYCC(const double value)
 {
-  if (value <= 0.0f)
+  if (value <= 0.0)
     return(0);
-  if (value >= 1388.0f)
+  if (value >= 1388.0)
     return(1388);
-  return((ssize_t) (value+0.5f));
-}
-
-static inline void ConvertXYZToRGB(const double x,const double y,const double z,
-  double *red,double *green,double *blue)
-{
-  double
-    b,
-    g,
-    r;
-
-  /*
-    Convert XYZ to sRGB colorspace.
-  */
-  assert(red != (double *) NULL);
-  assert(green != (double *) NULL);
-  assert(blue != (double *) NULL);
-  r=3.2406f*x-1.5372f*y-0.4986f*z;
-  g=(-0.9689f*x+1.8758f*y+0.0415f*z);
-  b=0.0557f*x-0.2040f*y+1.0570f*z;
-  *red=QuantumRange*r;
-  *green=QuantumRange*g;
-  *blue=QuantumRange*b;
+  return((ssize_t) (value+0.5));
 }
 
 static inline void ConvertCMYKToRGB(PixelInfo *pixel)
@@ -1920,8 +1252,70 @@ static inline void ConvertCMYKToRGB(PixelInfo *pixel)
     (QuantumRange-pixel->black)+pixel->black)));
 }
 
+static inline void ConvertLabToRGB(const double L,const double a,
+  const double b,double *red,double *green,double *blue)
+{
+  double
+    X,
+    Y,
+    Z;
+
+  ConvertLabToXYZ(100.0*L,255.0*(a-0.5),255.0*(b-0.5),&X,&Y,&Z);
+  ConvertXYZToRGB(X,Y,Z,red,green,blue);
+}
+
+static void ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr,
+  double *red,double *green,double *blue)
+{
+  *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)-
+    0.71413649331646789076*(Pr-0.5));
+  *blue=QuantumRange*(1.00000124040004623180*Y+1.77200006607230409200*(Pb-0.5)+
+    2.1453384174593273e-06*(Pr-0.5));
+}
+
+static void ConvertYCbCrToRGB(const double Y,const double Cb,
+  const double Cr,double *red,double *green,double *blue)
+{
+  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)
+{
+  *red=QuantumRange*(Y+0.9562957197589482261*(I-0.5)+0.6210244164652610754*
+    (Q-0.5));
+  *green=QuantumRange*(Y-0.2721220993185104464*(I-0.5)-0.6473805968256950427*
+    (Q-0.5));
+  *blue=QuantumRange*(Y-1.1069890167364901945*(I-0.5)+1.7046149983646481374*
+    (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)
+{
+  *red=QuantumRange*(Y-3.945707070708279e-05*(U-0.5)+1.1398279671717170825*
+    (V-0.5));
+  *green=QuantumRange*(Y-0.3946101641414141437*(U-0.5)-0.5805003156565656797*
+    (V-0.5));
+  *blue=QuantumRange*(Y+2.0319996843434342537*(U-0.5)-4.813762626262513e-04*
+    (V-0.5));
+}
+
 static MagickBooleanType TransformsRGBImage(Image *image,
-  const ColorspaceType colorspace,ExceptionInfo *exception)
+  ExceptionInfo *exception)
 {
 #define TransformsRGBImageTag  "Transform/Image"
 
@@ -2129,455 +1523,74 @@ static MagickBooleanType TransformsRGBImage(Image *image,
       0.855908f, 0.856628f, 0.857349f, 0.858069f, 0.858790f, 0.859510f,
       0.860231f, 0.860951f, 0.861671f, 0.862392f, 0.863112f, 0.863833f,
       0.864553f, 0.865274f, 0.865994f, 0.866715f, 0.867435f, 0.868156f,
-      0.868876f, 0.869597f, 0.870317f, 0.871037f, 0.871758f, 0.872478f,
-      0.873199f, 0.873919f, 0.874640f, 0.875360f, 0.876081f, 0.876801f,
-      0.877522f, 0.878242f, 0.878963f, 0.879683f, 0.880403f, 0.881124f,
-      0.881844f, 0.882565f, 0.883285f, 0.884006f, 0.884726f, 0.885447f,
-      0.886167f, 0.886888f, 0.887608f, 0.888329f, 0.889049f, 0.889769f,
-      0.890490f, 0.891210f, 0.891931f, 0.892651f, 0.893372f, 0.894092f,
-      0.894813f, 0.895533f, 0.896254f, 0.896974f, 0.897695f, 0.898415f,
-      0.899135f, 0.899856f, 0.900576f, 0.901297f, 0.902017f, 0.902738f,
-      0.903458f, 0.904179f, 0.904899f, 0.905620f, 0.906340f, 0.907061f,
-      0.907781f, 0.908501f, 0.909222f, 0.909942f, 0.910663f, 0.911383f,
-      0.912104f, 0.912824f, 0.913545f, 0.914265f, 0.914986f, 0.915706f,
-      0.916427f, 0.917147f, 0.917867f, 0.918588f, 0.919308f, 0.920029f,
-      0.920749f, 0.921470f, 0.922190f, 0.922911f, 0.923631f, 0.924352f,
-      0.925072f, 0.925793f, 0.926513f, 0.927233f, 0.927954f, 0.928674f,
-      0.929395f, 0.930115f, 0.930836f, 0.931556f, 0.932277f, 0.932997f,
-      0.933718f, 0.934438f, 0.935158f, 0.935879f, 0.936599f, 0.937320f,
-      0.938040f, 0.938761f, 0.939481f, 0.940202f, 0.940922f, 0.941643f,
-      0.942363f, 0.943084f, 0.943804f, 0.944524f, 0.945245f, 0.945965f,
-      0.946686f, 0.947406f, 0.948127f, 0.948847f, 0.949568f, 0.950288f,
-      0.951009f, 0.951729f, 0.952450f, 0.953170f, 0.953891f, 0.954611f,
-      0.955331f, 0.956052f, 0.956772f, 0.957493f, 0.958213f, 0.958934f,
-      0.959654f, 0.960375f, 0.961095f, 0.961816f, 0.962536f, 0.963256f,
-      0.963977f, 0.964697f, 0.965418f, 0.966138f, 0.966859f, 0.967579f,
-      0.968300f, 0.969020f, 0.969741f, 0.970461f, 0.971182f, 0.971902f,
-      0.972622f, 0.973343f, 0.974063f, 0.974784f, 0.975504f, 0.976225f,
-      0.976945f, 0.977666f, 0.978386f, 0.979107f, 0.979827f, 0.980548f,
-      0.981268f, 0.981988f, 0.982709f, 0.983429f, 0.984150f, 0.984870f,
-      0.985591f, 0.986311f, 0.987032f, 0.987752f, 0.988473f, 0.989193f,
-      0.989914f, 0.990634f, 0.991354f, 0.992075f, 0.992795f, 0.993516f,
-      0.994236f, 0.994957f, 0.995677f, 0.996398f, 0.997118f, 0.997839f,
-      0.998559f, 0.999280f, 1.000000f
-    };
-
-  CacheView
-    *image_view;
-
-  MagickBooleanType
-    status;
-
-  MagickOffsetType
-    progress;
-
-  register ssize_t
-    i;
-
-  ssize_t
-    y;
-
-  TransformPacket
-    *y_map,
-    *x_map,
-    *z_map;
-
-  assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  status=MagickTrue;
-  progress=0;
-  switch (image->colorspace)
-  {
-    case CMYColorspace:
-    {
-      /*
-        Transform image from CMY to sRGB.
-      */
-      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
-            cyan,
-            magenta,
-            yellow;
-
-          cyan=EncodePixelGamma((MagickRealType) (QuantumRange-
-            GetPixelCyan(image,q)));
-          magenta=EncodePixelGamma((MagickRealType) (QuantumRange-
-            GetPixelMagenta(image,q)));
-          yellow=EncodePixelGamma((MagickRealType) (QuantumRange-
-            GetPixelYellow(image,q)));
-          SetPixelCyan(image,ClampToQuantum(cyan),q);
-          SetPixelMagenta(image,ClampToQuantum(magenta),q);
-          SetPixelYellow(image,ClampToQuantum(yellow),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
-    case CMYKColorspace:
-    {
-      PixelInfo
-        zero;
-
-      /*
-        Transform image from CMYK to sRGB.
-      */
-      if (image->storage_class == PseudoClass)
-        {
-          if (SyncImage(image,exception) == MagickFalse)
-            return(MagickFalse);
-          if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
-            return(MagickFalse);
-        }
-      GetPixelInfo(image,&zero);
-      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;
-
-        PixelInfo
-          pixel;
-
-        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;
-          }
-        pixel=zero;
-        for (x=0; x < (ssize_t) image->columns; x++)
-        {
-          GetPixelInfoPixel(image,q,&pixel);
-          ConvertCMYKToRGB(&pixel);
-          pixel.red=EncodePixelGamma(pixel.red);
-          pixel.green=EncodePixelGamma(pixel.green);
-          pixel.blue=EncodePixelGamma(pixel.blue);
-          SetPixelInfoPixel(image,&pixel,q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
-    case GRAYColorspace:
-    case Rec601LumaColorspace:
-    case Rec709LumaColorspace:
-    {
-      /*
-        Transform linear GRAY to sRGB colorspace.
-      */
-      if (image->storage_class == PseudoClass)
-        {
-          if (SyncImage(image,exception) == MagickFalse)
-            return(MagickFalse);
-          if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
-            return(MagickFalse);
-        }
-      if (SetImageColorspace(image,sRGBColorspace,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=(ssize_t) image->columns; x != 0; x--)
-        {
-          double
-            gray;
-
-          gray=EncodePixelGamma((MagickRealType) GetPixelGray(image,q));
-          SetPixelRed(image,ClampToQuantum(gray),q);
-          SetPixelGreen(image,ClampToQuantum(gray),q);
-          SetPixelBlue(image,ClampToQuantum(gray),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
-    case HCLColorspace:
-    {
-      /*
-        Transform image from HCL to sRGB.
-      */
-      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;
+      0.868876f, 0.869597f, 0.870317f, 0.871037f, 0.871758f, 0.872478f,
+      0.873199f, 0.873919f, 0.874640f, 0.875360f, 0.876081f, 0.876801f,
+      0.877522f, 0.878242f, 0.878963f, 0.879683f, 0.880403f, 0.881124f,
+      0.881844f, 0.882565f, 0.883285f, 0.884006f, 0.884726f, 0.885447f,
+      0.886167f, 0.886888f, 0.887608f, 0.888329f, 0.889049f, 0.889769f,
+      0.890490f, 0.891210f, 0.891931f, 0.892651f, 0.893372f, 0.894092f,
+      0.894813f, 0.895533f, 0.896254f, 0.896974f, 0.897695f, 0.898415f,
+      0.899135f, 0.899856f, 0.900576f, 0.901297f, 0.902017f, 0.902738f,
+      0.903458f, 0.904179f, 0.904899f, 0.905620f, 0.906340f, 0.907061f,
+      0.907781f, 0.908501f, 0.909222f, 0.909942f, 0.910663f, 0.911383f,
+      0.912104f, 0.912824f, 0.913545f, 0.914265f, 0.914986f, 0.915706f,
+      0.916427f, 0.917147f, 0.917867f, 0.918588f, 0.919308f, 0.920029f,
+      0.920749f, 0.921470f, 0.922190f, 0.922911f, 0.923631f, 0.924352f,
+      0.925072f, 0.925793f, 0.926513f, 0.927233f, 0.927954f, 0.928674f,
+      0.929395f, 0.930115f, 0.930836f, 0.931556f, 0.932277f, 0.932997f,
+      0.933718f, 0.934438f, 0.935158f, 0.935879f, 0.936599f, 0.937320f,
+      0.938040f, 0.938761f, 0.939481f, 0.940202f, 0.940922f, 0.941643f,
+      0.942363f, 0.943084f, 0.943804f, 0.944524f, 0.945245f, 0.945965f,
+      0.946686f, 0.947406f, 0.948127f, 0.948847f, 0.949568f, 0.950288f,
+      0.951009f, 0.951729f, 0.952450f, 0.953170f, 0.953891f, 0.954611f,
+      0.955331f, 0.956052f, 0.956772f, 0.957493f, 0.958213f, 0.958934f,
+      0.959654f, 0.960375f, 0.961095f, 0.961816f, 0.962536f, 0.963256f,
+      0.963977f, 0.964697f, 0.965418f, 0.966138f, 0.966859f, 0.967579f,
+      0.968300f, 0.969020f, 0.969741f, 0.970461f, 0.971182f, 0.971902f,
+      0.972622f, 0.973343f, 0.974063f, 0.974784f, 0.975504f, 0.976225f,
+      0.976945f, 0.977666f, 0.978386f, 0.979107f, 0.979827f, 0.980548f,
+      0.981268f, 0.981988f, 0.982709f, 0.983429f, 0.984150f, 0.984870f,
+      0.985591f, 0.986311f, 0.987032f, 0.987752f, 0.988473f, 0.989193f,
+      0.989914f, 0.990634f, 0.991354f, 0.992075f, 0.992795f, 0.993516f,
+      0.994236f, 0.994957f, 0.995677f, 0.996398f, 0.997118f, 0.997839f,
+      0.998559f, 0.999280f, 1.000000f
+    };
 
-        register ssize_t
-          x;
+  CacheView
+    *image_view;
 
-        register Quantum
-          *restrict q;
+  MagickBooleanType
+    status;
 
-        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;
+  MagickOffsetType
+    progress;
 
-          hue=(double) (QuantumScale*GetPixelRed(image,q));
-          chroma=(double) (QuantumScale*GetPixelGreen(image,q));
-          luma=(double) (QuantumScale*GetPixelBlue(image,q));
-          ConvertHCLToRGB(hue,chroma,luma,&red,&green,&blue);
-          SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
-          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
-          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
-    case HSBColorspace:
-    {
-      /*
-        Transform image from HSB to sRGB.
-      */
-      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
+    i;
 
-        register ssize_t
-          x;
+  ssize_t
+    y;
 
-        register Quantum
-          *restrict q;
+  TransformPacket
+    *y_map,
+    *x_map,
+    *z_map;
 
-        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,
-            brightness,
-            green,
-            hue,
-            red,
-            saturation;
-
-          hue=(double) (QuantumScale*GetPixelRed(image,q));
-          saturation=(double) (QuantumScale*GetPixelGreen(image,q));
-          brightness=(double) (QuantumScale*GetPixelBlue(image,q));
-          ConvertHSBToRGB(hue,saturation,brightness,&red,&green,&blue);
-          SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
-          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
-          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
-    case HSLColorspace:
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  status=MagickTrue;
+  progress=0;
+  switch (image->colorspace)
+  {
+    case CMYKColorspace:
     {
-      /*
-        Transform image from HSL to sRGB.
-      */
-      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;
+      PixelInfo
+        zero;
 
-        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,
-            green,
-            hue,
-            lightness,
-            red,
-            saturation;
-
-          hue=(double) (QuantumScale*GetPixelRed(image,q));
-          saturation=(double) (QuantumScale*GetPixelGreen(image,q));
-          lightness=(double) (QuantumScale*GetPixelBlue(image,q));
-          ConvertHSLToRGB(hue,saturation,lightness,&red,&green,&blue);
-          SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
-          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
-          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
-    case HWBColorspace:
-    {
       /*
-        Transform image from HWB to sRGB.
+        Transform image from CMYK to sRGB.
       */
       if (image->storage_class == PseudoClass)
         {
@@ -2586,6 +1599,7 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
             return(MagickFalse);
         }
+      GetPixelInfo(image,&zero);
       image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
       #pragma omp parallel for schedule(static,4) shared(status) \
@@ -2596,70 +1610,8 @@ static MagickBooleanType TransformsRGBImage(Image *image,
         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
-            blackness,
-            blue,
-            green,
-            hue,
-            red,
-            whiteness;
-
-          hue=(double) (QuantumScale*GetPixelRed(image,q));
-          whiteness=(double) (QuantumScale*GetPixelGreen(image,q));
-          blackness=(double) (QuantumScale*GetPixelBlue(image,q));
-          ConvertHWBToRGB(hue,whiteness,blackness,&red,&green,&blue);
-          SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
-          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
-          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
-    case LabColorspace:
-    {
-      /*
-        Transform image from Lab to sRGB.
-      */
-      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;
+        PixelInfo
+          pixel;
 
         register ssize_t
           x;
@@ -2676,27 +1628,12 @@ static MagickBooleanType TransformsRGBImage(Image *image,
             status=MagickFalse;
             continue;
           }
+        pixel=zero;
         for (x=0; x < (ssize_t) image->columns; x++)
-        {
-          double
-            a,
-            b,
-            blue,
-            green,
-            L,
-            red,
-            X,
-            Y,
-            Z;
-
-          L=QuantumScale*GetPixelRed(image,q);
-          a=QuantumScale*GetPixelGreen(image,q);
-          b=QuantumScale*GetPixelBlue(image,q);
-          ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
-          ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
-          SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
-          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
-          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),q);
+        {
+          GetPixelInfoPixel(image,q,&pixel);
+          ConvertCMYKToRGB(&pixel);
+          SetPixelInfoPixel(image,&pixel,q);
           q+=GetPixelChannels(image);
         }
         sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -2708,10 +1645,10 @@ static MagickBooleanType TransformsRGBImage(Image *image,
         return(MagickFalse);
       return(status);
     }
-    case LCHColorspace:
+    case GRAYColorspace:
     {
       /*
-        Transform image from LCH to sRGB.
+        Transform linear GRAY to sRGB colorspace.
       */
       if (image->storage_class == PseudoClass)
         {
@@ -2720,6 +1657,8 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
             return(MagickFalse);
         }
+      if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
+        return(MagickFalse);
       image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
       #pragma omp parallel for schedule(static,4) shared(status) \
@@ -2745,31 +1684,18 @@ static MagickBooleanType TransformsRGBImage(Image *image,
             status=MagickFalse;
             continue;
           }
-        for (x=0; x < (ssize_t) image->columns; x++)
+        for (x=(ssize_t) image->columns; x != 0; x--)
         {
-          double
-            a,
-            b,
-            blue,
-            C,
-            green,
-            H,
-            L,
-            red,
-            X,
-            Y,
-            Z;
+          MagickRealType
+            gray;
 
-          L=QuantumScale*GetPixelRed(image,q);
-          C=QuantumScale*GetPixelGreen(image,q);
-          H=QuantumScale*GetPixelBlue(image,q);
-          a=C*cos(H*(MagickPI/180.0f));
-          b=C*sin(H*(MagickPI/180.0f));
-          ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
-          ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
-          SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
-          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
-          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),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);
           q+=GetPixelChannels(image);
         }
         sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -2781,10 +1707,29 @@ static MagickBooleanType TransformsRGBImage(Image *image,
         return(MagickFalse);
       return(status);
     }
+    case CMYColorspace:
+    case HCLColorspace:
+    case HCLpColorspace:
+    case HSBColorspace:
+    case HSIColorspace:
+    case HSLColorspace:
+    case HSVColorspace:
+    case HWBColorspace:
+    case LabColorspace:
+    case LCHColorspace:
+    case LCHabColorspace:
+    case LCHuvColorspace:
     case LMSColorspace:
+    case LuvColorspace:
+    case XYZColorspace:
+    case YCbCrColorspace:
+    case YDbDrColorspace:
+    case YIQColorspace:
+    case YPbPrColorspace:
+    case YUVColorspace:
     {
       /*
-        Transform image from LMS to sRGB.
+        Transform image from source colorspace to sRGB.
       */
       if (image->storage_class == PseudoClass)
         {
@@ -2823,22 +1768,123 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           double
             blue,
             green,
-            L,
-            M,
             red,
-            S,
             X,
             Y,
             Z;
 
-          L=QuantumScale*GetPixelRed(image,q);
-          M=QuantumScale*GetPixelGreen(image,q);
-          S=QuantumScale*GetPixelBlue(image,q);
-          ConvertLMSToXYZ(L,M,S,&X,&Y,&Z);
-          ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
-          SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
-          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
-          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),q);
+          X=QuantumScale*GetPixelRed(image,q);
+          Y=QuantumScale*GetPixelGreen(image,q);
+          Z=QuantumScale*GetPixelBlue(image,q);
+          switch (image->colorspace)
+          {
+            case CMYColorspace:
+            {
+              ConvertCMYToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case HCLColorspace:
+            {
+              ConvertHCLToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case HCLpColorspace:
+            {
+              ConvertHCLpToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case HSBColorspace:
+            {
+              ConvertHSBToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case HSIColorspace:
+            {
+              ConvertHSIToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case HSLColorspace:
+            {
+              ConvertHSLToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case HSVColorspace:
+            {
+              ConvertHSVToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case HWBColorspace:
+            {
+              ConvertHWBToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case LabColorspace:
+            {
+              ConvertLabToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case LCHColorspace:
+            case LCHabColorspace:
+            {
+              ConvertLCHabToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case LCHuvColorspace:
+            {
+              ConvertLCHuvToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case LMSColorspace:
+            {
+              ConvertLMSToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case LuvColorspace:
+            {
+              ConvertLuvToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case XYZColorspace:
+            {
+              ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case YCbCrColorspace:
+            {
+              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);
+              break;
+            }
+            case YPbPrColorspace:
+            {
+              ConvertYPbPrToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            case YUVColorspace:
+            {
+              ConvertYUVToRGB(X,Y,Z,&red,&green,&blue);
+              break;
+            }
+            default:
+            {
+              red=QuantumRange*X;
+              green=QuantumRange*Y;
+              blue=QuantumRange*Z;
+              break;
+            }
+          }
+          SetPixelRed(image,ClampToQuantum(red),q);
+          SetPixelGreen(image,ClampToQuantum(green),q);
+          SetPixelBlue(image,ClampToQuantum(blue),q);
           q+=GetPixelChannels(image);
         }
         sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -2891,13 +1937,13 @@ static MagickBooleanType TransformsRGBImage(Image *image,
       if (logmap == (Quantum *) NULL)
         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
           image->filename);
-      black=pow(10.0,(reference_black-reference_white)*(gamma/density)*0.002f/
+      black=pow(10.0,(reference_black-reference_white)*(gamma/density)*0.002/
         film_gamma);
-      for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0f); i++)
+      for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
         logmap[i]=(Quantum) 0;
-      for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0f); i++)
-        logmap[i]=ClampToQuantum(QuantumRange/(1.0f-black)*
-          (pow(10.0,(1024.0*i/MaxMap-reference_white)*(gamma/density)*0.002f/
+      for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0); i++)
+        logmap[i]=ClampToQuantum(QuantumRange/(1.0-black)*
+          (pow(10.0,(1024.0*i/MaxMap-reference_white)*(gamma/density)*0.002/
           film_gamma)-black));
       for ( ; i <= (ssize_t) MaxMap; i++)
         logmap[i]=QuantumRange;
@@ -2940,15 +1986,15 @@ static MagickBooleanType TransformsRGBImage(Image *image,
             green,
             red;
 
-          red=EncodePixelGamma((MagickRealType) logmap[ScaleQuantumToMap(
-            GetPixelRed(image,q))]);
-          green=EncodePixelGamma((MagickRealType) logmap[ScaleQuantumToMap(
-            GetPixelGreen(image,q))]);
-          blue=EncodePixelGamma((MagickRealType) logmap[ScaleQuantumToMap(
-            GetPixelBlue(image,q))]);
-          SetPixelRed(image,ClampToQuantum(red),q);
-          SetPixelGreen(image,ClampToQuantum(green),q);
-          SetPixelBlue(image,ClampToQuantum(blue),q);
+          red=(double) logmap[ScaleQuantumToMap(GetPixelRed(image,q))];
+          green=(double) logmap[ScaleQuantumToMap(GetPixelGreen(image,q))];
+          blue=(double) logmap[ScaleQuantumToMap(GetPixelBlue(image,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);
@@ -2961,76 +2007,8 @@ static MagickBooleanType TransformsRGBImage(Image *image,
         return(MagickFalse);
       return(status);
     }
-    case LuvColorspace:
-    {
-      /*
-        Transform image from Luv to sRGB.
-      */
-      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,
-            green,
-            L,
-            red,
-            u,
-            v,
-            X,
-            Y,
-            Z;
-
-          L=QuantumScale*GetPixelRed(image,q);
-          u=QuantumScale*GetPixelGreen(image,q);
-          v=QuantumScale*GetPixelBlue(image,q);
-          ConvertLuvToXYZ(L,u,v,&X,&Y,&Z);
-          ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
-          SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
-          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
-          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
     case RGBColorspace:
+    case scRGBColorspace:
     {
       /*
         Transform linear RGB to sRGB colorspace.
@@ -3091,71 +2069,6 @@ static MagickBooleanType TransformsRGBImage(Image *image,
         return(MagickFalse);
       return(status);
     }
-    case XYZColorspace:
-    {
-      /*
-        Transform image from XYZ to sRGB.
-      */
-      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,
-            green,
-            red,
-            X,
-            Y,
-            Z;
-
-          X=QuantumScale*GetPixelRed(image,q);
-          Y=QuantumScale*GetPixelGreen(image,q);
-          Z=QuantumScale*GetPixelBlue(image,q);
-          ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
-          SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
-          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
-          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-      }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
-    }
     default:
       break;
   }
@@ -3188,6 +2101,9 @@ static MagickBooleanType TransformsRGBImage(Image *image,
       /*
         Initialize OHTA tables:
 
+          I1 = 0.33333*R+0.33334*G+0.33333*B
+          I2 = 0.50000*R+0.00000*G-0.50000*B
+          I3 =-0.25000*R+0.50000*G-0.25000*B
           R = I1+1.00000*I2-0.66668*I3
           G = I1+0.00000*I2+1.33333*I3
           B = I1-1.00000*I2-0.66668*I3
@@ -3201,20 +2117,19 @@ static MagickBooleanType TransformsRGBImage(Image *image,
 #endif
       for (i=0; i <= (ssize_t) MaxMap; i++)
       {
-        x_map[i].x=(MagickRealType) (1.0f*(float) i);
-        y_map[i].x=(MagickRealType) (0.5f*(2.0f*(float) i-MaxMap));
-        z_map[i].x=(MagickRealType) ((-0.333340f)*(2.0f*(float) i-MaxMap));
-        x_map[i].y=(MagickRealType) (1.0f*(float) i);
-        y_map[i].y=(MagickRealType) 0.000000f;
-        z_map[i].y=(MagickRealType) (0.666665f*(2.0f*(float) i-MaxMap));
-        x_map[i].z=(MagickRealType) (1.0f*(float) i);
-        y_map[i].z=(MagickRealType) (-0.500000f*(2.0f*(float) i-MaxMap));
-        z_map[i].z=(MagickRealType) (-0.333340f*(2.0f*(float) i-MaxMap));
+        x_map[i].x=(MagickRealType) (1.0*(double) i);
+        y_map[i].x=(MagickRealType) (0.5*1.00000*(2.0*(double) i-MaxMap));
+        z_map[i].x=(MagickRealType) (-0.5*0.66668*(2.0*(double) i-MaxMap));
+        x_map[i].y=(MagickRealType) (1.0*(double) i);
+        y_map[i].y=(MagickRealType) (0.5*0.00000*(2.0*(double) i-MaxMap));
+        z_map[i].y=(MagickRealType) (0.5*1.33333*(2.0*(double) i-MaxMap));
+        x_map[i].z=(MagickRealType) (1.0*(double) i);
+        y_map[i].z=(MagickRealType) (-0.5*1.00000*(2.0*(double) i-MaxMap));
+        z_map[i].z=(MagickRealType) (-0.5*0.66668*(2.0*(double) i-MaxMap));
       }
       break;
     }
     case Rec601YCbCrColorspace:
-    case YCbCrColorspace:
     {
       /*
         Initialize YCbCr tables:
@@ -3232,15 +2147,15 @@ static MagickBooleanType TransformsRGBImage(Image *image,
 #endif
       for (i=0; i <= (ssize_t) MaxMap; i++)
       {
-        x_map[i].x=0.99999999999914679361*i;
-        y_map[i].x=(1.2188941887145875e-06)*i;
-        z_map[i].x=0.5f*1.4019995886561440468*(2.00f*i-MaxMap);
-        x_map[i].y=0.99999975910502514331*i;
-        y_map[i].y=0.5f*(-0.34413567816504303521)*(2.00f*i-MaxMap);
-        z_map[i].y=0.5f*(-0.71413649331646789076)*(2.00f*i-MaxMap);
-        x_map[i].z=1.00000124040004623180*i;
-        y_map[i].z=0.5f*1.77200006607230409200*(2.00f*i-MaxMap);
-        z_map[i].z=2.1453384174593273e-06*i;
+        x_map[i].x=0.99999999999914679361*(double) i;
+        y_map[i].x=0.5*(-1.2188941887145875e-06)*(2.00*(double) i-MaxMap);
+        z_map[i].x=0.5*1.4019995886561440468*(2.00*(double) i-MaxMap);
+        x_map[i].y=0.99999975910502514331*(double) i;
+        y_map[i].y=0.5*(-0.34413567816504303521)*(2.00*(double) i-MaxMap);
+        z_map[i].y=0.5*(-0.71413649331646789076)*(2.00*(double) i-MaxMap);
+        x_map[i].z=1.00000124040004623180*(double) i;
+        y_map[i].z=0.5*1.77200006607230409200*(2.00*(double) i-MaxMap);
+        z_map[i].z=0.5*2.1453384174593273e-06*(2.00*(double) i-MaxMap);
       }
       break;
     }
@@ -3262,15 +2177,15 @@ static MagickBooleanType TransformsRGBImage(Image *image,
 #endif
       for (i=0; i <= (ssize_t) MaxMap; i++)
       {
-        x_map[i].x=(MagickRealType) (1.0f*i);
-        y_map[i].x=(MagickRealType) (0.000000f*(2.0f*i-MaxMap));
-        z_map[i].x=(MagickRealType) (0.5f*1.574800f*(2.0f*i-MaxMap));
-        x_map[i].y=(MagickRealType) (1.0f*i);
-        y_map[i].y=(MagickRealType) (0.5f*(-0.187324f)*(2.0f*i-MaxMap));
-        z_map[i].y=(MagickRealType) (0.5f*(-0.468124f)*(2.0f*i-MaxMap));
-        x_map[i].z=(MagickRealType) (1.0f*i);
-        y_map[i].z=(MagickRealType) (0.5f*1.855600f*(2.0f*i-MaxMap));
-        z_map[i].z=(MagickRealType) (0.000000f*(2.0f*i-MaxMap));
+        x_map[i].x=(MagickRealType) (1.0*i);
+        y_map[i].x=(MagickRealType) (0.5*0.000000*(2.0*i-MaxMap));
+        z_map[i].x=(MagickRealType) (0.5*1.574800*(2.0*i-MaxMap));
+        x_map[i].y=(MagickRealType) (1.0*i);
+        y_map[i].y=(MagickRealType) (0.5*(-0.187324)*(2.0*i-MaxMap));
+        z_map[i].y=(MagickRealType) (0.5*(-0.468124)*(2.0*i-MaxMap));
+        x_map[i].z=(MagickRealType) (1.0*i);
+        y_map[i].z=(MagickRealType) (0.5*1.855600*(2.0*i-MaxMap));
+        z_map[i].z=(MagickRealType) (0.5*0.000000*(2.0*i-MaxMap));
       }
       break;
     }
@@ -3291,109 +2206,19 @@ static MagickBooleanType TransformsRGBImage(Image *image,
 #endif
       for (i=0; i <= (ssize_t) MaxMap; i++)
       {
-        x_map[i].x=(MagickRealType) (1.3584000f*(float) i);
-        y_map[i].x=(MagickRealType) 0.0000000f;
-        z_map[i].x=(MagickRealType) (1.8215000f*(1.0f*(float) i-(double)
+        x_map[i].x=(MagickRealType) (1.3584000*(double) i);
+        y_map[i].x=(MagickRealType) 0.0000000;
+        z_map[i].x=(MagickRealType) (1.8215000*(1.0*(double) i-(double)
           ScaleQuantumToMap(ScaleCharToQuantum(137))));
-        x_map[i].y=(MagickRealType) (1.3584000f*(float) i);
-        y_map[i].y=(MagickRealType) (-0.4302726f*(1.0f*(float) i-(double)
+        x_map[i].y=(MagickRealType) (1.3584000*(double) i);
+        y_map[i].y=(MagickRealType) (-0.4302726*(1.0*(double) i-(double)
           ScaleQuantumToMap(ScaleCharToQuantum(156))));
-        z_map[i].y=(MagickRealType) (-0.9271435f*(1.0f*(float) i-(double)
+        z_map[i].y=(MagickRealType) (-0.9271435*(1.0*(double) i-(double)
           ScaleQuantumToMap(ScaleCharToQuantum(137))));
-        x_map[i].z=(MagickRealType) (1.3584000f*(float) i);
-        y_map[i].z=(MagickRealType) (2.2179000f*(1.0f*(float) i-(double)
+        x_map[i].z=(MagickRealType) (1.3584000*(double) i);
+        y_map[i].z=(MagickRealType) (2.2179000*(1.0*(double) i-(double)
           ScaleQuantumToMap(ScaleCharToQuantum(156))));
-        z_map[i].z=(MagickRealType) 0.0000000f;
-      }
-      break;
-    }
-    case YIQColorspace:
-    {
-      /*
-        Initialize YIQ tables:
-
-          R = Y+0.95620*I+0.62140*Q
-          G = Y-0.27270*I-0.64680*Q
-          B = Y-1.10370*I+1.70060*Q
-
-        I and Q, normally -0.5 through 0.5, must be normalized to the range 0
-        through QuantumRange.
-      */
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=1.0f*i;
-        y_map[i].x=0.5f*0.9562957197589482261*(2.00000f*i-MaxMap);
-        z_map[i].x=0.5f*0.6210244164652610754*(2.00000f*i-MaxMap);
-        x_map[i].y=1.0f*i;
-        y_map[i].y=0.5f*(-0.2721220993185104464)*(2.00000f*i-MaxMap);
-        z_map[i].y=0.5f*(-0.6473805968256950427)*(2.00000f*i-MaxMap);
-        x_map[i].z=1.0f*i;
-        y_map[i].z=0.5f*(-1.1069890167364901945)*(2.00000f*i-MaxMap);
-        z_map[i].z=0.5f*1.7046149983646481374*(2.00000f*i-MaxMap);
-      }
-      break;
-    }
-    case YPbPrColorspace:
-    {
-      /*
-        Initialize YPbPr tables:
-
-          R = Y            +1.402000*C2
-          G = Y-0.344136*C1+0.714136*C2
-          B = Y+1.772000*C1
-
-        Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
-        through QuantumRange.
-      */
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=0.99999999999914679361*i;
-        y_map[i].x=(-1.2188941887145875e-06)*(2.0f*i-MaxMap);
-        z_map[i].x=0.5f*1.4019995886561440468*(2.0f*i-MaxMap);
-        x_map[i].y=0.99999975910502514331*i;
-        y_map[i].y=0.5f*(-0.34413567816504303521)*(2.0f*i-MaxMap);
-        z_map[i].y=0.5f*(-0.71413649331646789076)*(2.0f*i-MaxMap);
-        x_map[i].z=1.00000124040004623180*i;
-        y_map[i].z=0.5f*1.77200006607230409200*(2.0f*i-MaxMap);
-        z_map[i].z=2.1453384174593273e-06*(2.0f*i-MaxMap);
-      }
-      break;
-    }
-    case YUVColorspace:
-    {
-      /*
-        Initialize YUV tables:
-
-          R = Y         +1.13983*V
-          G = Y-0.39464*U-0.58060*V
-          B = Y+2.03211*U
-
-        U and V, normally -0.5 through 0.5, must be normalized to the range 0
-        through QuantumRange.
-      */
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) \
-        magick_threads(image,image,1,1)
-#endif
-      for (i=0; i <= (ssize_t) MaxMap; i++)
-      {
-        x_map[i].x=1.0f*i;
-        y_map[i].x=(-3.945707070708279e-05)*(2.0f*i-MaxMap);
-        z_map[i].x=0.5f*1.1398279671717170825*(2.0f*i-MaxMap);
-        x_map[i].y=1.0f*i;
-        y_map[i].y=0.5f*(-0.3946101641414141437)*(2.0f*i-MaxMap);
-        z_map[i].y=0.5f*(-0.5805003156565656797)*(2.0f*i-MaxMap);
-        x_map[i].z=1.0f*i;
-        y_map[i].z=0.5f*2.0319996843434342537*(2.0f*i-MaxMap);
-        z_map[i].z=(-4.813762626262513e-04)*(2.0f*i-MaxMap);
+        z_map[i].z=(MagickRealType) 0.0000000;
       }
       break;
     }
@@ -3408,15 +2233,15 @@ static MagickBooleanType TransformsRGBImage(Image *image,
 #endif
       for (i=0; i <= (ssize_t) MaxMap; i++)
       {
-        x_map[i].x=(MagickRealType) (1.0*(float) i);
+        x_map[i].x=(MagickRealType) (1.0*(double) i);
         y_map[i].x=(MagickRealType) 0.0;
         z_map[i].x=(MagickRealType) 0.0;
         x_map[i].y=(MagickRealType) 0.0;
-        y_map[i].y=(MagickRealType) (1.0*(float) i);
+        y_map[i].y=(MagickRealType) (1.0*(double) i);
         z_map[i].y=(MagickRealType) 0.0;
         x_map[i].z=(MagickRealType) 0.0;
         y_map[i].z=(MagickRealType) 0.0;
-        z_map[i].z=(MagickRealType) (1.0*(float) i);
+        z_map[i].z=(MagickRealType) (1.0*(double) i);
       }
       break;
     }
@@ -3475,21 +2300,18 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
           if (image->colorspace == YCCColorspace)
             {
-              pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.red/
+              pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.red/
                 (double) MaxMap)];
-              pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.green/
+              pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.green/
                 (double) MaxMap)];
-              pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.blue/
+              pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.blue/
                 (double) MaxMap)];
             }
           else
             {
-              pixel.red=EncodePixelGamma((MagickRealType)
-                ScaleMapToQuantum(pixel.red));
-              pixel.green=EncodePixelGamma((MagickRealType)
-                ScaleMapToQuantum(pixel.green));
-              pixel.blue=EncodePixelGamma((MagickRealType)
-                ScaleMapToQuantum(pixel.blue));
+              pixel.red=(MagickRealType) ScaleMapToQuantum(pixel.red);
+              pixel.green=(MagickRealType) ScaleMapToQuantum(pixel.green);
+              pixel.blue=(MagickRealType) ScaleMapToQuantum(pixel.blue);
             }
           SetPixelRed(image,ClampToQuantum(pixel.red),q);
           SetPixelGreen(image,ClampToQuantum(pixel.green),q);
@@ -3543,21 +2365,18 @@ static MagickBooleanType TransformsRGBImage(Image *image,
         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
         if (image->colorspace == YCCColorspace)
           {
-            pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.red/
+            pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.red/
               (double) MaxMap)];
-            pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.green/
+            pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.green/
               (double) MaxMap)];
-            pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.blue/
+            pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*pixel.blue/
               (double) MaxMap)];
           }
         else
           {
-            pixel.red=EncodePixelGamma((MagickRealType)
-              ScaleMapToQuantum(pixel.red));
-            pixel.green=EncodePixelGamma((MagickRealType)
-              ScaleMapToQuantum(pixel.green));
-            pixel.blue=EncodePixelGamma((MagickRealType)
-              ScaleMapToQuantum(pixel.blue));
+            pixel.red=(MagickRealType) ScaleMapToQuantum(pixel.red);
+            pixel.green=(MagickRealType) ScaleMapToQuantum(pixel.green);
+            pixel.blue=(MagickRealType) ScaleMapToQuantum(pixel.blue);
           }
         image->colormap[i].red=(double) ClampToQuantum(pixel.red);
         image->colormap[i].green=(double) ClampToQuantum(pixel.green);