]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/colorspace.c
Fixed detection of Ghostscript location.
[imagemagick] / MagickCore / colorspace.c
index 3bf5b7a0215b74f5ffc1c1a3a28a8f70ef23e338..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  %
@@ -115,57 +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.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;
-  *L=QuantumRange*l;
-  *M=QuantumRange*m;
-  *S=QuantumRange*s;
+  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+  ConvertXYZToLMS(X,Y,Z,L,M,S);
+}
+
+static void ConvertRGBToLab(const double red,const double green,
+  const double blue,double *L,double *a,double *b)
+{
+  double
+    X,
+    Y,
+    Z;
+
+  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+  ConvertXYZToLab(X,Y,Z,L,a,b);
+}
+
+static void ConvertRGBToLuv(const double red,const double green,
+  const double blue,double *L,double *u,double *v)
+{
+  double
+    X,
+    Y,
+    Z;
+
+  ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
+  ConvertXYZToLuv(X,Y,Z,L,u,v);
+}
+
+static void ConvertRGBToYDbDr(const double red,const double green,
+  const double blue,double *Y,double *Db,double *Dr)
+{
+  *Y=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
+  *Db=QuantumScale*(-0.450*red-0.883*green+1.333*blue)+0.5;
+  *Dr=QuantumScale*(-1.333*red+1.116*green+0.217*blue)+0.5;
+}
+
+static void ConvertRGBToYIQ(const double red,const double green,
+  const double blue,double *Y,double *I,double *Q)
+{
+  *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)
 {
-  /*
-    Convert RGB to YPbPr colorspace.
-  */
-  assert(Y != (double *) NULL);
-  assert(Pb != (double *) NULL);
-  assert(Pr != (double *) NULL);
-  *Y=0.298839*QuantumScale*red+0.586811*QuantumScale*green+0.114350*
-    QuantumScale*blue;
-  *Pb=(-0.1687367)*QuantumScale*red-0.331264*QuantumScale*green+0.5*
-    QuantumScale*blue;
-  *Pr=0.5*QuantumScale*red-0.418688*QuantumScale*green-0.081312*
-    QuantumScale*blue;
+  *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)
 {
-  /*
-    Convert RGB to -YCbCr colorspace.
-  */
-  assert(Y != (double *) NULL);
-  assert(Cb != (double *) NULL);
-  assert(Cr != (double *) NULL);
   ConvertRGBToYPbPr(red,green,blue,Y,Cb,Cr);
-  *Cb+=0.5;
-  *Cr+=0.5;
+}
+
+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,
@@ -207,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=(MagickRealType) GetPixelCyan(image,q);
-          magenta=(MagickRealType) GetPixelMagenta(image,q);
-          yellow=(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
@@ -387,6 +361,7 @@ static MagickBooleanType sRGBTransformImage(Image *image,
       image->type=GrayscaleType;
       return(status);
     }
+    case CMYColorspace:
     case HCLColorspace:
     case HCLpColorspace:
     case HSBColorspace:
@@ -394,6 +369,18 @@ static MagickBooleanType sRGBTransformImage(Image *image,
     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 target colorspace.
@@ -445,6 +432,11 @@ static MagickBooleanType sRGBTransformImage(Image *image,
           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);
@@ -480,8 +472,69 @@ static MagickBooleanType sRGBTransformImage(Image *image,
               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);
@@ -497,18 +550,62 @@ static MagickBooleanType sRGBTransformImage(Image *image,
         return(MagickFalse);
       return(status);
     }
-    case LabColorspace:
+    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 Lab.
+        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) \
@@ -534,27 +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
-            a,
-            b,
             blue,
             green,
-            L,
-            red,
-            X,
-            Y,
-            Z;
+            red;
 
-          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);
+          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);
@@ -562,15 +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 LCHColorspace:
-    case LCHabColorspace:
+    case RGBColorspace:
+    case scRGBColorspace:
     {
       /*
-        Transform image from sRGB to LCHab.
+        Transform image from sRGB to linear RGB.
       */
       if (image->storage_class == PseudoClass)
         {
@@ -608,19 +702,15 @@ static MagickBooleanType sRGBTransformImage(Image *image,
         {
           double
             blue,
-            chroma,
             green,
-            hue,
-            luma,
             red;
 
-          red=(double) GetPixelRed(image,q);
-          green=(double) GetPixelGreen(image,q);
-          blue=(double) GetPixelBlue(image,q);
-          ConvertRGBToLCHab(red,green,blue,&luma,&chroma,&hue);
-          SetPixelRed(image,ClampToQuantum(QuantumRange*luma),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*chroma),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*hue),q);
+          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);
@@ -632,83 +722,196 @@ static MagickBooleanType sRGBTransformImage(Image *image,
         return(MagickFalse);
       return(status);
     }
-    case LCHuvColorspace:
+    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 LCHuv.
+        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;
+        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);
+      }
+      break;
+    }
+    case Rec601YCbCrColorspace:
+    {
+      /*
+        Initialize YCbCr tables (ITU-R BT.601):
 
-        register ssize_t
-          x;
+          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
 
-        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.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):
 
-        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;
+          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
 
-          red=(double) GetPixelRed(image,q);
-          green=(double) GetPixelGreen(image,q);
-          blue=(double) GetPixelBlue(image,q);
-          ConvertRGBToLCHuv(red,green,blue,&luma,&chroma,&hue);
-          SetPixelRed(image,ClampToQuantum(QuantumRange*luma),q);
-          SetPixelGreen(image,ClampToQuantum(QuantumRange*chroma),q);
-          SetPixelBlue(image,ClampToQuantum(QuantumRange*hue),q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
+        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);
       }
-      image_view=DestroyCacheView(image_view);
-      if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
+      break;
     }
-    case LMSColorspace:
+    case YCCColorspace:
     {
       /*
-        Transform image from sRGB to LMS.
+        Initialize YCC tables:
+
+          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
+
+        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;
+      }
+      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;
+    }
+    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*(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) \
@@ -719,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,
@@ -736,972 +947,380 @@ static MagickBooleanType sRGBTransformImage(Image *image,
           }
         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);
+          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 LogColorspace:
+    case PseudoClass:
     {
-#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;
+      register unsigned int
+        blue,
+        green,
+        red;
 
       /*
-        Transform RGB to Log colorspace.
+        Convert PseudoClass image.
       */
-      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) \
-        magick_threads(image,image,image->rows,1)
-#endif
-      for (y=0; y < (ssize_t) image->rows; y++)
+      for (i=0; i < (ssize_t) image->colors; 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=(ssize_t) image->columns; x != 0; x--)
-        {
-          double
-            blue,
-            green,
-            red;
+        PixelInfo
+          pixel;
 
-          red=(double) GetPixelRed(image,q);
-          green=(double) GetPixelGreen(image,q);
-          blue=(double) 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;
+        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;
+        image->colormap[i].red=(double) ScaleMapToQuantum(pixel.red);
+        image->colormap[i].green=(double) ScaleMapToQuantum(pixel.green);
+        image->colormap[i].blue=(double) ScaleMapToQuantum(pixel.blue);
       }
