MagickCore  6.7.5
colorspace.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %     CCCC   OOO   L       OOO   RRRR   SSSSS  PPPP    AAA    CCCC  EEEEE     %
00007 %    C      O   O  L      O   O  R   R  SS     P   P  A   A  C      E         %
00008 %    C      O   O  L      O   O  RRRR    SSS   PPPP   AAAAA  C      EEE       %
00009 %    C      O   O  L      O   O  R R       SS  P      A   A  C      E         %
00010 %     CCCC   OOO   LLLLL   OOO   R  R   SSSSS  P      A   A   CCCC  EEEEE     %
00011 %                                                                             %
00012 %                                                                             %
00013 %                     MagickCore Image Colorspace Methods                     %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                                John Cristy                                  %
00017 %                                 July 1992                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "MagickCore/studio.h"
00043 #include "MagickCore/property.h"
00044 #include "MagickCore/cache.h"
00045 #include "MagickCore/cache-private.h"
00046 #include "MagickCore/cache-view.h"
00047 #include "MagickCore/color.h"
00048 #include "MagickCore/color-private.h"
00049 #include "MagickCore/colorspace.h"
00050 #include "MagickCore/colorspace-private.h"
00051 #include "MagickCore/exception.h"
00052 #include "MagickCore/exception-private.h"
00053 #include "MagickCore/image.h"
00054 #include "MagickCore/image-private.h"
00055 #include "MagickCore/gem.h"
00056 #include "MagickCore/gem-private.h"
00057 #include "MagickCore/memory_.h"
00058 #include "MagickCore/monitor.h"
00059 #include "MagickCore/monitor-private.h"
00060 #include "MagickCore/pixel-accessor.h"
00061 #include "MagickCore/quantize.h"
00062 #include "MagickCore/quantum.h"
00063 #include "MagickCore/quantum-private.h"
00064 #include "MagickCore/string_.h"
00065 #include "MagickCore/string-private.h"
00066 #include "MagickCore/utility.h"
00067 
00068 /*
00069   Typedef declarations.
00070 */
00071 typedef struct _TransformPacket
00072 {
00073   MagickRealType
00074     x,
00075     y,
00076     z;
00077 } TransformPacket;
00078 
00079 /*
00080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00081 %                                                                             %
00082 %                                                                             %
00083 %                                                                             %
00084 +     R G B T r a n s f o r m I m a g e                                       %
00085 %                                                                             %
00086 %                                                                             %
00087 %                                                                             %
00088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00089 %
00090 %  RGBTransformImage() converts the reference image from RGB to an alternate
00091 %  colorspace.  The transformation matrices are not the standard ones: the
00092 %  weights are rescaled to normalized the range of the transformed values to
00093 %  be [0..QuantumRange].
00094 %
00095 %  The format of the RGBTransformImage method is:
00096 %
00097 %      MagickBooleanType RGBTransformImage(Image *image,
00098 %        const ColorspaceType colorspace,EsceptionInfo *exception)
00099 %
00100 %  A description of each parameter follows:
00101 %
00102 %    o image: the image.
00103 %
00104 %    o colorspace: the colorspace to transform the image to.
00105 %
00106 %   o exception: return any errors or warnings in this structure.
00107 %
00108 */
00109 
00110 static inline void ConvertRGBToXYZ(const Quantum red,const Quantum green,
00111   const Quantum blue,double *X,double *Y,double *Z)
00112 {
00113   double
00114     b,
00115     g,
00116     r;
00117 
00118   assert(X != (double *) NULL);
00119   assert(Y != (double *) NULL);
00120   assert(Z != (double *) NULL);
00121   r=QuantumScale*red;
00122   if (r > 0.04045)
00123     r=pow((r+0.055)/1.055,2.4);
00124   else
00125     r/=12.92;
00126   g=QuantumScale*green;
00127   if (g > 0.04045)
00128     g=pow((g+0.055)/1.055,2.4);
00129   else
00130     g/=12.92;
00131   b=QuantumScale*blue;
00132   if (b > 0.04045)
00133     b=pow((b+0.055)/1.055,2.4);
00134   else
00135     b/=12.92;
00136   *X=0.4124240*r+0.3575790*g+0.1804640*b;
00137   *Y=0.2126560*r+0.7151580*g+0.0721856*b;
00138   *Z=0.0193324*r+0.1191930*g+0.9504440*b;
00139 }
00140 
00141 static double LabF1(double alpha)
00142 {
00143 
00144   if (alpha <= ((24.0/116.0)*(24.0/116.0)*(24.0/116.0)))
00145     return((841.0/108.0)*alpha+(16.0/116.0));
00146   return(pow(alpha,1.0/3.0));
00147 }
00148 
00149 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
00150   double *L,double *a,double *b)
00151 {
00152 #define D50X  (0.9642)
00153 #define D50Y  (1.0)
00154 #define D50Z  (0.8249)
00155 
00156   double
00157     fx,
00158     fy,
00159     fz;
00160 
00161   assert(L != (double *) NULL);
00162   assert(a != (double *) NULL);
00163   assert(b != (double *) NULL);
00164   *L=0.0;
00165   *a=0.5;
00166   *b=0.5;
00167   if ((fabs(X) < MagickEpsilon) && (fabs(Y) < MagickEpsilon) &&
00168       (fabs(Z) < MagickEpsilon))
00169     return;
00170   fx=LabF1(X/D50X);
00171   fy=LabF1(Y/D50Y);
00172   fz=LabF1(Z/D50Z);
00173   *L=(116.0*fy-16.0)/100.0;
00174   *a=(500.0*(fx-fy))/255.0;
00175   if (*a < 0.0)
00176     *a+=1.0;
00177   *b=(200.0*(fy-fz))/255.0;
00178   if (*b < 0.0)
00179     *b+=1.0;
00180 }
00181 
00182 MagickExport MagickBooleanType RGBTransformImage(Image *image,
00183   const ColorspaceType colorspace,ExceptionInfo *exception)
00184 {
00185 #define RGBTransformImageTag  "RGBTransform/Image"
00186 
00187   CacheView
00188     *image_view;
00189 
00190   MagickBooleanType
00191     status;
00192 
00193   MagickOffsetType
00194     progress;
00195 
00196   PrimaryInfo
00197     primary_info;
00198 
00199   register ssize_t
00200     i;
00201 
00202   ssize_t
00203     y;
00204 
00205   TransformPacket
00206     *x_map,
00207     *y_map,
00208     *z_map;
00209 
00210   assert(image != (Image *) NULL);
00211   assert(image->signature == MagickSignature);
00212   if (image->debug != MagickFalse)
00213     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00214   assert(colorspace != RGBColorspace);
00215   assert(colorspace != TransparentColorspace);
00216   assert(colorspace != UndefinedColorspace);
00217   if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
00218     return(MagickFalse);
00219   status=MagickTrue;
00220   progress=0;
00221   switch (colorspace)
00222   {
00223     case CMYColorspace:
00224     {
00225       /*
00226         Convert RGB to CMY colorspace.
00227       */
00228       if (image->storage_class == PseudoClass)
00229         {
00230           if (SyncImage(image,exception) == MagickFalse)
00231             return(MagickFalse);
00232           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
00233             return(MagickFalse);
00234         }
00235       image_view=AcquireCacheView(image);
00236 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00237       #pragma omp parallel for schedule(static,4) shared(status)
00238 #endif
00239       for (y=0; y < (ssize_t) image->rows; y++)
00240       {
00241         MagickBooleanType
00242           sync;
00243 
00244         register ssize_t
00245           x;
00246 
00247         register Quantum
00248           *restrict q;
00249 
00250         if (status == MagickFalse)
00251           continue;
00252         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00253           exception);
00254         if (q == (Quantum *) NULL)
00255           {
00256             status=MagickFalse;
00257             continue;
00258           }
00259         for (x=0; x < (ssize_t) image->columns; x++)
00260         {
00261           SetPixelRed(image,ClampToQuantum((MagickRealType) (QuantumRange-
00262             GetPixelRed(image,q))),q);
00263           SetPixelGreen(image,ClampToQuantum((MagickRealType) (QuantumRange-
00264             GetPixelGreen(image,q))),q);
00265           SetPixelBlue(image,ClampToQuantum((MagickRealType) (QuantumRange-
00266             GetPixelBlue(image,q))),q);
00267           q+=GetPixelChannels(image);
00268         }
00269         sync=SyncCacheViewAuthenticPixels(image_view,exception);
00270         if (sync == MagickFalse)
00271           status=MagickFalse;
00272       }
00273       image_view=DestroyCacheView(image_view);
00274       image->type=image->matte == MagickFalse ? ColorSeparationType :
00275         ColorSeparationMatteType;
00276       return(status);
00277     }
00278     case CMYKColorspace:
00279     {
00280       PixelInfo
00281         zero;
00282 
00283       /*
00284         Convert RGB to CMYK colorspace.
00285       */
00286       if (image->storage_class == PseudoClass)
00287         {
00288           if (SyncImage(image,exception) == MagickFalse)
00289             return(MagickFalse);
00290           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
00291             return(MagickFalse);
00292         }
00293       GetPixelInfo(image,&zero);
00294       image_view=AcquireCacheView(image);
00295 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00296       #pragma omp parallel for schedule(static,4) shared(status)
00297 #endif
00298       for (y=0; y < (ssize_t) image->rows; y++)
00299       {
00300         MagickBooleanType
00301           sync;
00302 
00303         PixelInfo
00304           pixel;
00305 
00306         register ssize_t
00307           x;
00308 
00309         register Quantum
00310           *restrict q;
00311 
00312         if (status == MagickFalse)
00313           continue;
00314         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00315           exception);
00316         if (q == (Quantum *) NULL)
00317           {
00318             status=MagickFalse;
00319             continue;
00320           }
00321         pixel=zero;
00322         for (x=0; x < (ssize_t) image->columns; x++)
00323         {
00324           GetPixelInfoPixel(image,q,&pixel);
00325           ConvertRGBToCMYK(&pixel);
00326           SetPixelInfoPixel(image,&pixel,q);
00327           q+=GetPixelChannels(image);
00328         }
00329         sync=SyncCacheViewAuthenticPixels(image_view,exception);
00330         if (sync == MagickFalse)
00331           status=MagickFalse;
00332       }
00333       image_view=DestroyCacheView(image_view);
00334       image->type=image->matte == MagickFalse ? ColorSeparationType :
00335         ColorSeparationMatteType;
00336       return(status);
00337     }
00338     case HSBColorspace:
00339     {
00340       /*
00341         Transform image from RGB to HSB.
00342       */
00343       if (image->storage_class == PseudoClass)
00344         {
00345           if (SyncImage(image,exception) == MagickFalse)
00346             return(MagickFalse);
00347           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
00348             return(MagickFalse);
00349         }
00350       image_view=AcquireCacheView(image);
00351 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00352       #pragma omp parallel for schedule(static,4) shared(status)
00353 #endif
00354       for (y=0; y < (ssize_t) image->rows; y++)
00355       {
00356         double
00357           brightness,
00358           hue,
00359           saturation;
00360 
00361         MagickBooleanType
00362           sync;
00363 
00364         register ssize_t
00365           x;
00366 
00367         register Quantum
00368           *restrict q;
00369 
00370         if (status == MagickFalse)
00371           continue;
00372         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00373           exception);
00374         if (q == (Quantum *) NULL)
00375           {
00376             status=MagickFalse;
00377             continue;
00378           }
00379         hue=0.0;
00380         saturation=0.0;
00381         brightness=0.0;
00382         for (x=0; x < (ssize_t) image->columns; x++)
00383         {
00384           ConvertRGBToHSB((double) GetPixelRed(image,q),
00385             (double) GetPixelGreen(image,q),(double) GetPixelBlue(image,q),
00386             &hue,&saturation,&brightness);
00387           SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
00388             hue),q);
00389           SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
00390             saturation),q);
00391           SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
00392             brightness),q);
00393           q+=GetPixelChannels(image);
00394         }
00395         sync=SyncCacheViewAuthenticPixels(image_view,exception);
00396         if (sync == MagickFalse)
00397           status=MagickFalse;
00398       }
00399       image_view=DestroyCacheView(image_view);
00400       return(status);
00401     }
00402     case HSLColorspace:
00403     {
00404       /*
00405         Transform image from RGB to HSL.
00406       */
00407       if (image->storage_class == PseudoClass)
00408         {
00409           if (SyncImage(image,exception) == MagickFalse)
00410             return(MagickFalse);
00411           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
00412             return(MagickFalse);
00413         }
00414       image_view=AcquireCacheView(image);
00415 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00416       #pragma omp parallel for schedule(static,4) shared(status)
00417 #endif
00418       for (y=0; y < (ssize_t) image->rows; y++)
00419       {
00420         double
00421           hue,
00422           lightness,
00423           saturation;
00424 
00425         MagickBooleanType
00426           sync;
00427 
00428         register ssize_t
00429           x;
00430 
00431         register Quantum
00432           *restrict q;
00433 
00434         if (status == MagickFalse)
00435           continue;
00436         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00437           exception);
00438         if (q == (Quantum *) NULL)
00439           {
00440             status=MagickFalse;
00441             continue;
00442           }
00443         hue=0.0;
00444         saturation=0.0;
00445         lightness=0.0;
00446         for (x=0; x < (ssize_t) image->columns; x++)
00447         {
00448           ConvertRGBToHSL((double) GetPixelRed(image,q),(double)
00449             GetPixelGreen(image,q),(double) GetPixelBlue(image,q),
00450             &hue,&saturation,&lightness);
00451           SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
00452             hue),q);
00453           SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
00454             saturation),q);
00455           SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
00456             lightness),q);
00457           q+=GetPixelChannels(image);
00458         }
00459         sync=SyncCacheViewAuthenticPixels(image_view,exception);
00460         if (sync == MagickFalse)
00461           status=MagickFalse;
00462       }
00463       image_view=DestroyCacheView(image_view);
00464       return(status);
00465     }
00466     case HWBColorspace:
00467     {
00468       /*
00469         Transform image from RGB to HWB.
00470       */
00471       if (image->storage_class == PseudoClass)
00472         {
00473           if (SyncImage(image,exception) == MagickFalse)
00474             return(MagickFalse);
00475           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
00476             return(MagickFalse);
00477         }
00478       image_view=AcquireCacheView(image);
00479 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00480       #pragma omp parallel for schedule(static,4) shared(status)
00481 #endif
00482       for (y=0; y < (ssize_t) image->rows; y++)
00483       {
00484         double
00485           blackness,
00486           hue,
00487           whiteness;
00488 
00489         MagickBooleanType
00490           sync;
00491 
00492         register ssize_t
00493           x;
00494 
00495         register Quantum
00496           *restrict q;
00497 
00498         if (status == MagickFalse)
00499           continue;
00500         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00501           exception);
00502         if (q == (Quantum *) NULL)
00503           {
00504             status=MagickFalse;
00505             continue;
00506           }
00507         hue=0.0;
00508         whiteness=0.0;
00509         blackness=0.0;
00510         for (x=0; x < (ssize_t) image->columns; x++)
00511         {
00512           ConvertRGBToHWB((double) GetPixelRed(image,q),(double)
00513             GetPixelGreen(image,q),(double) GetPixelBlue(image,q),
00514             &hue,&whiteness,&blackness);
00515           SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
00516             hue),q);
00517           SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
00518             whiteness),q);
00519           SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
00520             blackness),q);
00521           q+=GetPixelChannels(image);
00522         }
00523         sync=SyncCacheViewAuthenticPixels(image_view,exception);
00524         if (sync == MagickFalse)
00525           status=MagickFalse;
00526       }
00527       image_view=DestroyCacheView(image_view);
00528       return(status);
00529     }
00530     case LabColorspace:
00531     {
00532       /*
00533         Transform image from RGB to Lab.
00534       */
00535       if (image->storage_class == PseudoClass)
00536         {
00537           if (SyncImage(image,exception) == MagickFalse)
00538             return(MagickFalse);
00539           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
00540             return(MagickFalse);
00541         }
00542       image_view=AcquireCacheView(image);
00543 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00544       #pragma omp parallel for schedule(static,4) shared(status)
00545 #endif
00546       for (y=0; y < (ssize_t) image->rows; y++)
00547       {
00548         double
00549           a,
00550           b,
00551           L,
00552           X,
00553           Y,
00554           Z;
00555 
00556         MagickBooleanType
00557           sync;
00558 
00559         register ssize_t
00560           x;
00561 
00562         register Quantum
00563           *restrict q;
00564 
00565         if (status == MagickFalse)
00566           continue;
00567         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00568           exception);
00569         if (q == (Quantum *) NULL)
00570           {
00571             status=MagickFalse;
00572             continue;
00573           }
00574         L=0.0;
00575         a=0.0;
00576         b=0.0;
00577         X=0.0;
00578         Y=0.0;
00579         Z=0.0;
00580         for (x=0; x < (ssize_t) image->columns; x++)
00581         {
00582           ConvertRGBToXYZ(GetPixelRed(image,q),GetPixelGreen(image,q),
00583             GetPixelBlue(image,q),&X,&Y,&Z);
00584           ConvertXYZToLab(X,Y,Z,&L,&a,&b);
00585           SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
00586             L),q);
00587           SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
00588             a),q);
00589           SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
00590             b),q);
00591           q+=GetPixelChannels(image);
00592         }
00593         sync=SyncCacheViewAuthenticPixels(image_view,exception);
00594         if (sync == MagickFalse)
00595           status=MagickFalse;
00596       }
00597       image_view=DestroyCacheView(image_view);
00598       return(status);
00599     }
00600     case LogColorspace:
00601     {
00602 #define DisplayGamma  (1.0/1.7)
00603 #define FilmGamma  0.6
00604 #define ReferenceBlack  95.0
00605 #define ReferenceWhite  685.0
00606 
00607       const char
00608         *value;
00609 
00610       double
00611         black,
00612         density,
00613         film_gamma,
00614         gamma,
00615         reference_black,
00616         reference_white;
00617 
00618       Quantum
00619         *logmap;
00620 
00621       /*
00622         Transform RGB to Log colorspace.
00623       */
00624       density=DisplayGamma;
00625       gamma=DisplayGamma;
00626       value=GetImageProperty(image,"gamma",exception);
00627       if (value != (const char *) NULL)
00628         gamma=1.0/fabs(StringToDouble(value,(char **) NULL)) >= MagickEpsilon ?
00629           StringToDouble(value,(char **) NULL) : 1.0;
00630       film_gamma=FilmGamma;
00631       value=GetImageProperty(image,"film-gamma",exception);
00632       if (value != (const char *) NULL)
00633         film_gamma=StringToDouble(value,(char **) NULL);
00634       reference_black=ReferenceBlack;
00635       value=GetImageProperty(image,"reference-black",exception);
00636       if (value != (const char *) NULL)
00637         reference_black=StringToDouble(value,(char **) NULL);
00638       reference_white=ReferenceWhite;
00639       value=GetImageProperty(image,"reference-white",exception);
00640       if (value != (const char *) NULL)
00641         reference_white=StringToDouble(value,(char **) NULL);
00642       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00643         sizeof(*logmap));
00644       if (logmap == (Quantum *) NULL)
00645         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00646           image->filename);
00647       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
00648         0.002/film_gamma);
00649 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00650       #pragma omp parallel for schedule(static)
00651 #endif
00652       for (i=0; i <= (ssize_t) MaxMap; i++)
00653         logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+
00654           log10(black+((MagickRealType) i/MaxMap)*(1.0-black))/((gamma/density)*
00655           0.002/film_gamma))/1024.0));
00656       image_view=AcquireCacheView(image);
00657 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00658       #pragma omp parallel for schedule(static,4) shared(status)
00659 #endif
00660       for (y=0; y < (ssize_t) image->rows; y++)
00661       {
00662         MagickBooleanType
00663           sync;
00664 
00665         register ssize_t
00666           x;
00667 
00668         register Quantum
00669           *restrict q;
00670 
00671         if (status == MagickFalse)
00672           continue;
00673         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00674           exception);
00675         if (q == (Quantum *) NULL)
00676           {
00677             status=MagickFalse;
00678             continue;
00679           }
00680         for (x=(ssize_t) image->columns; x != 0; x--)
00681         {
00682           SetPixelRed(image,logmap[ScaleQuantumToMap(
00683             GetPixelRed(image,q))],q);
00684           SetPixelGreen(image,logmap[ScaleQuantumToMap(
00685             GetPixelGreen(image,q))],q);
00686           SetPixelBlue(image,logmap[ScaleQuantumToMap(
00687             GetPixelBlue(image,q))],q);
00688           q+=GetPixelChannels(image);
00689         }
00690         sync=SyncCacheViewAuthenticPixels(image_view,exception);
00691         if (sync == MagickFalse)
00692           status=MagickFalse;
00693       }
00694       image_view=DestroyCacheView(image_view);
00695       logmap=(Quantum *) RelinquishMagickMemory(logmap);
00696       return(status);
00697     }
00698     default:
00699       break;
00700   }
00701   /*
00702     Allocate the tables.
00703   */
00704   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00705     sizeof(*x_map));
00706   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00707     sizeof(*y_map));
00708   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00709     sizeof(*z_map));
00710   if ((x_map == (TransformPacket *) NULL) ||
00711       (y_map == (TransformPacket *) NULL) ||
00712       (z_map == (TransformPacket *) NULL))
00713     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00714       image->filename);
00715   (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
00716   switch (colorspace)
00717   {
00718     case OHTAColorspace:
00719     {
00720       /*
00721         Initialize OHTA tables:
00722 
00723           I1 = 0.33333*R+0.33334*G+0.33333*B
00724           I2 = 0.50000*R+0.00000*G-0.50000*B
00725           I3 =-0.25000*R+0.50000*G-0.25000*B
00726 
00727         I and Q, normally -0.5 through 0.5, are normalized to the range 0
00728         through QuantumRange.
00729       */
00730       primary_info.y=(double) (MaxMap+1.0)/2.0;
00731       primary_info.z=(double) (MaxMap+1.0)/2.0;
00732 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00733       #pragma omp parallel for schedule(static)
00734 #endif
00735       for (i=0; i <= (ssize_t) MaxMap; i++)
00736       {
00737         x_map[i].x=0.33333f*(MagickRealType) i;
00738         y_map[i].x=0.33334f*(MagickRealType) i;
00739         z_map[i].x=0.33333f*(MagickRealType) i;
00740         x_map[i].y=0.50000f*(MagickRealType) i;
00741         y_map[i].y=0.00000f*(MagickRealType) i;
00742         z_map[i].y=(-0.50000f)*(MagickRealType) i;
00743         x_map[i].z=(-0.25000f)*(MagickRealType) i;
00744         y_map[i].z=0.50000f*(MagickRealType) i;
00745         z_map[i].z=(-0.25000f)*(MagickRealType) i;
00746       }
00747       break;
00748     }
00749     case Rec601LumaColorspace:
00750     case GRAYColorspace:
00751     {
00752       /*
00753         Initialize Rec601 luma tables:
00754 
00755           G = 0.29900*R+0.58700*G+0.11400*B
00756       */
00757 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00758       #pragma omp parallel for schedule(static)
00759 #endif
00760       for (i=0; i <= (ssize_t) MaxMap; i++)
00761       {
00762         x_map[i].x=0.29900f*(MagickRealType) i;
00763         y_map[i].x=0.58700f*(MagickRealType) i;
00764         z_map[i].x=0.11400f*(MagickRealType) i;
00765         x_map[i].y=0.29900f*(MagickRealType) i;
00766         y_map[i].y=0.58700f*(MagickRealType) i;
00767         z_map[i].y=0.11400f*(MagickRealType) i;
00768         x_map[i].z=0.29900f*(MagickRealType) i;
00769         y_map[i].z=0.58700f*(MagickRealType) i;
00770         z_map[i].z=0.11400f*(MagickRealType) i;
00771       }
00772       image->type=GrayscaleType;
00773       break;
00774     }
00775     case Rec601YCbCrColorspace:
00776     case YCbCrColorspace:
00777     {
00778       /*
00779         Initialize YCbCr tables (ITU-R BT.601):
00780 
00781           Y =  0.299000*R+0.587000*G+0.114000*B
00782           Cb= -0.168736*R-0.331264*G+0.500000*B
00783           Cr=  0.500000*R-0.418688*G-0.081312*B
00784 
00785         Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
00786         through QuantumRange.
00787       */
00788       primary_info.y=(double) (MaxMap+1.0)/2.0;
00789       primary_info.z=(double) (MaxMap+1.0)/2.0;
00790 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00791       #pragma omp parallel for schedule(static)
00792 #endif
00793       for (i=0; i <= (ssize_t) MaxMap; i++)
00794       {
00795         x_map[i].x=0.299000f*(MagickRealType) i;
00796         y_map[i].x=0.587000f*(MagickRealType) i;
00797         z_map[i].x=0.114000f*(MagickRealType) i;
00798         x_map[i].y=(-0.168730f)*(MagickRealType) i;
00799         y_map[i].y=(-0.331264f)*(MagickRealType) i;
00800         z_map[i].y=0.500000f*(MagickRealType) i;
00801         x_map[i].z=0.500000f*(MagickRealType) i;
00802         y_map[i].z=(-0.418688f)*(MagickRealType) i;
00803         z_map[i].z=(-0.081312f)*(MagickRealType) i;
00804       }
00805       break;
00806     }
00807     case Rec709LumaColorspace:
00808     {
00809       /*
00810         Initialize Rec709 luma tables:
00811 
00812           G = 0.21260*R+0.71520*G+0.07220*B
00813       */
00814 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00815       #pragma omp parallel for schedule(static)
00816 #endif
00817       for (i=0; i <= (ssize_t) MaxMap; i++)
00818       {
00819         x_map[i].x=0.21260f*(MagickRealType) i;
00820         y_map[i].x=0.71520f*(MagickRealType) i;
00821         z_map[i].x=0.07220f*(MagickRealType) i;
00822         x_map[i].y=0.21260f*(MagickRealType) i;
00823         y_map[i].y=0.71520f*(MagickRealType) i;
00824         z_map[i].y=0.07220f*(MagickRealType) i;
00825         x_map[i].z=0.21260f*(MagickRealType) i;
00826         y_map[i].z=0.71520f*(MagickRealType) i;
00827         z_map[i].z=0.07220f*(MagickRealType) i;
00828       }
00829       break;
00830     }
00831     case Rec709YCbCrColorspace:
00832     {
00833       /*
00834         Initialize YCbCr tables (ITU-R BT.709):
00835 
00836           Y =  0.212600*R+0.715200*G+0.072200*B
00837           Cb= -0.114572*R-0.385428*G+0.500000*B
00838           Cr=  0.500000*R-0.454153*G-0.045847*B
00839 
00840         Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
00841         through QuantumRange.
00842       */
00843       primary_info.y=(double) (MaxMap+1.0)/2.0;
00844       primary_info.z=(double) (MaxMap+1.0)/2.0;
00845 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00846       #pragma omp parallel for schedule(static)
00847 #endif
00848       for (i=0; i <= (ssize_t) MaxMap; i++)
00849       {
00850         x_map[i].x=0.212600f*(MagickRealType) i;
00851         y_map[i].x=0.715200f*(MagickRealType) i;
00852         z_map[i].x=0.072200f*(MagickRealType) i;
00853         x_map[i].y=(-0.114572f)*(MagickRealType) i;
00854         y_map[i].y=(-0.385428f)*(MagickRealType) i;
00855         z_map[i].y=0.500000f*(MagickRealType) i;
00856         x_map[i].z=0.500000f*(MagickRealType) i;
00857         y_map[i].z=(-0.454153f)*(MagickRealType) i;
00858         z_map[i].z=(-0.045847f)*(MagickRealType) i;
00859       }
00860       break;
00861     }
00862     case sRGBColorspace:
00863     {
00864       /*
00865         Nonlinear sRGB to linear RGB (http://www.w3.org/Graphics/Color/sRGB):
00866 
00867           R = 1.0*R+0.0*G+0.0*B
00868           G = 0.0*R+1.0*G+0.0*B
00869           B = 0.0*R+0.0*G+1.0*B
00870       */
00871 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00872       #pragma omp parallel for schedule(static)
00873 #endif
00874       for (i=0; i <= (ssize_t) MaxMap; i++)
00875       {
00876         MagickRealType
00877           v;
00878 
00879         v=(MagickRealType) i/(MagickRealType) MaxMap;
00880         if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.0031308)
00881           v*=12.92f;
00882         else
00883           v=(MagickRealType) (1.055*pow((double) i/MaxMap,1.0/2.4)-0.055);
00884         x_map[i].x=1.0f*MaxMap*v;
00885         y_map[i].x=0.0f*MaxMap*v;
00886         z_map[i].x=0.0f*MaxMap*v;
00887         x_map[i].y=0.0f*MaxMap*v;
00888         y_map[i].y=1.0f*MaxMap*v;
00889         z_map[i].y=0.0f*MaxMap*v;
00890         x_map[i].z=0.0f*MaxMap*v;
00891         y_map[i].z=0.0f*MaxMap*v;
00892         z_map[i].z=1.0f*MaxMap*v;
00893       }
00894       break;
00895     }
00896     case XYZColorspace:
00897     {
00898       /*
00899         Initialize CIE XYZ tables (ITU-R 709 RGB):
00900 
00901           X = 0.4124564*R+0.3575761*G+0.1804375*B
00902           Y = 0.2126729*R+0.7151522*G+0.0721750*B
00903           Z = 0.0193339*R+0.1191920*G+0.9503041*B
00904       */
00905 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00906       #pragma omp parallel for schedule(static)
00907 #endif
00908       for (i=0; i <= (ssize_t) MaxMap; i++)
00909       {
00910         x_map[i].x=0.4124564f*(MagickRealType) i;
00911         y_map[i].x=0.3575761f*(MagickRealType) i;
00912         z_map[i].x=0.1804375f*(MagickRealType) i;
00913         x_map[i].y=0.2126729f*(MagickRealType) i;
00914         y_map[i].y=0.7151522f*(MagickRealType) i;
00915         z_map[i].y=0.0721750f*(MagickRealType) i;
00916         x_map[i].z=0.0193339f*(MagickRealType) i;
00917         y_map[i].z=0.1191920f*(MagickRealType) i;
00918         z_map[i].z=0.9503041f*(MagickRealType) i;
00919       }
00920       break;
00921     }
00922     case YCCColorspace:
00923     {
00924       /*
00925         Initialize YCC tables:
00926 
00927           Y =  0.29900*R+0.58700*G+0.11400*B
00928           C1= -0.29900*R-0.58700*G+0.88600*B
00929           C2=  0.70100*R-0.58700*G-0.11400*B
00930 
00931         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
00932       */
00933       primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
00934       primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
00935       for (i=0; i <= (ssize_t) (0.018*MaxMap); i++)
00936       {
00937         x_map[i].x=0.003962014134275617f*(MagickRealType) i;
00938         y_map[i].x=0.007778268551236748f*(MagickRealType) i;
00939         z_map[i].x=0.001510600706713781f*(MagickRealType) i;
00940         x_map[i].y=(-0.002426619775463276f)*(MagickRealType) i;
00941         y_map[i].y=(-0.004763965913702149f)*(MagickRealType) i;
00942         z_map[i].y=0.007190585689165425f*(MagickRealType) i;
00943         x_map[i].z=0.006927257754597858f*(MagickRealType) i;
00944         y_map[i].z=(-0.005800713697502058f)*(MagickRealType) i;
00945         z_map[i].z=(-0.0011265440570958f)*(MagickRealType) i;
00946       }
00947       for ( ; i <= (ssize_t) MaxMap; i++)
00948       {
00949         x_map[i].x=0.2201118963486454*(1.099f*(MagickRealType) i-0.099f);
00950         y_map[i].x=0.4321260306242638*(1.099f*(MagickRealType) i-0.099f);
00951         z_map[i].x=0.08392226148409894*(1.099f*(MagickRealType) i-0.099f);
00952         x_map[i].y=(-0.1348122097479598)*(1.099f*(MagickRealType) i-0.099f);
00953         y_map[i].y=(-0.2646647729834528)*(1.099f*(MagickRealType) i-0.099f);
00954         z_map[i].y=0.3994769827314126*(1.099f*(MagickRealType) i-0.099f);
00955         x_map[i].z=0.3848476530332144*(1.099f*(MagickRealType) i-0.099f);
00956         y_map[i].z=(-0.3222618720834477)*(1.099f*(MagickRealType) i-0.099f);
00957         z_map[i].z=(-0.06258578094976668)*(1.099f*(MagickRealType) i-0.099f);
00958       }
00959       break;
00960     }
00961     case YIQColorspace:
00962     {
00963       /*
00964         Initialize YIQ tables:
00965 
00966           Y = 0.29900*R+0.58700*G+0.11400*B
00967           I = 0.59600*R-0.27400*G-0.32200*B
00968           Q = 0.21100*R-0.52300*G+0.31200*B
00969 
00970         I and Q, normally -0.5 through 0.5, are normalized to the range 0
00971         through QuantumRange.
00972       */
00973       primary_info.y=(double) (MaxMap+1.0)/2.0;
00974       primary_info.z=(double) (MaxMap+1.0)/2.0;
00975 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00976       #pragma omp parallel for schedule(static)
00977 #endif
00978       for (i=0; i <= (ssize_t) MaxMap; i++)
00979       {
00980         x_map[i].x=0.29900f*(MagickRealType) i;
00981         y_map[i].x=0.58700f*(MagickRealType) i;
00982         z_map[i].x=0.11400f*(MagickRealType) i;
00983         x_map[i].y=0.59600f*(MagickRealType) i;
00984         y_map[i].y=(-0.27400f)*(MagickRealType) i;
00985         z_map[i].y=(-0.32200f)*(MagickRealType) i;
00986         x_map[i].z=0.21100f*(MagickRealType) i;
00987         y_map[i].z=(-0.52300f)*(MagickRealType) i;
00988         z_map[i].z=0.31200f*(MagickRealType) i;
00989       }
00990       break;
00991     }
00992     case YPbPrColorspace:
00993     {
00994       /*
00995         Initialize YPbPr tables (ITU-R BT.601):
00996 
00997           Y =  0.299000*R+0.587000*G+0.114000*B
00998           Pb= -0.168736*R-0.331264*G+0.500000*B
00999           Pr=  0.500000*R-0.418688*G-0.081312*B
01000 
01001         Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0
01002         through QuantumRange.
01003       */
01004       primary_info.y=(double) (MaxMap+1.0)/2.0;
01005       primary_info.z=(double) (MaxMap+1.0)/2.0;
01006 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01007       #pragma omp parallel for schedule(static)
01008 #endif
01009       for (i=0; i <= (ssize_t) MaxMap; i++)
01010       {
01011         x_map[i].x=0.299000f*(MagickRealType) i;
01012         y_map[i].x=0.587000f*(MagickRealType) i;
01013         z_map[i].x=0.114000f*(MagickRealType) i;
01014         x_map[i].y=(-0.168736f)*(MagickRealType) i;
01015         y_map[i].y=(-0.331264f)*(MagickRealType) i;
01016         z_map[i].y=0.500000f*(MagickRealType) i;
01017         x_map[i].z=0.500000f*(MagickRealType) i;
01018         y_map[i].z=(-0.418688f)*(MagickRealType) i;
01019         z_map[i].z=(-0.081312f)*(MagickRealType) i;
01020       }
01021       break;
01022     }
01023     case YUVColorspace:
01024     default:
01025     {
01026       /*
01027         Initialize YUV tables:
01028 
01029           Y =  0.29900*R+0.58700*G+0.11400*B
01030           U = -0.14740*R-0.28950*G+0.43690*B
01031           V =  0.61500*R-0.51500*G-0.10000*B
01032 
01033         U and V, normally -0.5 through 0.5, are normalized to the range 0
01034         through QuantumRange.  Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
01035       */
01036       primary_info.y=(double) (MaxMap+1.0)/2.0;
01037       primary_info.z=(double) (MaxMap+1.0)/2.0;
01038 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01039       #pragma omp parallel for schedule(static)
01040 #endif
01041       for (i=0; i <= (ssize_t) MaxMap; i++)
01042       {
01043         x_map[i].x=0.29900f*(MagickRealType) i;
01044         y_map[i].x=0.58700f*(MagickRealType) i;
01045         z_map[i].x=0.11400f*(MagickRealType) i;
01046         x_map[i].y=(-0.14740f)*(MagickRealType) i;
01047         y_map[i].y=(-0.28950f)*(MagickRealType) i;
01048         z_map[i].y=0.43690f*(MagickRealType) i;
01049         x_map[i].z=0.61500f*(MagickRealType) i;
01050         y_map[i].z=(-0.51500f)*(MagickRealType) i;
01051         z_map[i].z=(-0.10000f)*(MagickRealType) i;
01052       }
01053       break;
01054     }
01055   }
01056   /*
01057     Convert from RGB.
01058   */
01059   switch (image->storage_class)
01060   {
01061     case DirectClass:
01062     default:
01063     {
01064       /*
01065         Convert DirectClass image.
01066       */
01067       image_view=AcquireCacheView(image);
01068 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01069       #pragma omp parallel for schedule(static,4) shared(status)
01070 #endif
01071       for (y=0; y < (ssize_t) image->rows; y++)
01072       {
01073         MagickBooleanType
01074           sync;
01075 
01076         PixelInfo
01077           pixel;
01078 
01079         register Quantum
01080           *restrict q;
01081 
01082         register ssize_t
01083           x;
01084 
01085         register unsigned int
01086           blue,
01087           green,
01088           red;
01089 
01090         if (status == MagickFalse)
01091           continue;
01092         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01093           exception);
01094         if (q == (Quantum *) NULL)
01095           {
01096             status=MagickFalse;
01097             continue;
01098           }
01099         for (x=0; x < (ssize_t) image->columns; x++)
01100         {
01101           red=ScaleQuantumToMap(GetPixelRed(image,q));
01102           green=ScaleQuantumToMap(GetPixelGreen(image,q));
01103           blue=ScaleQuantumToMap(GetPixelBlue(image,q));
01104           pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
01105             (MagickRealType) primary_info.x;
01106           pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
01107             (MagickRealType) primary_info.y;
01108           pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
01109             (MagickRealType) primary_info.z;
01110           SetPixelRed(image,ScaleMapToQuantum(pixel.red),q);
01111           SetPixelGreen(image,ScaleMapToQuantum(pixel.green),q);
01112           SetPixelBlue(image,ScaleMapToQuantum(pixel.blue),q);
01113           q+=GetPixelChannels(image);
01114         }
01115         sync=SyncCacheViewAuthenticPixels(image_view,exception);
01116         if (sync == MagickFalse)
01117           status=MagickFalse;
01118         if (image->progress_monitor != (MagickProgressMonitor) NULL)
01119           {
01120             MagickBooleanType
01121               proceed;
01122 
01123 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01124             #pragma omp critical (MagickCore_RGBTransformImage)
01125 #endif
01126             proceed=SetImageProgress(image,RGBTransformImageTag,progress++,
01127               image->rows);
01128             if (proceed == MagickFalse)
01129               status=MagickFalse;
01130           }
01131       }
01132       image_view=DestroyCacheView(image_view);
01133       break;
01134     }
01135     case PseudoClass:
01136     {
01137       register unsigned int
01138         blue,
01139         green,
01140         red;
01141 
01142       /*
01143         Convert PseudoClass image.
01144       */
01145       for (i=0; i < (ssize_t) image->colors; i++)
01146       {
01147         PixelInfo
01148           pixel;
01149 
01150         red=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red));
01151         green=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green));
01152         blue=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue));
01153         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
01154         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
01155         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
01156         image->colormap[i].red=(double) ScaleMapToQuantum(pixel.red);
01157         image->colormap[i].green=(double) ScaleMapToQuantum(pixel.green);
01158         image->colormap[i].blue=(double) ScaleMapToQuantum(pixel.blue);
01159       }
01160       (void) SyncImage(image,exception);
01161       break;
01162     }
01163   }
01164   /*
01165     Relinquish resources.
01166   */
01167   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
01168   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
01169   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
01170   if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
01171     return(MagickFalse);
01172   return(status);
01173 }
01174 
01175 /*
01176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01177 %                                                                             %
01178 %                                                                             %
01179 %                                                                             %
01180 %   S e t I m a g e C o l o r s p a c e                                       %
01181 %                                                                             %
01182 %                                                                             %
01183 %                                                                             %
01184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01185 %
01186 %  SetImageColorspace() sets the colorspace member of the Image structure.
01187 %
01188 %  The format of the SetImageColorspace method is:
01189 %
01190 %      MagickBooleanType SetImageColorspace(Image *image,
01191 %        const ColorspaceType colorspace,ExceptiionInfo *exception)
01192 %
01193 %  A description of each parameter follows:
01194 %
01195 %    o image: the image.
01196 %
01197 %    o colorspace: the colorspace.
01198 %
01199 %   o exception: return any errors or warnings in this structure.
01200 %
01201 */
01202 MagickExport MagickBooleanType SetImageColorspace(Image *image,
01203   const ColorspaceType colorspace,ExceptionInfo *exception)
01204 {
01205   image->colorspace=colorspace;
01206   return(SyncImagePixelCache(image,exception));
01207 }
01208 
01209 /*
01210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01211 %                                                                             %
01212 %                                                                             %
01213 %                                                                             %
01214 %   T r a n s f o r m I m a g e C o l o r s p a c e                           %
01215 %                                                                             %
01216 %                                                                             %
01217 %                                                                             %
01218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01219 %
01220 %  TransformImageColorspace() transforms an image colorspace.
01221 %
01222 %  The format of the TransformImageColorspace method is:
01223 %
01224 %      MagickBooleanType TransformImageColorspace(Image *image,
01225 %        const ColorspaceType colorspace,ExceptionInfo *exception)
01226 %
01227 %  A description of each parameter follows:
01228 %
01229 %    o image: the image.
01230 %
01231 %    o colorspace: the colorspace.
01232 %
01233 %   o exception: return any errors or warnings in this structure.
01234 %
01235 */
01236 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
01237   const ColorspaceType colorspace,ExceptionInfo *exception)
01238 {
01239   MagickBooleanType
01240     status;
01241 
01242   assert(image != (Image *) NULL);
01243   assert(image->signature == MagickSignature);
01244   if (image->debug != MagickFalse)
01245     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01246   if (colorspace == UndefinedColorspace)
01247     return(SetImageColorspace(image,colorspace,exception));
01248   if (image->colorspace == colorspace)
01249     return(MagickTrue);  /* same colorspace: no op */
01250   /*
01251     Convert the reference image from an alternate colorspace to RGB.
01252   */
01253   if ((colorspace == RGBColorspace) || (colorspace == TransparentColorspace))
01254     return(TransformRGBImage(image,colorspace,exception));
01255   status=MagickTrue;
01256   if (IsRGBColorspace(image->colorspace) == MagickFalse)
01257     status=TransformRGBImage(image,image->colorspace,exception);
01258   /*
01259     Convert the reference image from RGB to an alternate colorspace.
01260   */
01261   if (RGBTransformImage(image,colorspace,exception) == MagickFalse)
01262     status=MagickFalse;
01263   return(status);
01264 }
01265 
01266 /*
01267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01268 %                                                                             %
01269 %                                                                             %
01270 %                                                                             %
01271 +     T r a n s f o r m R G B I m a g e                                       %
01272 %                                                                             %
01273 %                                                                             %
01274 %                                                                             %
01275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01276 %
01277 %  TransformRGBImage() converts the reference image from an alternate
01278 %  colorspace to RGB.  The transformation matrices are not the standard ones:
01279 %  the weights are rescaled to normalize the range of the transformed values to
01280 %  be [0..QuantumRange].
01281 %
01282 %  The format of the TransformRGBImage method is:
01283 %
01284 %      MagickBooleanType TransformRGBImage(Image *image,
01285 %        const ColorspaceType colorspace,ExceptionInfo *exception)
01286 %
01287 %  A description of each parameter follows:
01288 %
01289 %    o image: the image.
01290 %
01291 %    o colorspace: the colorspace to transform the image to.
01292 %
01293 %   o exception: return any errors or warnings in this structure.
01294 %
01295 */
01296 
01297 static double LabF2(double alpha)
01298 {
01299   double
01300     beta;
01301 
01302   if (alpha > (24.0/116.0))
01303     return(alpha*alpha*alpha);
01304   beta=(108.0/841.0)*(alpha-(16.0/116.0));
01305   if (beta > 0.0)
01306     return(beta);
01307   return(0.0);
01308 }
01309 
01310 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
01311   double *X,double *Y,double *Z)
01312 {
01313 
01314   double
01315     x,
01316     y,
01317     z;
01318 
01319   assert(X != (double *) NULL);
01320   assert(Y != (double *) NULL);
01321   assert(Z != (double *) NULL);
01322   *X=0.0;
01323   *Y=0.0;
01324   *Z=0.0;
01325   if (L <= 0.0)
01326     return;
01327   y=(100.0*L+16.0)/116.0;
01328   x=y+255.0*0.002*(a > 0.5 ? a-1.0 : a);
01329   z=y-255.0*0.005*(b > 0.5 ? b-1.0 : b);
01330   *X=D50X*LabF2(x);
01331   *Y=D50Y*LabF2(y);
01332   *Z=D50Z*LabF2(z);
01333 }
01334 
01335 static inline ssize_t RoundToYCC(const MagickRealType value)
01336 {
01337   if (value <= 0.0)
01338     return(0);
01339   if (value >= 1388.0)
01340     return(1388);
01341   return((ssize_t) (value+0.5));
01342 }
01343 
01344 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
01345   Quantum *red,Quantum *green,Quantum *blue)
01346 {
01347   double
01348     b,
01349     g,
01350     r;
01351 
01352   /*
01353     Convert XYZ to RGB colorspace.
01354   */
01355   assert(red != (Quantum *) NULL);
01356   assert(green != (Quantum *) NULL);
01357   assert(blue != (Quantum *) NULL);
01358   r=3.2404542*x-1.5371385*y-0.4985314*z;
01359   g=(-0.9692660*x+1.8760108*y+0.0415560*z);
01360   b=0.0556434*x-0.2040259*y+1.0572252*z;
01361   if (r > 0.0031308)
01362     r=1.055*pow(r,1.0/2.4)-0.055;
01363   else
01364     r*=12.92;
01365   if (g > 0.0031308)
01366     g=1.055*pow(g,1.0/2.4)-0.055;
01367   else
01368     g*=12.92;
01369   if (b > 0.0031308)
01370     b=1.055*pow(b,1.0/2.4)-0.055;
01371   else
01372     b*=12.92;
01373   *red=RoundToQuantum((MagickRealType) QuantumRange*r);
01374   *green=RoundToQuantum((MagickRealType) QuantumRange*g);
01375   *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
01376 }
01377 
01378 static inline void ConvertCMYKToRGB(PixelInfo *pixel)
01379 {
01380   pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red*
01381     (QuantumRange-pixel->black)+pixel->black);
01382   pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green*
01383     (QuantumRange-pixel->black)+pixel->black);
01384   pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue*
01385     (QuantumRange-pixel->black)+pixel->black);
01386 }
01387 
01388 MagickExport MagickBooleanType TransformRGBImage(Image *image,
01389   const ColorspaceType colorspace,ExceptionInfo *exception)
01390 {
01391 #define D50X  (0.9642)
01392 #define D50Y  (1.0)
01393 #define D50Z  (0.8249)
01394 #define TransformRGBImageTag  "Transform/Image"
01395 
01396 #if !defined(MAGICKCORE_HDRI_SUPPORT)
01397   static const float
01398     YCCMap[1389] =
01399     {
01400       0.000000f, 0.000720f, 0.001441f, 0.002161f, 0.002882f, 0.003602f,
01401       0.004323f, 0.005043f, 0.005764f, 0.006484f, 0.007205f, 0.007925f,
01402       0.008646f, 0.009366f, 0.010086f, 0.010807f, 0.011527f, 0.012248f,
01403       0.012968f, 0.013689f, 0.014409f, 0.015130f, 0.015850f, 0.016571f,
01404       0.017291f, 0.018012f, 0.018732f, 0.019452f, 0.020173f, 0.020893f,
01405       0.021614f, 0.022334f, 0.023055f, 0.023775f, 0.024496f, 0.025216f,
01406       0.025937f, 0.026657f, 0.027378f, 0.028098f, 0.028818f, 0.029539f,
01407       0.030259f, 0.030980f, 0.031700f, 0.032421f, 0.033141f, 0.033862f,
01408       0.034582f, 0.035303f, 0.036023f, 0.036744f, 0.037464f, 0.038184f,
01409       0.038905f, 0.039625f, 0.040346f, 0.041066f, 0.041787f, 0.042507f,
01410       0.043228f, 0.043948f, 0.044669f, 0.045389f, 0.046110f, 0.046830f,
01411       0.047550f, 0.048271f, 0.048991f, 0.049712f, 0.050432f, 0.051153f,
01412       0.051873f, 0.052594f, 0.053314f, 0.054035f, 0.054755f, 0.055476f,
01413       0.056196f, 0.056916f, 0.057637f, 0.058357f, 0.059078f, 0.059798f,
01414       0.060519f, 0.061239f, 0.061960f, 0.062680f, 0.063401f, 0.064121f,
01415       0.064842f, 0.065562f, 0.066282f, 0.067003f, 0.067723f, 0.068444f,
01416       0.069164f, 0.069885f, 0.070605f, 0.071326f, 0.072046f, 0.072767f,
01417       0.073487f, 0.074207f, 0.074928f, 0.075648f, 0.076369f, 0.077089f,
01418       0.077810f, 0.078530f, 0.079251f, 0.079971f, 0.080692f, 0.081412f,
01419       0.082133f, 0.082853f, 0.083573f, 0.084294f, 0.085014f, 0.085735f,
01420       0.086455f, 0.087176f, 0.087896f, 0.088617f, 0.089337f, 0.090058f,
01421       0.090778f, 0.091499f, 0.092219f, 0.092939f, 0.093660f, 0.094380f,
01422       0.095101f, 0.095821f, 0.096542f, 0.097262f, 0.097983f, 0.098703f,
01423       0.099424f, 0.100144f, 0.100865f, 0.101585f, 0.102305f, 0.103026f,
01424       0.103746f, 0.104467f, 0.105187f, 0.105908f, 0.106628f, 0.107349f,
01425       0.108069f, 0.108790f, 0.109510f, 0.110231f, 0.110951f, 0.111671f,
01426       0.112392f, 0.113112f, 0.113833f, 0.114553f, 0.115274f, 0.115994f,
01427       0.116715f, 0.117435f, 0.118156f, 0.118876f, 0.119597f, 0.120317f,
01428       0.121037f, 0.121758f, 0.122478f, 0.123199f, 0.123919f, 0.124640f,
01429       0.125360f, 0.126081f, 0.126801f, 0.127522f, 0.128242f, 0.128963f,
01430       0.129683f, 0.130403f, 0.131124f, 0.131844f, 0.132565f, 0.133285f,
01431       0.134006f, 0.134726f, 0.135447f, 0.136167f, 0.136888f, 0.137608f,
01432       0.138329f, 0.139049f, 0.139769f, 0.140490f, 0.141210f, 0.141931f,
01433       0.142651f, 0.143372f, 0.144092f, 0.144813f, 0.145533f, 0.146254f,
01434       0.146974f, 0.147695f, 0.148415f, 0.149135f, 0.149856f, 0.150576f,
01435       0.151297f, 0.152017f, 0.152738f, 0.153458f, 0.154179f, 0.154899f,
01436       0.155620f, 0.156340f, 0.157061f, 0.157781f, 0.158501f, 0.159222f,
01437       0.159942f, 0.160663f, 0.161383f, 0.162104f, 0.162824f, 0.163545f,
01438       0.164265f, 0.164986f, 0.165706f, 0.166427f, 0.167147f, 0.167867f,
01439       0.168588f, 0.169308f, 0.170029f, 0.170749f, 0.171470f, 0.172190f,
01440       0.172911f, 0.173631f, 0.174352f, 0.175072f, 0.175793f, 0.176513f,
01441       0.177233f, 0.177954f, 0.178674f, 0.179395f, 0.180115f, 0.180836f,
01442       0.181556f, 0.182277f, 0.182997f, 0.183718f, 0.184438f, 0.185159f,
01443       0.185879f, 0.186599f, 0.187320f, 0.188040f, 0.188761f, 0.189481f,
01444       0.190202f, 0.190922f, 0.191643f, 0.192363f, 0.193084f, 0.193804f,
01445       0.194524f, 0.195245f, 0.195965f, 0.196686f, 0.197406f, 0.198127f,
01446       0.198847f, 0.199568f, 0.200288f, 0.201009f, 0.201729f, 0.202450f,
01447       0.203170f, 0.203890f, 0.204611f, 0.205331f, 0.206052f, 0.206772f,
01448       0.207493f, 0.208213f, 0.208934f, 0.209654f, 0.210375f, 0.211095f,
01449       0.211816f, 0.212536f, 0.213256f, 0.213977f, 0.214697f, 0.215418f,
01450       0.216138f, 0.216859f, 0.217579f, 0.218300f, 0.219020f, 0.219741f,
01451       0.220461f, 0.221182f, 0.221902f, 0.222622f, 0.223343f, 0.224063f,
01452       0.224784f, 0.225504f, 0.226225f, 0.226945f, 0.227666f, 0.228386f,
01453       0.229107f, 0.229827f, 0.230548f, 0.231268f, 0.231988f, 0.232709f,
01454       0.233429f, 0.234150f, 0.234870f, 0.235591f, 0.236311f, 0.237032f,
01455       0.237752f, 0.238473f, 0.239193f, 0.239914f, 0.240634f, 0.241354f,
01456       0.242075f, 0.242795f, 0.243516f, 0.244236f, 0.244957f, 0.245677f,
01457       0.246398f, 0.247118f, 0.247839f, 0.248559f, 0.249280f, 0.250000f,
01458       0.250720f, 0.251441f, 0.252161f, 0.252882f, 0.253602f, 0.254323f,
01459       0.255043f, 0.255764f, 0.256484f, 0.257205f, 0.257925f, 0.258646f,
01460       0.259366f, 0.260086f, 0.260807f, 0.261527f, 0.262248f, 0.262968f,
01461       0.263689f, 0.264409f, 0.265130f, 0.265850f, 0.266571f, 0.267291f,
01462       0.268012f, 0.268732f, 0.269452f, 0.270173f, 0.270893f, 0.271614f,
01463       0.272334f, 0.273055f, 0.273775f, 0.274496f, 0.275216f, 0.275937f,
01464       0.276657f, 0.277378f, 0.278098f, 0.278818f, 0.279539f, 0.280259f,
01465       0.280980f, 0.281700f, 0.282421f, 0.283141f, 0.283862f, 0.284582f,
01466       0.285303f, 0.286023f, 0.286744f, 0.287464f, 0.288184f, 0.288905f,
01467       0.289625f, 0.290346f, 0.291066f, 0.291787f, 0.292507f, 0.293228f,
01468       0.293948f, 0.294669f, 0.295389f, 0.296109f, 0.296830f, 0.297550f,
01469       0.298271f, 0.298991f, 0.299712f, 0.300432f, 0.301153f, 0.301873f,
01470       0.302594f, 0.303314f, 0.304035f, 0.304755f, 0.305476f, 0.306196f,
01471       0.306916f, 0.307637f, 0.308357f, 0.309078f, 0.309798f, 0.310519f,
01472       0.311239f, 0.311960f, 0.312680f, 0.313401f, 0.314121f, 0.314842f,
01473       0.315562f, 0.316282f, 0.317003f, 0.317723f, 0.318444f, 0.319164f,
01474       0.319885f, 0.320605f, 0.321326f, 0.322046f, 0.322767f, 0.323487f,
01475       0.324207f, 0.324928f, 0.325648f, 0.326369f, 0.327089f, 0.327810f,
01476       0.328530f, 0.329251f, 0.329971f, 0.330692f, 0.331412f, 0.332133f,
01477       0.332853f, 0.333573f, 0.334294f, 0.335014f, 0.335735f, 0.336455f,
01478       0.337176f, 0.337896f, 0.338617f, 0.339337f, 0.340058f, 0.340778f,
01479       0.341499f, 0.342219f, 0.342939f, 0.343660f, 0.344380f, 0.345101f,
01480       0.345821f, 0.346542f, 0.347262f, 0.347983f, 0.348703f, 0.349424f,
01481       0.350144f, 0.350865f, 0.351585f, 0.352305f, 0.353026f, 0.353746f,
01482       0.354467f, 0.355187f, 0.355908f, 0.356628f, 0.357349f, 0.358069f,
01483       0.358790f, 0.359510f, 0.360231f, 0.360951f, 0.361671f, 0.362392f,
01484       0.363112f, 0.363833f, 0.364553f, 0.365274f, 0.365994f, 0.366715f,
01485       0.367435f, 0.368156f, 0.368876f, 0.369597f, 0.370317f, 0.371037f,
01486       0.371758f, 0.372478f, 0.373199f, 0.373919f, 0.374640f, 0.375360f,
01487       0.376081f, 0.376801f, 0.377522f, 0.378242f, 0.378963f, 0.379683f,
01488       0.380403f, 0.381124f, 0.381844f, 0.382565f, 0.383285f, 0.384006f,
01489       0.384726f, 0.385447f, 0.386167f, 0.386888f, 0.387608f, 0.388329f,
01490       0.389049f, 0.389769f, 0.390490f, 0.391210f, 0.391931f, 0.392651f,
01491       0.393372f, 0.394092f, 0.394813f, 0.395533f, 0.396254f, 0.396974f,
01492       0.397695f, 0.398415f, 0.399135f, 0.399856f, 0.400576f, 0.401297f,
01493       0.402017f, 0.402738f, 0.403458f, 0.404179f, 0.404899f, 0.405620f,
01494       0.406340f, 0.407061f, 0.407781f, 0.408501f, 0.409222f, 0.409942f,
01495       0.410663f, 0.411383f, 0.412104f, 0.412824f, 0.413545f, 0.414265f,
01496       0.414986f, 0.415706f, 0.416427f, 0.417147f, 0.417867f, 0.418588f,
01497       0.419308f, 0.420029f, 0.420749f, 0.421470f, 0.422190f, 0.422911f,
01498       0.423631f, 0.424352f, 0.425072f, 0.425793f, 0.426513f, 0.427233f,
01499       0.427954f, 0.428674f, 0.429395f, 0.430115f, 0.430836f, 0.431556f,
01500       0.432277f, 0.432997f, 0.433718f, 0.434438f, 0.435158f, 0.435879f,
01501       0.436599f, 0.437320f, 0.438040f, 0.438761f, 0.439481f, 0.440202f,
01502       0.440922f, 0.441643f, 0.442363f, 0.443084f, 0.443804f, 0.444524f,
01503       0.445245f, 0.445965f, 0.446686f, 0.447406f, 0.448127f, 0.448847f,
01504       0.449568f, 0.450288f, 0.451009f, 0.451729f, 0.452450f, 0.453170f,
01505       0.453891f, 0.454611f, 0.455331f, 0.456052f, 0.456772f, 0.457493f,
01506       0.458213f, 0.458934f, 0.459654f, 0.460375f, 0.461095f, 0.461816f,
01507       0.462536f, 0.463256f, 0.463977f, 0.464697f, 0.465418f, 0.466138f,
01508       0.466859f, 0.467579f, 0.468300f, 0.469020f, 0.469741f, 0.470461f,
01509       0.471182f, 0.471902f, 0.472622f, 0.473343f, 0.474063f, 0.474784f,
01510       0.475504f, 0.476225f, 0.476945f, 0.477666f, 0.478386f, 0.479107f,
01511       0.479827f, 0.480548f, 0.481268f, 0.481988f, 0.482709f, 0.483429f,
01512       0.484150f, 0.484870f, 0.485591f, 0.486311f, 0.487032f, 0.487752f,
01513       0.488473f, 0.489193f, 0.489914f, 0.490634f, 0.491354f, 0.492075f,
01514       0.492795f, 0.493516f, 0.494236f, 0.494957f, 0.495677f, 0.496398f,
01515       0.497118f, 0.497839f, 0.498559f, 0.499280f, 0.500000f, 0.500720f,
01516       0.501441f, 0.502161f, 0.502882f, 0.503602f, 0.504323f, 0.505043f,
01517       0.505764f, 0.506484f, 0.507205f, 0.507925f, 0.508646f, 0.509366f,
01518       0.510086f, 0.510807f, 0.511527f, 0.512248f, 0.512968f, 0.513689f,
01519       0.514409f, 0.515130f, 0.515850f, 0.516571f, 0.517291f, 0.518012f,
01520       0.518732f, 0.519452f, 0.520173f, 0.520893f, 0.521614f, 0.522334f,
01521       0.523055f, 0.523775f, 0.524496f, 0.525216f, 0.525937f, 0.526657f,
01522       0.527378f, 0.528098f, 0.528818f, 0.529539f, 0.530259f, 0.530980f,
01523       0.531700f, 0.532421f, 0.533141f, 0.533862f, 0.534582f, 0.535303f,
01524       0.536023f, 0.536744f, 0.537464f, 0.538184f, 0.538905f, 0.539625f,
01525       0.540346f, 0.541066f, 0.541787f, 0.542507f, 0.543228f, 0.543948f,
01526       0.544669f, 0.545389f, 0.546109f, 0.546830f, 0.547550f, 0.548271f,
01527       0.548991f, 0.549712f, 0.550432f, 0.551153f, 0.551873f, 0.552594f,
01528       0.553314f, 0.554035f, 0.554755f, 0.555476f, 0.556196f, 0.556916f,
01529       0.557637f, 0.558357f, 0.559078f, 0.559798f, 0.560519f, 0.561239f,
01530       0.561960f, 0.562680f, 0.563401f, 0.564121f, 0.564842f, 0.565562f,
01531       0.566282f, 0.567003f, 0.567723f, 0.568444f, 0.569164f, 0.569885f,
01532       0.570605f, 0.571326f, 0.572046f, 0.572767f, 0.573487f, 0.574207f,
01533       0.574928f, 0.575648f, 0.576369f, 0.577089f, 0.577810f, 0.578530f,
01534       0.579251f, 0.579971f, 0.580692f, 0.581412f, 0.582133f, 0.582853f,
01535       0.583573f, 0.584294f, 0.585014f, 0.585735f, 0.586455f, 0.587176f,
01536       0.587896f, 0.588617f, 0.589337f, 0.590058f, 0.590778f, 0.591499f,
01537       0.592219f, 0.592939f, 0.593660f, 0.594380f, 0.595101f, 0.595821f,
01538       0.596542f, 0.597262f, 0.597983f, 0.598703f, 0.599424f, 0.600144f,
01539       0.600865f, 0.601585f, 0.602305f, 0.603026f, 0.603746f, 0.604467f,
01540       0.605187f, 0.605908f, 0.606628f, 0.607349f, 0.608069f, 0.608790f,
01541       0.609510f, 0.610231f, 0.610951f, 0.611671f, 0.612392f, 0.613112f,
01542       0.613833f, 0.614553f, 0.615274f, 0.615994f, 0.616715f, 0.617435f,
01543       0.618156f, 0.618876f, 0.619597f, 0.620317f, 0.621037f, 0.621758f,
01544       0.622478f, 0.623199f, 0.623919f, 0.624640f, 0.625360f, 0.626081f,
01545       0.626801f, 0.627522f, 0.628242f, 0.628963f, 0.629683f, 0.630403f,
01546       0.631124f, 0.631844f, 0.632565f, 0.633285f, 0.634006f, 0.634726f,
01547       0.635447f, 0.636167f, 0.636888f, 0.637608f, 0.638329f, 0.639049f,
01548       0.639769f, 0.640490f, 0.641210f, 0.641931f, 0.642651f, 0.643372f,
01549       0.644092f, 0.644813f, 0.645533f, 0.646254f, 0.646974f, 0.647695f,
01550       0.648415f, 0.649135f, 0.649856f, 0.650576f, 0.651297f, 0.652017f,
01551       0.652738f, 0.653458f, 0.654179f, 0.654899f, 0.655620f, 0.656340f,
01552       0.657061f, 0.657781f, 0.658501f, 0.659222f, 0.659942f, 0.660663f,
01553       0.661383f, 0.662104f, 0.662824f, 0.663545f, 0.664265f, 0.664986f,
01554       0.665706f, 0.666427f, 0.667147f, 0.667867f, 0.668588f, 0.669308f,
01555       0.670029f, 0.670749f, 0.671470f, 0.672190f, 0.672911f, 0.673631f,
01556       0.674352f, 0.675072f, 0.675793f, 0.676513f, 0.677233f, 0.677954f,
01557       0.678674f, 0.679395f, 0.680115f, 0.680836f, 0.681556f, 0.682277f,
01558       0.682997f, 0.683718f, 0.684438f, 0.685158f, 0.685879f, 0.686599f,
01559       0.687320f, 0.688040f, 0.688761f, 0.689481f, 0.690202f, 0.690922f,
01560       0.691643f, 0.692363f, 0.693084f, 0.693804f, 0.694524f, 0.695245f,
01561       0.695965f, 0.696686f, 0.697406f, 0.698127f, 0.698847f, 0.699568f,
01562       0.700288f, 0.701009f, 0.701729f, 0.702450f, 0.703170f, 0.703891f,
01563       0.704611f, 0.705331f, 0.706052f, 0.706772f, 0.707493f, 0.708213f,
01564       0.708934f, 0.709654f, 0.710375f, 0.711095f, 0.711816f, 0.712536f,
01565       0.713256f, 0.713977f, 0.714697f, 0.715418f, 0.716138f, 0.716859f,
01566       0.717579f, 0.718300f, 0.719020f, 0.719741f, 0.720461f, 0.721182f,
01567       0.721902f, 0.722622f, 0.723343f, 0.724063f, 0.724784f, 0.725504f,
01568       0.726225f, 0.726945f, 0.727666f, 0.728386f, 0.729107f, 0.729827f,
01569       0.730548f, 0.731268f, 0.731988f, 0.732709f, 0.733429f, 0.734150f,
01570       0.734870f, 0.735591f, 0.736311f, 0.737032f, 0.737752f, 0.738473f,
01571       0.739193f, 0.739914f, 0.740634f, 0.741354f, 0.742075f, 0.742795f,
01572       0.743516f, 0.744236f, 0.744957f, 0.745677f, 0.746398f, 0.747118f,
01573       0.747839f, 0.748559f, 0.749280f, 0.750000f, 0.750720f, 0.751441f,
01574       0.752161f, 0.752882f, 0.753602f, 0.754323f, 0.755043f, 0.755764f,
01575       0.756484f, 0.757205f, 0.757925f, 0.758646f, 0.759366f, 0.760086f,
01576       0.760807f, 0.761527f, 0.762248f, 0.762968f, 0.763689f, 0.764409f,
01577       0.765130f, 0.765850f, 0.766571f, 0.767291f, 0.768012f, 0.768732f,
01578       0.769452f, 0.770173f, 0.770893f, 0.771614f, 0.772334f, 0.773055f,
01579       0.773775f, 0.774496f, 0.775216f, 0.775937f, 0.776657f, 0.777378f,
01580       0.778098f, 0.778818f, 0.779539f, 0.780259f, 0.780980f, 0.781700f,
01581       0.782421f, 0.783141f, 0.783862f, 0.784582f, 0.785303f, 0.786023f,
01582       0.786744f, 0.787464f, 0.788184f, 0.788905f, 0.789625f, 0.790346f,
01583       0.791066f, 0.791787f, 0.792507f, 0.793228f, 0.793948f, 0.794669f,
01584       0.795389f, 0.796109f, 0.796830f, 0.797550f, 0.798271f, 0.798991f,
01585       0.799712f, 0.800432f, 0.801153f, 0.801873f, 0.802594f, 0.803314f,
01586       0.804035f, 0.804755f, 0.805476f, 0.806196f, 0.806916f, 0.807637f,
01587       0.808357f, 0.809078f, 0.809798f, 0.810519f, 0.811239f, 0.811960f,
01588       0.812680f, 0.813401f, 0.814121f, 0.814842f, 0.815562f, 0.816282f,
01589       0.817003f, 0.817723f, 0.818444f, 0.819164f, 0.819885f, 0.820605f,
01590       0.821326f, 0.822046f, 0.822767f, 0.823487f, 0.824207f, 0.824928f,
01591       0.825648f, 0.826369f, 0.827089f, 0.827810f, 0.828530f, 0.829251f,
01592       0.829971f, 0.830692f, 0.831412f, 0.832133f, 0.832853f, 0.833573f,
01593       0.834294f, 0.835014f, 0.835735f, 0.836455f, 0.837176f, 0.837896f,
01594       0.838617f, 0.839337f, 0.840058f, 0.840778f, 0.841499f, 0.842219f,
01595       0.842939f, 0.843660f, 0.844380f, 0.845101f, 0.845821f, 0.846542f,
01596       0.847262f, 0.847983f, 0.848703f, 0.849424f, 0.850144f, 0.850865f,
01597       0.851585f, 0.852305f, 0.853026f, 0.853746f, 0.854467f, 0.855187f,
01598       0.855908f, 0.856628f, 0.857349f, 0.858069f, 0.858790f, 0.859510f,
01599       0.860231f, 0.860951f, 0.861671f, 0.862392f, 0.863112f, 0.863833f,
01600       0.864553f, 0.865274f, 0.865994f, 0.866715f, 0.867435f, 0.868156f,
01601       0.868876f, 0.869597f, 0.870317f, 0.871037f, 0.871758f, 0.872478f,
01602       0.873199f, 0.873919f, 0.874640f, 0.875360f, 0.876081f, 0.876801f,
01603       0.877522f, 0.878242f, 0.878963f, 0.879683f, 0.880403f, 0.881124f,
01604       0.881844f, 0.882565f, 0.883285f, 0.884006f, 0.884726f, 0.885447f,
01605       0.886167f, 0.886888f, 0.887608f, 0.888329f, 0.889049f, 0.889769f,
01606       0.890490f, 0.891210f, 0.891931f, 0.892651f, 0.893372f, 0.894092f,
01607       0.894813f, 0.895533f, 0.896254f, 0.896974f, 0.897695f, 0.898415f,
01608       0.899135f, 0.899856f, 0.900576f, 0.901297f, 0.902017f, 0.902738f,
01609       0.903458f, 0.904179f, 0.904899f, 0.905620f, 0.906340f, 0.907061f,
01610       0.907781f, 0.908501f, 0.909222f, 0.909942f, 0.910663f, 0.911383f,
01611       0.912104f, 0.912824f, 0.913545f, 0.914265f, 0.914986f, 0.915706f,
01612       0.916427f, 0.917147f, 0.917867f, 0.918588f, 0.919308f, 0.920029f,
01613       0.920749f, 0.921470f, 0.922190f, 0.922911f, 0.923631f, 0.924352f,
01614       0.925072f, 0.925793f, 0.926513f, 0.927233f, 0.927954f, 0.928674f,
01615       0.929395f, 0.930115f, 0.930836f, 0.931556f, 0.932277f, 0.932997f,
01616       0.933718f, 0.934438f, 0.935158f, 0.935879f, 0.936599f, 0.937320f,
01617       0.938040f, 0.938761f, 0.939481f, 0.940202f, 0.940922f, 0.941643f,
01618       0.942363f, 0.943084f, 0.943804f, 0.944524f, 0.945245f, 0.945965f,
01619       0.946686f, 0.947406f, 0.948127f, 0.948847f, 0.949568f, 0.950288f,
01620       0.951009f, 0.951729f, 0.952450f, 0.953170f, 0.953891f, 0.954611f,
01621       0.955331f, 0.956052f, 0.956772f, 0.957493f, 0.958213f, 0.958934f,
01622       0.959654f, 0.960375f, 0.961095f, 0.961816f, 0.962536f, 0.963256f,
01623       0.963977f, 0.964697f, 0.965418f, 0.966138f, 0.966859f, 0.967579f,
01624       0.968300f, 0.969020f, 0.969741f, 0.970461f, 0.971182f, 0.971902f,
01625       0.972622f, 0.973343f, 0.974063f, 0.974784f, 0.975504f, 0.976225f,
01626       0.976945f, 0.977666f, 0.978386f, 0.979107f, 0.979827f, 0.980548f,
01627       0.981268f, 0.981988f, 0.982709f, 0.983429f, 0.984150f, 0.984870f,
01628       0.985591f, 0.986311f, 0.987032f, 0.987752f, 0.988473f, 0.989193f,
01629       0.989914f, 0.990634f, 0.991354f, 0.992075f, 0.992795f, 0.993516f,
01630       0.994236f, 0.994957f, 0.995677f, 0.996398f, 0.997118f, 0.997839f,
01631       0.998559f, 0.999280f, 1.000000f
01632     };
01633 #endif
01634 
01635   CacheView
01636     *image_view;
01637 
01638   MagickBooleanType
01639     status;
01640 
01641   MagickOffsetType
01642     progress;
01643 
01644   register ssize_t
01645     i;
01646 
01647   ssize_t
01648     y;
01649 
01650   TransformPacket
01651     *y_map,
01652     *x_map,
01653     *z_map;
01654 
01655   assert(image != (Image *) NULL);
01656   assert(image->signature == MagickSignature);
01657   if (image->debug != MagickFalse)
01658     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01659   status=MagickTrue;
01660   progress=0;
01661   switch (image->colorspace)
01662   {
01663     case CMYColorspace:
01664     {
01665       /*
01666         Transform image from CMY to RGB.
01667       */
01668       if (image->storage_class == PseudoClass)
01669         {
01670           if (SyncImage(image,exception) == MagickFalse)
01671             return(MagickFalse);
01672           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
01673             return(MagickFalse);
01674         }
01675       image_view=AcquireCacheView(image);
01676 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01677       #pragma omp parallel for schedule(static,4) shared(status)
01678 #endif
01679       for (y=0; y < (ssize_t) image->rows; y++)
01680       {
01681         MagickBooleanType
01682           sync;
01683 
01684         register ssize_t
01685           x;
01686 
01687         register Quantum
01688           *restrict q;
01689 
01690         if (status == MagickFalse)
01691           continue;
01692         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01693           exception);
01694         if (q == (Quantum *) NULL)
01695           {
01696             status=MagickFalse;
01697             continue;
01698           }
01699         for (x=0; x < (ssize_t) image->columns; x++)
01700         {
01701           SetPixelRed(image,ClampToQuantum((MagickRealType) (QuantumRange-
01702             GetPixelRed(image,q))),q);
01703           SetPixelGreen(image,ClampToQuantum((MagickRealType) (QuantumRange-
01704             GetPixelGreen(image,q))),q);
01705           SetPixelBlue(image,ClampToQuantum((MagickRealType) (QuantumRange-
01706             GetPixelBlue(image,q))),q);
01707           q+=GetPixelChannels(image);
01708         }
01709         sync=SyncCacheViewAuthenticPixels(image_view,exception);
01710         if (sync == MagickFalse)
01711           status=MagickFalse;
01712       }
01713       image_view=DestroyCacheView(image_view);
01714       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
01715         return(MagickFalse);
01716       return(status);
01717     }
01718     case CMYKColorspace:
01719     {
01720       PixelInfo
01721         zero;
01722 
01723       /*
01724         Transform image from CMYK to RGB.
01725       */
01726       if (image->storage_class == PseudoClass)
01727         {
01728           if (SyncImage(image,exception) == MagickFalse)
01729             return(MagickFalse);
01730           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
01731             return(MagickFalse);
01732         }
01733       GetPixelInfo(image,&zero);
01734       image_view=AcquireCacheView(image);
01735 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01736       #pragma omp parallel for schedule(static,4) shared(status)
01737 #endif
01738       for (y=0; y < (ssize_t) image->rows; y++)
01739       {
01740         MagickBooleanType
01741           sync;
01742 
01743         PixelInfo
01744           pixel;
01745 
01746         register ssize_t
01747           x;
01748 
01749         register Quantum
01750           *restrict q;
01751 
01752         if (status == MagickFalse)
01753           continue;
01754         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01755           exception);
01756         if (q == (Quantum *) NULL)
01757           {
01758             status=MagickFalse;
01759             continue;
01760           }
01761         pixel=zero;
01762         for (x=0; x < (ssize_t) image->columns; x++)
01763         {
01764           GetPixelInfoPixel(image,q,&pixel);
01765           ConvertCMYKToRGB(&pixel);
01766           SetPixelInfoPixel(image,&pixel,q);
01767           q+=GetPixelChannels(image);
01768         }
01769         sync=SyncCacheViewAuthenticPixels(image_view,exception);
01770         if (sync == MagickFalse)
01771           status=MagickFalse;
01772       }
01773       image_view=DestroyCacheView(image_view);
01774       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
01775         return(MagickFalse);
01776       return(status);
01777     }
01778     case HSBColorspace:
01779     {
01780       /*
01781         Transform image from HSB to RGB.
01782       */
01783       if (image->storage_class == PseudoClass)
01784         {
01785           if (SyncImage(image,exception) == MagickFalse)
01786             return(MagickFalse);
01787           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
01788             return(MagickFalse);
01789         }
01790       image_view=AcquireCacheView(image);
01791 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01792       #pragma omp parallel for schedule(static,4) shared(status)
01793 #endif
01794       for (y=0; y < (ssize_t) image->rows; y++)
01795       {
01796         double
01797           brightness,
01798           hue,
01799           saturation;
01800 
01801         MagickBooleanType
01802           sync;
01803 
01804         register ssize_t
01805           x;
01806 
01807         register Quantum
01808           *restrict q;
01809 
01810         if (status == MagickFalse)
01811           continue;
01812         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01813           exception);
01814         if (q == (Quantum *) NULL)
01815           {
01816             status=MagickFalse;
01817             continue;
01818           }
01819         for (x=0; x < (ssize_t) image->columns; x++)
01820         {
01821           double
01822             blue,
01823             green,
01824             red;
01825 
01826           hue=(double) (QuantumScale*GetPixelRed(image,q));
01827           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
01828           brightness=(double) (QuantumScale*GetPixelBlue(image,q));
01829           ConvertHSBToRGB(hue,saturation,brightness,&red,&green,&blue);
01830           SetPixelRed(image,ClampToQuantum(red),q);
01831           SetPixelGreen(image,ClampToQuantum(green),q);
01832           SetPixelBlue(image,ClampToQuantum(blue),q);
01833           q+=GetPixelChannels(image);
01834         }
01835         sync=SyncCacheViewAuthenticPixels(image_view,exception);
01836         if (sync == MagickFalse)
01837           status=MagickFalse;
01838       }
01839       image_view=DestroyCacheView(image_view);
01840       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
01841         return(MagickFalse);
01842       return(status);
01843     }
01844     case HSLColorspace:
01845     {
01846       /*
01847         Transform image from HSL to RGB.
01848       */
01849       if (image->storage_class == PseudoClass)
01850         {
01851           if (SyncImage(image,exception) == MagickFalse)
01852             return(MagickFalse);
01853           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
01854             return(MagickFalse);
01855         }
01856       image_view=AcquireCacheView(image);
01857 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01858       #pragma omp parallel for schedule(static,4) shared(status)
01859 #endif
01860       for (y=0; y < (ssize_t) image->rows; y++)
01861       {
01862         double
01863           hue,
01864           lightness,
01865           saturation;
01866 
01867         MagickBooleanType
01868           sync;
01869 
01870         register ssize_t
01871           x;
01872 
01873         register Quantum
01874           *restrict q;
01875 
01876         if (status == MagickFalse)
01877           continue;
01878         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01879           exception);
01880         if (q == (Quantum *) NULL)
01881           {
01882             status=MagickFalse;
01883             continue;
01884           }
01885         for (x=0; x < (ssize_t) image->columns; x++)
01886         {
01887           double
01888             blue,
01889             green,
01890             red;
01891 
01892           hue=(double) (QuantumScale*GetPixelRed(image,q));
01893           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
01894           lightness=(double) (QuantumScale*GetPixelBlue(image,q));
01895           ConvertHSLToRGB(hue,saturation,lightness,&red,&green,&blue);
01896           SetPixelRed(image,ClampToQuantum(red),q);
01897           SetPixelGreen(image,ClampToQuantum(green),q);
01898           SetPixelBlue(image,ClampToQuantum(blue),q);
01899           q+=GetPixelChannels(image);
01900         }
01901         sync=SyncCacheViewAuthenticPixels(image_view,exception);
01902         if (sync == MagickFalse)
01903           status=MagickFalse;
01904       }
01905       image_view=DestroyCacheView(image_view);
01906       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
01907         return(MagickFalse);
01908       return(status);
01909     }
01910     case HWBColorspace:
01911     {
01912       /*
01913         Transform image from HWB to RGB.
01914       */
01915       if (image->storage_class == PseudoClass)
01916         {
01917           if (SyncImage(image,exception) == MagickFalse)
01918             return(MagickFalse);
01919           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
01920             return(MagickFalse);
01921         }
01922       image_view=AcquireCacheView(image);
01923 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01924       #pragma omp parallel for schedule(static,4) shared(status)
01925 #endif
01926       for (y=0; y < (ssize_t) image->rows; y++)
01927       {
01928         double
01929           blackness,
01930           hue,
01931           whiteness;
01932 
01933         MagickBooleanType
01934           sync;
01935 
01936         register ssize_t
01937           x;
01938 
01939         register Quantum
01940           *restrict q;
01941 
01942         if (status == MagickFalse)
01943           continue;
01944         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
01945           exception);
01946         if (q == (Quantum *) NULL)
01947           {
01948             status=MagickFalse;
01949             continue;
01950           }
01951         for (x=0; x < (ssize_t) image->columns; x++)
01952         {
01953           double
01954             blue,
01955             green,
01956             red;
01957 
01958           hue=(double) (QuantumScale*GetPixelRed(image,q));
01959           whiteness=(double) (QuantumScale*GetPixelGreen(image,q));
01960           blackness=(double) (QuantumScale*GetPixelBlue(image,q));
01961           ConvertHWBToRGB(hue,whiteness,blackness,&red,&green,&blue);
01962           SetPixelRed(image,ClampToQuantum(red),q);
01963           SetPixelGreen(image,ClampToQuantum(green),q);
01964           SetPixelBlue(image,ClampToQuantum(blue),q);
01965           q+=GetPixelChannels(image);
01966         }
01967         sync=SyncCacheViewAuthenticPixels(image_view,exception);
01968         if (sync == MagickFalse)
01969           status=MagickFalse;
01970       }
01971       image_view=DestroyCacheView(image_view);
01972       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
01973         return(MagickFalse);
01974       return(status);
01975     }
01976     case LabColorspace:
01977     {
01978       /*
01979         Transform image from Lab to RGB.
01980       */
01981       if (image->storage_class == PseudoClass)
01982         {
01983           if (SyncImage(image,exception) == MagickFalse)
01984             return(MagickFalse);
01985           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
01986             return(MagickFalse);
01987         }
01988       image_view=AcquireCacheView(image);
01989 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01990       #pragma omp parallel for schedule(static,4) shared(status)
01991 #endif
01992       for (y=0; y < (ssize_t) image->rows; y++)
01993       {
01994         double
01995           a,
01996           b,
01997           L,
01998           X,
01999           Y,
02000           Z;
02001 
02002         MagickBooleanType
02003           sync;
02004 
02005         register ssize_t
02006           x;
02007 
02008         register Quantum
02009           *restrict q;
02010 
02011         if (status == MagickFalse)
02012           continue;
02013         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
02014           exception);
02015         if (q == (Quantum *) NULL)
02016           {
02017             status=MagickFalse;
02018             continue;
02019           }
02020         X=0.0;
02021         Y=0.0;
02022         Z=0.0;
02023         for (x=0; x < (ssize_t) image->columns; x++)
02024         {
02025           Quantum
02026             blue,
02027             green,
02028             red;
02029 
02030           L=QuantumScale*GetPixelRed(image,q);
02031           a=QuantumScale*GetPixelGreen(image,q);
02032           b=QuantumScale*GetPixelBlue(image,q);
02033           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
02034           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
02035           SetPixelRed(image,red,q);
02036           SetPixelGreen(image,green,q);
02037           SetPixelBlue(image,blue,q);
02038           q+=GetPixelChannels(image);
02039         }
02040         sync=SyncCacheViewAuthenticPixels(image_view,exception);
02041         if (sync == MagickFalse)
02042           status=MagickFalse;
02043       }
02044       image_view=DestroyCacheView(image_view);
02045       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
02046         return(MagickFalse);
02047       return(status);
02048     }
02049     case LogColorspace:
02050     {
02051       const char
02052         *value;
02053 
02054       double
02055         black,
02056         density,
02057         film_gamma,
02058         gamma,
02059         reference_black,
02060         reference_white;
02061 
02062       Quantum
02063         *logmap;
02064 
02065       /*
02066         Transform Log to RGB colorspace.
02067       */
02068       density=DisplayGamma;
02069       gamma=DisplayGamma;
02070       value=GetImageProperty(image,"gamma",exception);
02071       if (value != (const char *) NULL)
02072         gamma=1.0/fabs(StringToDouble(value,(char **) NULL)) >=
02073           MagickEpsilon ? StringToDouble(value,(char **) NULL) : 1.0;
02074       film_gamma=FilmGamma;
02075       value=GetImageProperty(image,"film-gamma",exception);
02076       if (value != (const char *) NULL)
02077         film_gamma=StringToDouble(value,(char **) NULL);
02078       reference_black=ReferenceBlack;
02079       value=GetImageProperty(image,"reference-black",exception);
02080       if (value != (const char *) NULL)
02081         reference_black=StringToDouble(value,(char **) NULL);
02082       reference_white=ReferenceWhite;
02083       value=GetImageProperty(image,"reference-white",exception);
02084       if (value != (const char *) NULL)
02085         reference_white=StringToDouble(value,(char **) NULL);
02086       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
02087         sizeof(*logmap));
02088       if (logmap == (Quantum *) NULL)
02089         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
02090           image->filename);
02091       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
02092         0.002/film_gamma);
02093       for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
02094         logmap[i]=(Quantum) 0;
02095       for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0); i++)
02096         logmap[i]=ClampToQuantum((MagickRealType) QuantumRange/(1.0-black)*
02097           (pow(10.0,(1024.0*i/MaxMap-reference_white)*
02098           (gamma/density)*0.002/film_gamma)-black));
02099       for ( ; i <= (ssize_t) MaxMap; i++)
02100         logmap[i]=(Quantum) QuantumRange;
02101       if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
02102         return(MagickFalse);
02103       image_view=AcquireCacheView(image);
02104 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02105       #pragma omp parallel for schedule(static,4) shared(status)
02106 #endif
02107       for (y=0; y < (ssize_t) image->rows; y++)
02108       {
02109         MagickBooleanType
02110           sync;
02111 
02112         register ssize_t
02113           x;
02114 
02115         register Quantum
02116           *restrict q;
02117 
02118         if (status == MagickFalse)
02119           continue;
02120         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
02121           exception);
02122         if (q == (Quantum *) NULL)
02123           {
02124             status=MagickFalse;
02125             continue;
02126           }
02127         for (x=(ssize_t) image->columns; x != 0; x--)
02128         {
02129           SetPixelRed(image,logmap[ScaleQuantumToMap(
02130             GetPixelRed(image,q))],q);
02131           SetPixelGreen(image,logmap[ScaleQuantumToMap(
02132             GetPixelGreen(image,q))],q);
02133           SetPixelBlue(image,logmap[ScaleQuantumToMap(
02134             GetPixelBlue(image,q))],q);
02135           q+=GetPixelChannels(image);
02136         }
02137         sync=SyncCacheViewAuthenticPixels(image_view,exception);
02138         if (sync == MagickFalse)
02139           status=MagickFalse;
02140       }
02141       image_view=DestroyCacheView(image_view);
02142       logmap=(Quantum *) RelinquishMagickMemory(logmap);
02143       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
02144         return(MagickFalse);
02145       return(status);
02146     }
02147     default:
02148       break;
02149   }
02150   /*
02151     Allocate the tables.
02152   */
02153   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
02154     sizeof(*x_map));
02155   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
02156     sizeof(*y_map));
02157   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
02158     sizeof(*z_map));
02159   if ((x_map == (TransformPacket *) NULL) ||
02160       (y_map == (TransformPacket *) NULL) ||
02161       (z_map == (TransformPacket *) NULL))
02162     {
02163       if (z_map != (TransformPacket *) NULL)
02164         z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
02165       if (y_map != (TransformPacket *) NULL)
02166         y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
02167       if (x_map != (TransformPacket *) NULL)
02168         x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
02169       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
02170         image->filename);
02171     }
02172   switch (image->colorspace)
02173   {
02174     case OHTAColorspace:
02175     {
02176       /*
02177         Initialize OHTA tables:
02178 
02179           R = I1+1.00000*I2-0.66668*I3
02180           G = I1+0.00000*I2+1.33333*I3
02181           B = I1-1.00000*I2-0.66668*I3
02182 
02183         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
02184         through QuantumRange.
02185       */
02186 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02187       #pragma omp parallel for schedule(static)
02188 #endif
02189       for (i=0; i <= (ssize_t) MaxMap; i++)
02190       {
02191         x_map[i].x=(MagickRealType) i;
02192         y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType)
02193           MaxMap);
02194         z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
02195           MaxMap);
02196         x_map[i].y=(MagickRealType) i;
02197         y_map[i].y=0.000000f;
02198         z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType)
02199           MaxMap);
02200         x_map[i].z=(MagickRealType) i;
02201         y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType)
02202           MaxMap);
02203         z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
02204           MaxMap);
02205       }
02206       break;
02207     }
02208     case Rec601YCbCrColorspace:
02209     case YCbCrColorspace:
02210     {
02211       /*
02212         Initialize YCbCr tables:
02213 
02214           R = Y            +1.402000*Cr
02215           G = Y-0.344136*Cb-0.714136*Cr
02216           B = Y+1.772000*Cb
02217 
02218         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
02219         through QuantumRange.
02220       */
02221 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02222       #pragma omp parallel for schedule(static)
02223 #endif
02224       for (i=0; i <= (ssize_t) MaxMap; i++)
02225       {
02226         x_map[i].x=(MagickRealType) i;
02227         y_map[i].x=0.000000f;
02228         z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i-
02229           (MagickRealType) MaxMap);
02230         x_map[i].y=(MagickRealType) i;
02231         y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i-
02232           (MagickRealType) MaxMap);
02233         z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i-
02234           (MagickRealType) MaxMap);
02235         x_map[i].z=(MagickRealType) i;
02236         y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i-
02237           (MagickRealType) MaxMap);
02238         z_map[i].z=0.000000f;
02239       }
02240       break;
02241     }
02242     case Rec709YCbCrColorspace:
02243     {
02244       /*
02245         Initialize YCbCr tables:
02246 
02247           R = Y            +1.574800*Cr
02248           G = Y-0.187324*Cb-0.468124*Cr
02249           B = Y+1.855600*Cb
02250 
02251         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
02252         through QuantumRange.
02253       */
02254 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02255       #pragma omp parallel for schedule(static)
02256 #endif
02257       for (i=0; i <= (ssize_t) MaxMap; i++)
02258       {
02259         x_map[i].x=(MagickRealType) i;
02260         y_map[i].x=0.000000f;
02261         z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i-
02262           (MagickRealType) MaxMap);
02263         x_map[i].y=(MagickRealType) i;
02264         y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i-
02265           (MagickRealType) MaxMap);
02266         z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i-
02267           (MagickRealType) MaxMap);
02268         x_map[i].z=(MagickRealType) i;
02269         y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i-
02270           (MagickRealType) MaxMap);
02271         z_map[i].z=0.00000f;
02272       }
02273       break;
02274     }
02275     case sRGBColorspace:
02276     {
02277       /*
02278         Nonlinear sRGB to linear RGB.
02279 
02280           R = 1.0*R+0.0*G+0.0*B
02281           G = 0.0*R+1.0*G+0.0*B
02282           B = 0.0*R+0.0*G+1.0*B
02283       */
02284 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02285       #pragma omp parallel for schedule(static)
02286 #endif
02287       for (i=0; i <= (ssize_t) MaxMap; i++)
02288       {
02289         MagickRealType
02290           v;
02291 
02292         v=(MagickRealType) i/(MagickRealType) MaxMap;
02293         if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.04045f)
02294           v/=12.92f;
02295         else
02296           v=(MagickRealType) pow((((double) i/MaxMap)+0.055)/1.055,2.4);
02297         x_map[i].x=1.0f*MaxMap*v;
02298         y_map[i].x=0.0f*MaxMap*v;
02299         z_map[i].x=0.0f*MaxMap*v;
02300         x_map[i].y=0.0f*MaxMap*v;
02301         y_map[i].y=1.0f*MaxMap*v;
02302         z_map[i].y=0.0f*MaxMap*v;
02303         x_map[i].z=0.0f*MaxMap*v;
02304         y_map[i].z=0.0f*MaxMap*v;
02305         z_map[i].z=1.0f*MaxMap*v;
02306       }
02307       break;
02308     }
02309     case XYZColorspace:
02310     {
02311       /*
02312         Initialize CIE XYZ tables (ITU R-709 RGB):
02313 
02314           R =  3.2404542*X-1.5371385*Y-0.4985314*Z
02315           G = -0.9692660*X+1.8760108*Y+0.0415560*Z
02316           B =  0.0556434*X-0.2040259*Y+1.057225*Z
02317       */
02318 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02319       #pragma omp parallel for schedule(static)
02320 #endif
02321       for (i=0; i <= (ssize_t) MaxMap; i++)
02322       {
02323         x_map[i].x=3.2404542f*(MagickRealType) i;
02324         x_map[i].y=(-0.9692660f)*(MagickRealType) i;
02325         x_map[i].z=0.0556434f*(MagickRealType) i;
02326         y_map[i].x=(-1.5371385f)*(MagickRealType) i;
02327         y_map[i].y=1.8760108f*(MagickRealType) i;
02328         y_map[i].z=(-0.2040259f)*(MagickRealType) i;
02329         z_map[i].x=(-0.4985314f)*(MagickRealType) i;
02330         z_map[i].y=0.0415560f*(MagickRealType) i;
02331         z_map[i].z=1.0572252f*(MagickRealType) i;
02332       }
02333       break;
02334     }
02335     case YCCColorspace:
02336     {
02337       /*
02338         Initialize YCC tables:
02339 
02340           R = Y            +1.340762*C2
02341           G = Y-0.317038*C1-0.682243*C2
02342           B = Y+1.632639*C1
02343 
02344         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
02345       */
02346 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02347       #pragma omp parallel for schedule(static)
02348 #endif
02349       for (i=0; i <= (ssize_t) MaxMap; i++)
02350       {
02351         x_map[i].x=1.3584000f*(MagickRealType) i;
02352         y_map[i].x=0.0000000f;
02353         z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType)
02354           ScaleQuantumToMap(ScaleCharToQuantum(137)));
02355         x_map[i].y=1.3584000f*(MagickRealType) i;
02356         y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType)
02357           ScaleQuantumToMap(ScaleCharToQuantum(156)));
02358         z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType)
02359           ScaleQuantumToMap(ScaleCharToQuantum(137)));
02360         x_map[i].z=1.3584000f*(MagickRealType) i;
02361         y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType)
02362           ScaleQuantumToMap(ScaleCharToQuantum(156)));
02363         z_map[i].z=0.0000000f;
02364       }
02365       break;
02366     }
02367     case YIQColorspace:
02368     {
02369       /*
02370         Initialize YIQ tables:
02371 
02372           R = Y+0.95620*I+0.62140*Q
02373           G = Y-0.27270*I-0.64680*Q
02374           B = Y-1.10370*I+1.70060*Q
02375 
02376         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
02377         through QuantumRange.
02378       */
02379 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02380       #pragma omp parallel for schedule(static)
02381 #endif
02382       for (i=0; i <= (ssize_t) MaxMap; i++)
02383       {
02384         x_map[i].x=(MagickRealType) i;
02385         y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType)
02386           MaxMap);
02387         z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType)
02388           MaxMap);
02389         x_map[i].y=(MagickRealType) i;
02390         y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02391           MaxMap);
02392         z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02393           MaxMap);
02394         x_map[i].z=(MagickRealType) i;
02395         y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02396           MaxMap);
02397         z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType)
02398           MaxMap);
02399       }
02400       break;
02401     }
02402     case YPbPrColorspace:
02403     {
02404       /*
02405         Initialize YPbPr tables:
02406 
02407           R = Y            +1.402000*C2
02408           G = Y-0.344136*C1+0.714136*C2
02409           B = Y+1.772000*C1
02410 
02411         Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
02412         through QuantumRange.
02413       */
02414 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02415       #pragma omp parallel for schedule(static)
02416 #endif
02417       for (i=0; i <= (ssize_t) MaxMap; i++)
02418       {
02419         x_map[i].x=(MagickRealType) i;
02420         y_map[i].x=0.000000f;
02421         z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType)
02422           MaxMap);
02423         x_map[i].y=(MagickRealType) i;
02424         y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02425           MaxMap);
02426         z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType)
02427           MaxMap);
02428         x_map[i].z=(MagickRealType) i;
02429         y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType)
02430           MaxMap);
02431         z_map[i].z=0.00000f;
02432       }
02433       break;
02434     }
02435     case YUVColorspace:
02436     {
02437       /*
02438         Initialize YUV tables:
02439 
02440           R = Y          +1.13980*V
02441           G = Y-0.39380*U-0.58050*V
02442           B = Y+2.02790*U
02443 
02444         U and V, normally -0.5 through 0.5, must be normalized to the range 0
02445         through QuantumRange.
02446       */
02447 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02448       #pragma omp parallel for schedule(static)
02449 #endif
02450       for (i=0; i <= (ssize_t) MaxMap; i++)
02451       {
02452         x_map[i].x=(MagickRealType) i;
02453         y_map[i].x=0.00000f;
02454         z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType)
02455           MaxMap);
02456         x_map[i].y=(MagickRealType) i;
02457         y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02458           MaxMap);
02459         z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType)
02460           MaxMap);
02461         x_map[i].z=(MagickRealType) i;
02462         y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType)
02463           MaxMap);
02464         z_map[i].z=0.00000f;
02465       }
02466       break;
02467     }
02468     default:
02469     {
02470       /*
02471         Linear conversion tables.
02472       */
02473 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02474       #pragma omp parallel for schedule(static)
02475 #endif
02476       for (i=0; i <= (ssize_t) MaxMap; i++)
02477       {
02478         x_map[i].x=(MagickRealType) i;
02479         y_map[i].x=0.0f;
02480         z_map[i].x=0.0f;
02481         x_map[i].y=0.0f;
02482         y_map[i].y=(MagickRealType) i;
02483         z_map[i].y=0.0f;
02484         x_map[i].z=0.0f;
02485         y_map[i].z=0.0f;
02486         z_map[i].z=(MagickRealType) i;
02487       }
02488       break;
02489     }
02490   }
02491   /*
02492     Convert to RGB.
02493   */
02494   switch (image->storage_class)
02495   {
02496     case DirectClass:
02497     default:
02498     {
02499       /*
02500         Convert DirectClass image.
02501       */
02502       image_view=AcquireCacheView(image);
02503 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02504       #pragma omp parallel for schedule(static,4) shared(status)
02505 #endif
02506       for (y=0; y < (ssize_t) image->rows; y++)
02507       {
02508         MagickBooleanType
02509           sync;
02510 
02511         PixelInfo
02512           pixel;
02513 
02514         register ssize_t
02515           x;
02516 
02517         register Quantum
02518           *restrict q;
02519 
02520         if (status == MagickFalse)
02521           continue;
02522         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
02523           exception);
02524         if (q == (Quantum *) NULL)
02525           {
02526             status=MagickFalse;
02527             continue;
02528           }
02529         for (x=0; x < (ssize_t) image->columns; x++)
02530         {
02531           register size_t
02532             blue,
02533             green,
02534             red;
02535 
02536           red=ScaleQuantumToMap(GetPixelRed(image,q));
02537           green=ScaleQuantumToMap(GetPixelGreen(image,q));
02538           blue=ScaleQuantumToMap(GetPixelBlue(image,q));
02539           pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
02540           pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
02541           pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
02542           switch (colorspace)
02543           {
02544             case YCCColorspace:
02545             {
02546 #if !defined(MAGICKCORE_HDRI_SUPPORT)
02547               pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
02548                 pixel.red)];
02549               pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
02550                 pixel.green)];
02551               pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
02552                 pixel.blue)];
02553 #endif
02554               break;
02555             }
02556             case sRGBColorspace:
02557             {
02558               if ((QuantumScale*pixel.red) <= 0.0031308)
02559                 pixel.red*=12.92f;
02560               else
02561                 pixel.red=(MagickRealType) QuantumRange*(1.055*
02562                   pow(QuantumScale*pixel.red,(1.0/2.4))-0.055);
02563               if ((QuantumScale*pixel.green) <= 0.0031308)
02564                 pixel.green*=12.92f;
02565               else
02566                 pixel.green=(MagickRealType) QuantumRange*(1.055*
02567                   pow(QuantumScale*pixel.green,(1.0/2.4))-0.055);
02568               if ((QuantumScale*pixel.blue) <= 0.0031308)
02569                 pixel.blue*=12.92f;
02570               else
02571                 pixel.blue=(MagickRealType) QuantumRange*(1.055*
02572                   pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055);
02573               break;
02574             }
02575             default:
02576               break;
02577           }
02578           SetPixelRed(image,ScaleMapToQuantum((MagickRealType) MaxMap*
02579             QuantumScale*pixel.red),q);
02580           SetPixelGreen(image,ScaleMapToQuantum((MagickRealType) MaxMap*
02581             QuantumScale*pixel.green),q);
02582           SetPixelBlue(image,ScaleMapToQuantum((MagickRealType) MaxMap*
02583             QuantumScale*pixel.blue),q);
02584           q+=GetPixelChannels(image);
02585         }
02586         sync=SyncCacheViewAuthenticPixels(image_view,exception);
02587         if (sync == MagickFalse)
02588           status=MagickFalse;
02589         if (image->progress_monitor != (MagickProgressMonitor) NULL)
02590           {
02591             MagickBooleanType
02592               proceed;
02593 
02594 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02595             #pragma omp critical (MagickCore_TransformRGBImage)
02596 #endif
02597             proceed=SetImageProgress(image,TransformRGBImageTag,progress++,
02598               image->rows);
02599             if (proceed == MagickFalse)
02600               status=MagickFalse;
02601           }
02602       }
02603       image_view=DestroyCacheView(image_view);
02604       break;
02605     }
02606     case PseudoClass:
02607     {
02608       /*
02609         Convert PseudoClass image.
02610       */
02611       image_view=AcquireCacheView(image);
02612 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02613       #pragma omp parallel for schedule(static,4) shared(status)
02614 #endif
02615       for (i=0; i < (ssize_t) image->colors; i++)
02616       {
02617         PixelInfo
02618           pixel;
02619 
02620         register size_t
02621           blue,
02622           green,
02623           red;
02624 
02625         red=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red));
02626         green=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green));
02627         blue=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue));
02628         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
02629         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
02630         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
02631         switch (colorspace)
02632         {
02633           case YCCColorspace:
02634           {
02635 #if !defined(MAGICKCORE_HDRI_SUPPORT)
02636             image->colormap[i].red=(double) (QuantumRange*YCCMap[
02637               RoundToYCC(1024.0*QuantumScale*pixel.red)]);
02638             image->colormap[i].green=(double) (QuantumRange*YCCMap[
02639               RoundToYCC(1024.0*QuantumScale*pixel.green)]);
02640             image->colormap[i].blue=(double) (QuantumRange*YCCMap[
02641               RoundToYCC(1024.0*QuantumScale*pixel.blue)]);
02642 #endif
02643             break;
02644           }
02645           case sRGBColorspace:
02646           {
02647             if ((QuantumScale*pixel.red) <= 0.0031308)
02648               pixel.red*=12.92f;
02649             else
02650               pixel.red=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
02651                 pixel.red,(1.0/2.4))-0.055);
02652             if ((QuantumScale*pixel.green) <= 0.0031308)
02653               pixel.green*=12.92f;
02654             else
02655               pixel.green=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
02656                 pixel.green,(1.0/2.4))-0.055);
02657             if ((QuantumScale*pixel.blue) <= 0.0031308)
02658               pixel.blue*=12.92f;
02659             else
02660               pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
02661                 pixel.blue,(1.0/2.4))-0.055);
02662           }
02663           default:
02664           {
02665             image->colormap[i].red=(double) ScaleMapToQuantum((MagickRealType)
02666               MaxMap*QuantumScale*pixel.red);
02667             image->colormap[i].green=(double) ScaleMapToQuantum((MagickRealType)
02668               MaxMap*QuantumScale*pixel.green);
02669             image->colormap[i].blue=(double) ScaleMapToQuantum((MagickRealType)
02670               MaxMap*QuantumScale*pixel.blue);
02671             break;
02672           }
02673         }
02674       }
02675       image_view=DestroyCacheView(image_view);
02676       (void) SyncImage(image,exception);
02677       break;
02678     }
02679   }
02680   /*
02681     Relinquish resources.
02682   */
02683   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
02684   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
02685   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
02686   if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
02687     return(MagickFalse);
02688   return(MagickTrue);
02689 }