-      image_view=DestroyCacheView(image_view);
-      logmap=(Quantum *) RelinquishMagickMemory(logmap);
-      if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
-        return(MagickFalse);
-      return(status);
+      (void) SyncImage(image,exception);
+      break;
     }
-    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;
+  }
+  /*
+    Relinquish resources.
+  */
+  z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
+  y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
+  x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
+  if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
+    return(MagickFalse);
+  return(status);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   S e t I m a g e C o l o r s p a c e                                       %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  SetImageColorspace() sets the colorspace member of the Image structure.
+%
+%  The format of the SetImageColorspace method is:
+%
+%      MagickBooleanType SetImageColorspace(Image *image,
+%        const ColorspaceType colorspace,ExceptiionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o colorspace: the colorspace.
+%
+%   o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport MagickBooleanType SetImageColorspace(Image *image,
+  const ColorspaceType colorspace,ExceptionInfo *exception)
+{
+  ImageType
+    type;
 
-        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;
+  MagickBooleanType
+    status;
 
-          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:
-    case scRGBColorspace:
+  if (image->colorspace == colorspace)
+    return(MagickTrue);
+  image->colorspace=colorspace;
+  image->rendering_intent=UndefinedIntent;
+  image->gamma=1.000/2.200;
+  (void) ResetMagickMemory(&image->chromaticity,0,sizeof(image->chromaticity));
+  type=image->type;
+  if (IsGrayColorspace(colorspace) != MagickFalse)
     {
-      /*
-        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++)
+      if ((image->intensity == Rec601LuminancePixelIntensityMethod) ||
+          (image->intensity == Rec709LuminancePixelIntensityMethod))
+        image->gamma=1.000;
+      type=GrayscaleType;
+    }
+  else
+    if ((IsRGBColorspace(colorspace) != MagickFalse) ||
+        (colorspace == XYZColorspace))
+      image->gamma=1.000;
+    else
       {
-        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->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;
       }
-      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;
+  status=SyncImagePixelCache(image,exception);
+  image->type=type;
+  return(status);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   T r a n s f o r m I m a g e C o l o r s p a c e                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  TransformImageColorspace() transforms an image colorspace, changing the
+%  image data to reflect the new colorspace.
+%
+%  The format of the TransformImageColorspace method is:
+%
+%      MagickBooleanType TransformImageColorspace(Image *image,
+%        const ColorspaceType colorspace,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o colorspace: the colorspace.
+%
+%   o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport MagickBooleanType TransformImageColorspace(Image *image,
+  const ColorspaceType colorspace,ExceptionInfo *exception)
+{
+  MagickBooleanType
+    status;
 
-        register ssize_t
-          x;
+  assert(image != (Image *) NULL);
+  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));
+  /*
+    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,exception));
+  status=MagickTrue;
+  if (IssRGBColorspace(image->colorspace) == MagickFalse)
+    status=TransformsRGBImage(image,exception);
+  if (status == MagickFalse)
+    return(status);
+  /*
+    Convert the reference image from sRGB to an alternate colorspace.
+  */
+  if (sRGBTransformImage(image,colorspace,exception) == MagickFalse)
+    status=MagickFalse;
+  return(status);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++     T r a n s f o r m s R G B I m a g e                                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  TransformsRGBImage() converts the reference image from an alternate
+%  colorspace to sRGB.  The transformation matrices are not the standard ones:
+%  the weights are rescaled to normalize the range of the transformed values
+%  to be [0..QuantumRange].
+%
+%  The format of the TransformsRGBImage method is:
+%
+%      MagickBooleanType TransformsRGBImage(Image *image,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%   o exception: return any errors or warnings in this structure.
+%
+*/
 
-        register Quantum
-          *restrict q;
+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);
+}
 
-        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;
+static inline void ConvertLMSToXYZ(const double L,const double M,const double S,
+  double *X,double *Y,double *Z)
+{
+  *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;
+}
 
-          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:
+static inline void ConvertLMSToRGB(const double L,const double M,
+  const double S,double *red,double *green,double *blue)
+{
+  double
+    X,
+    Y,
+    Z;
 
-          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
+  ConvertLMSToXYZ(L,M,S,&X,&Y,&Z);
+  ConvertXYZToRGB(X,Y,Z,red,green,blue);
+}
 
-        I and Q, 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.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);
-      }
-      break;
-    }
-    case Rec601YCbCrColorspace:
-    case YCbCrColorspace:
-    {
-      /*
-        Initialize YCbCr tables (ITU-R BT.601):
+static inline void ConvertLuvToRGB(const double L,const double u,
+  const double v,double *red,double *green,double *blue)
+{
+  double
+    X,
+    Y,
+    Z;
 
-          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
+  ConvertLuvToXYZ(100.0*L,354.0*u-134.0,262.0*v-140.0,&X,&Y,&Z);
+  ConvertXYZToRGB(X,Y,Z,red,green,blue);
+}
 
-        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.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):
+static inline ssize_t RoundToYCC(const double value)
+{
+  if (value <= 0.0)
+    return(0);
+  if (value >= 1388.0)
+    return(1388);
+  return((ssize_t) (value+0.5));
+}
 
-          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
+static inline void ConvertCMYKToRGB(PixelInfo *pixel)
+{
+  pixel->red=((QuantumRange-(QuantumScale*pixel->red*
+    (QuantumRange-pixel->black)+pixel->black)));
+  pixel->green=((QuantumRange-(QuantumScale*pixel->green*
+    (QuantumRange-pixel->black)+pixel->black)));
+  pixel->blue=((QuantumRange-(QuantumScale*pixel->blue*
+    (QuantumRange-pixel->black)+pixel->black)));
+}
 
-        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.212600*(double) i);
-        y_map[i].x=(MagickRealType) (0.715200*(double) i);
-        z_map[i].x=(MagickRealType) (0.072200*(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:
+static inline void ConvertLabToRGB(const double L,const double a,
+  const double b,double *red,double *green,double *blue)
+{
+  double
+    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
+  ConvertLabToXYZ(100.0*L,255.0*(a-0.5),255.0*(b-0.5),&X,&Y,&Z);
+  ConvertXYZToRGB(X,Y,Z,red,green,blue);
+}
 
-        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;
-      }
-      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:
+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));
+}
 
-          Y = 0.298839*R+0.586811*G+0.114350*B
-          I = 0.595716*R-0.274453*G-0.321263*B
-          Q = 0.211456*R-0.522591*G+0.311135*B
+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);
+}
 
-        I and Q, 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.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.595716*(double) i);
-        y_map[i].y=(MagickRealType) (-0.274453*(double) i);
-        z_map[i].y=(MagickRealType) (-0.321263*(double) i);
-        x_map[i].z=(MagickRealType) (0.211456*(double) i);
-        y_map[i].z=(MagickRealType) (-0.522591*(double) i);
-        z_map[i].z=(MagickRealType) (0.311135*(double) i);
-      }
-      break;
-    }
-    case YPbPrColorspace:
-    {
-      /*
-        Initialize YPbPr tables (ITU-R BT.601):
+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));
+}
 
-          Y =  0.2988390*R+0.5868110*G+0.1143500*B
-          Pb= -0.1687367*R-0.3312640*G+0.5000000*B
-          Pr=  0.5000000*R-0.4186880*G-0.0813120*B
+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));
+}
 
-        Pb and Pr, 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.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 YUVColorspace:
-    {
-      /*
-        Initialize YUV tables:
+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));
+}
 
-          Y =  0.298839*R+0.586811*G+0.114350*B
-          U = -0.147130*R-0.288860*G+0.436000*B
-          V =  0.615000*R-0.514990*G-0.100010*B
+static MagickBooleanType TransformsRGBImage(Image *image,
+  ExceptionInfo *exception)
+{
+#define TransformsRGBImageTag  "Transform/Image"
 
-        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.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.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.147130*(double) i);
-        y_map[i].y=(MagickRealType) (-0.288860*(double) i);
-        z_map[i].y=(MagickRealType) (0.436000*(double) i);
-        x_map[i].z=(MagickRealType) (0.615000*(double) i);
-        y_map[i].z=(MagickRealType) (-0.514990*(double) i);
-        z_map[i].z=(MagickRealType) (-0.100001*(double) 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*(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.
-      */
-      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((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);
-      break;
-    }
-    case PseudoClass:
-    {
-      register unsigned int
-        blue,
-        green,
-        red;
-
-      /*
-        Convert PseudoClass image.
-      */
-      for (i=0; i < (ssize_t) image->colors; i++)
-      {
-        PixelInfo
-          pixel;
-
-        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;
-        image->colormap[i].red=(double) ScaleMapToQuantum(pixel.red);
-        image->colormap[i].green=(double) ScaleMapToQuantum(pixel.green);
-        image->colormap[i].blue=(double) ScaleMapToQuantum(pixel.blue);
-      }
-      (void) SyncImage(image,exception);
-      break;
-    }
-  }
-  /*
-    Relinquish resources.
-  */
-  z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
-  y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
-  x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
-  if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
-    return(MagickFalse);
-  return(status);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%   S e t I m a g e C o l o r s p a c e                                       %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  SetImageColorspace() sets the colorspace member of the Image structure.
-%
-%  The format of the SetImageColorspace method is:
-%
-%      MagickBooleanType SetImageColorspace(Image *image,
-%        const ColorspaceType colorspace,ExceptiionInfo *exception)
-%
-%  A description of each parameter follows:
-%
-%    o image: the image.
-%
-%    o colorspace: the colorspace.
-%
-%   o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport MagickBooleanType SetImageColorspace(Image *image,
-  const ColorspaceType colorspace,ExceptionInfo *exception)
-{
-  if (image->colorspace == colorspace)
-    return(MagickTrue);
-  image->colorspace=colorspace;
-  image->rendering_intent=UndefinedIntent;
-  image->gamma=1.000;
-  (void) ResetMagickMemory(&image->chromaticity,0,sizeof(image->chromaticity));
-  if (IsGrayColorspace(colorspace) != MagickFalse)
-    {
-      if ((image->intensity != Rec601LuminancePixelIntensityMethod) &&
-          (image->intensity != Rec709LuminancePixelIntensityMethod) &&
-          (image->intensity != UndefinedPixelIntensityMethod))
-        image->gamma=1.000/2.200;
-      image->type=GrayscaleType;
-    }
-  else
-    if (IssRGBColorspace(colorspace) != MagickFalse)
-      image->gamma=1.000/2.200;
-  if (image->gamma == (1.000/2.200))
-    {
-      image->rendering_intent=PerceptualIntent;
-      image->gamma=1.000/2.200;
-      image->chromaticity.red_primary.x=0.6400;
-      image->chromaticity.red_primary.y=0.3300;
-      image->chromaticity.red_primary.z=0.0300;
-      image->chromaticity.green_primary.x=0.3000;
-      image->chromaticity.green_primary.y=0.6000;
-      image->chromaticity.green_primary.z=0.1000;
-      image->chromaticity.blue_primary.x=0.1500;
-      image->chromaticity.blue_primary.y=0.0600;
-      image->chromaticity.blue_primary.z=0.7900;
-      image->chromaticity.white_point.x=0.3127;
-      image->chromaticity.white_point.y=0.3290;
-      image->chromaticity.white_point.z=0.3583;
-    }
-  if (IsGrayColorspace(colorspace) != MagickFalse)
-    image->type=GrayscaleType;
-  return(SyncImagePixelCache(image,exception));
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%   T r a n s f o r m I m a g e C o l o r s p a c e                           %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  TransformImageColorspace() transforms an image colorspace, changing the
-%  image data to reflect the new colorspace.
-%
-%  The format of the TransformImageColorspace method is:
-%
-%      MagickBooleanType TransformImageColorspace(Image *image,
-%        const ColorspaceType colorspace,ExceptionInfo *exception)
-%
-%  A description of each parameter follows:
-%
-%    o image: the image.
-%
-%    o colorspace: the colorspace.
-%
-%   o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport MagickBooleanType TransformImageColorspace(Image *image,
-  const ColorspaceType colorspace,ExceptionInfo *exception)
-{
-  MagickBooleanType
-    status;
-
-  assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  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,exception));
-  status=MagickTrue;
-  if (IssRGBColorspace(image->colorspace) == MagickFalse)
-    status=TransformsRGBImage(image,exception);
-  if (status == MagickFalse)
-    return(status);
-  /*
-    Convert the reference image from sRGB to an alternate colorspace.
-  */
-  if (sRGBTransformImage(image,colorspace,exception) == MagickFalse)
-    status=MagickFalse;
-  return(status);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-+     T r a n s f o r m s R G B I m a g e                                     %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  TransformsRGBImage() converts the reference image from an alternate
-%  colorspace to sRGB.  The transformation matrices are not the standard ones:
-%  the weights are rescaled to normalize the range of the transformed values
-%  to be [0..QuantumRange].
-%
-%  The format of the TransformsRGBImage method is:
-%
-%      MagickBooleanType TransformsRGBImage(Image *image,
-%        ExceptionInfo *exception)
-%
-%  A description of each parameter follows:
-%
-%    o image: the image.
-%
-%   o exception: return any errors or warnings in this structure.
-%
-*/
-
-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;
-}
-
-static inline ssize_t RoundToYCC(const double value)
-{
-  if (value <= 0.0)
-    return(0);
-  if (value >= 1388.0)
-    return(1388);
-  return((ssize_t) (value+0.5));
-}
-
-static inline void ConvertCMYKToRGB(PixelInfo *pixel)
-{
-  pixel->red=((QuantumRange-(QuantumScale*pixel->red*
-    (QuantumRange-pixel->black)+pixel->black)));
-  pixel->green=((QuantumRange-(QuantumScale*pixel->green*
-    (QuantumRange-pixel->black)+pixel->black)));
-  pixel->blue=((QuantumRange-(QuantumScale*pixel->blue*
-    (QuantumRange-pixel->black)+pixel->black)));
-}
-
-static void ConvertYPbPrToRGB(const double Y,const double Pb,const double Pr,
-  double *red,double *green,double *blue)
-{
-  /*
-    Convert YPbPr to RGB colorspace.
-  */
-  assert(red != (double *) NULL);
-  assert(green != (double *) NULL);
-  assert(blue != (double *) NULL);
-  *red=QuantumRange*(0.99999999999914679361*Y-1.2188941887145875e-06*Pb+
-    1.4019995886561440468*Pr);
-  *green=QuantumRange*(0.99999975910502514331*Y-0.34413567816504303521*Pb-
-    0.71413649331646789076*Pr);
-  *blue=QuantumRange*(1.00000124040004623180*Y+1.77200006607230409200*Pb+
-    2.1453384174593273e-06*Pr);
-}
-
-static void ConvertYCbCrToRGB(const double Y,const double Cb,
-  const double Cr,double *red,double *green,double *blue)
-{
-  /*
-    Convert -YCbCr to RGB colorspace.
-  */
-  assert(red != (double *) NULL);
-  assert(green != (double *) NULL);
-  assert(blue != (double *) NULL);
-  ConvertYPbPrToRGB(Y,Cb-0.5,Cr-0.5,red,green,blue);
-}
-
-static MagickBooleanType TransformsRGBImage(Image *image,
-  ExceptionInfo *exception)
-{
-#define TransformsRGBImageTag  "Transform/Image"
-
-  static const float
-    YCCMap[1389] =
+  static const float
+    YCCMap[1389] =
     {
       0.000000f, 0.000720f, 0.001441f, 0.002161f, 0.002882f, 0.003602f,
       0.004323f, 0.005043f, 0.005764f, 0.006484f, 0.007205f, 0.007925f,
@@ -1909,557 +1528,69 @@ static MagickBooleanType TransformsRGBImage(Image *image,
       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=(MagickRealType) (QuantumRange-GetPixelCyan(image,q));
-          magenta=(MagickRealType) (QuantumRange-GetPixelMagenta(image,q));
-          yellow=(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);
-          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:
-    {
-      /*
-        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:
-    case HCLpColorspace:
-    case HSBColorspace:
-    case HSIColorspace:
-    case HSLColorspace:
-    case HSVColorspace:
-    case HWBColorspace:
-    {
-      /*
-        Transform image from source colorspace 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);
-          switch (image->colorspace)
-          {
-            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;
-            }
-            default:
-              break;
-          }
-          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,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;
-
-        register ssize_t
-          x;
+      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 Quantum
-          *restrict q;
+  CacheView
+    *image_view;
 
-        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;
+  MagickBooleanType
+    status;
 
-          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);
-          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 LCHColorspace:
-    case LCHabColorspace:
-    {
-      /*
-        Transform image from LCHab 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;
+  MagickOffsetType
+    progress;
 
-        register ssize_t
-          x;
+  register ssize_t
+    i;
 
-        register Quantum
-          *restrict q;
+  ssize_t
+    y;
 
-        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;
+  TransformPacket
+    *y_map,
+    *x_map,
+    *z_map;
 
-          luma=(double) (QuantumScale*GetPixelRed(image,q));
-          chroma=(double) (QuantumScale*GetPixelGreen(image,q));
-          hue=(double) (QuantumScale*GetPixelBlue(image,q));
-          ConvertLCHabToRGB(luma,chroma,hue,&red,&green,&blue);
-          SetPixelRed(image,ClampToQuantum(EncodePixelGamma(red)),q);
-          SetPixelGreen(image,ClampToQuantum(EncodePixelGamma(green)),q);
-          SetPixelBlue(image,ClampToQuantum(EncodePixelGamma(blue)),q);
-          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 LCHuvColorspace:
+  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 LCHuv 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,
-            chroma,
-            green,
-            hue,
-            luma,
-            red;
+      PixelInfo
+        zero;
 
-          luma=(double) (QuantumScale*GetPixelRed(image,q));
-          chroma=(double) (QuantumScale*GetPixelGreen(image,q));
-          hue=(double) (QuantumScale*GetPixelBlue(image,q));
-          ConvertLCHuvToRGB(luma,chroma,hue,&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 LMSColorspace:
-    {
       /*
-        Transform image from LMS to sRGB.
+        Transform image from CMYK to sRGB.
       */
       if (image->storage_class == PseudoClass)
         {
@@ -2468,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) \
@@ -2478,6 +1610,9 @@ static MagickBooleanType TransformsRGBImage(Image *image,
         MagickBooleanType
           sync;
 
+        PixelInfo
+          pixel;
+
         register ssize_t
           x;
 
@@ -2493,27 +1628,12 @@ static MagickBooleanType TransformsRGBImage(Image *image,
             status=MagickFalse;
             continue;
           }
+        pixel=zero;
         for (x=0; x < (ssize_t) image->columns; x++)
         {
-          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);
+          GetPixelInfoPixel(image,q,&pixel);
+          ConvertCMYKToRGB(&pixel);
+          SetPixelInfoPixel(image,&pixel,q);
           q+=GetPixelChannels(image);
         }
         sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -2525,57 +1645,11 @@ static MagickBooleanType TransformsRGBImage(Image *image,
         return(MagickFalse);
       return(status);
     }
-    case LogColorspace:
+    case GRAYColorspace:
     {
-      const char
-        *value;
-
-      double
-        black,
-        density,
-        film_gamma,
-        gamma,
-        reference_black,
-        reference_white;
-
-      Quantum
-        *logmap;
-
       /*
-        Transform Log to sRGB colorspace.
+        Transform linear GRAY to sRGB 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.002/
-        film_gamma);
-      for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
-        logmap[i]=(Quantum) 0;
-      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;
       if (image->storage_class == PseudoClass)
         {
           if (SyncImage(image,exception) == MagickFalse)
@@ -2583,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) \
@@ -2610,17 +1686,16 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           }
         for (x=(ssize_t) image->columns; x != 0; x--)
         {
-          double
-            blue,
-            green,
-            red;
+          MagickRealType
+            gray;
 
-          red=(double) logmap[ScaleQuantumToMap(GetPixelRed(image,q))];
-          green=(double) logmap[ScaleQuantumToMap(GetPixelGreen(image,q))];
-          blue=(double) logmap[ScaleQuantumToMap(GetPixelBlue(image,q))];
-          SetPixelRed(image,ClampToQuantum(red),q);
-          SetPixelGreen(image,ClampToQuantum(green),q);
-          SetPixelBlue(image,ClampToQuantum(blue),q);
+          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);
@@ -2628,15 +1703,33 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           status=MagickFalse;
       }
       image_view=DestroyCacheView(image_view);
-      logmap=(Quantum *) RelinquishMagickMemory(logmap);
       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
         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 Luv to sRGB.
+        Transform image from source colorspace to sRGB.
       */
       if (image->storage_class == PseudoClass)
         {
@@ -2675,22 +1768,123 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           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);
+          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);
@@ -2702,12 +1896,57 @@ static MagickBooleanType TransformsRGBImage(Image *image,
         return(MagickFalse);
       return(status);
     }
-    case RGBColorspace:
-    case scRGBColorspace:
+    case LogColorspace:
     {
+      const char
+        *value;
+
+      double
+        black,
+        density,
+        film_gamma,
+        gamma,
+        reference_black,
+        reference_white;
+
+      Quantum
+        *logmap;
+
       /*
-        Transform linear RGB to sRGB colorspace.
+        Transform Log to sRGB 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.002/
+        film_gamma);
+      for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
+        logmap[i]=(Quantum) 0;
+      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;
       if (image->storage_class == PseudoClass)
         {
           if (SyncImage(image,exception) == MagickFalse)
@@ -2747,12 +1986,15 @@ static MagickBooleanType TransformsRGBImage(Image *image,
             green,
             red;
 
-          red=EncodePixelGamma((MagickRealType) GetPixelRed(image,q));
-          green=EncodePixelGamma((MagickRealType) GetPixelGreen(image,q));
-          blue=EncodePixelGamma((MagickRealType) 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);
@@ -2760,14 +2002,16 @@ static MagickBooleanType TransformsRGBImage(Image *image,
           status=MagickFalse;
       }
       image_view=DestroyCacheView(image_view);
+      logmap=(Quantum *) RelinquishMagickMemory(logmap);
       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
         return(MagickFalse);
       return(status);
     }
-    case XYZColorspace:
+    case RGBColorspace:
+    case scRGBColorspace:
     {
       /*
-        Transform image from XYZ to sRGB.
+        Transform linear RGB to sRGB colorspace.
       */
       if (image->storage_class == PseudoClass)
         {
@@ -2801,23 +2045,19 @@ 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
             blue,
             green,
-            red,
-            X,
-            Y,
-            Z;
+            red;
 
-          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);
+          red=EncodePixelGamma((MagickRealType) GetPixelRed(image,q));
+          green=EncodePixelGamma((MagickRealType) GetPixelGreen(image,q));
+          blue=EncodePixelGamma((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);
@@ -2861,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
@@ -2887,7 +2130,6 @@ static MagickBooleanType TransformsRGBImage(Image *image,
       break;
     }
     case Rec601YCbCrColorspace:
-    case YCbCrColorspace:
     {
       /*
         Initialize YCbCr tables:
@@ -2980,96 +2222,6 @@ static MagickBooleanType TransformsRGBImage(Image *image,
       }
       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.0*(double) i;
-        y_map[i].x=0.5*0.9562957197589482261*(2.00000*(double) i-MaxMap);
-        z_map[i].x=0.5*0.6210244164652610754*(2.00000*(double) i-MaxMap);
-        x_map[i].y=1.0*(double) i;
-        y_map[i].y=0.5*(-0.2721220993185104464)*(2.00000*(double) i-MaxMap);
-        z_map[i].y=0.5*(-0.6473805968256950427)*(2.00000*(double) i-MaxMap);
-        x_map[i].z=1.0*(double) i;
-        y_map[i].z=0.5*(-1.1069890167364901945)*(2.00000*(double) i-MaxMap);
-        z_map[i].z=0.5*1.7046149983646481374*(2.00000*(double) 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*(double) i;
-        y_map[i].x=0.5*(-1.2188941887145875e-06)*(2.0*(double) i-MaxMap);
-        z_map[i].x=0.5*1.4019995886561440468*(2.0*(double) i-MaxMap);
-        x_map[i].y=0.99999975910502514331*(double) i;
-        y_map[i].y=0.5*(-0.34413567816504303521)*(2.0*(double) i-MaxMap);
-        z_map[i].y=0.5*(-0.71413649331646789076)*(2.0*(double) i-MaxMap);
-        x_map[i].z=1.00000124040004623180*(double) i;
-        y_map[i].z=0.5*1.77200006607230409200*(2.0*(double) i-MaxMap);
-        z_map[i].z=0.5*2.1453384174593273e-06*(2.0*(double) 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.0*(double) i;
-        y_map[i].x=0.5*(-3.945707070708279e-05)*(2.0*(double) i-MaxMap);
-        z_map[i].x=0.5*1.1398279671717170825*(2.0*(double) i-MaxMap);
-        x_map[i].y=1.0*(double) i;
-        y_map[i].y=0.5*(-0.3946101641414141437)*(2.0*(double) i-MaxMap);
-        z_map[i].y=0.5*(-0.5805003156565656797)*(2.0*(double) i-MaxMap);
-        x_map[i].z=1.0*(double) i;
-        y_map[i].z=0.5*2.0319996843434342537*(2.0*(double) i-MaxMap);
-        z_map[i].z=0.5*(-4.813762626262513e-04)*(2.0*(double) i-MaxMap);
-      }
-      break;
-    }
     default:
     {
       /*