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-2008 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 "magick/studio.h"
00043 #include "magick/property.h"
00044 #include "magick/cache.h"
00045 #include "magick/cache-view.h"
00046 #include "magick/color.h"
00047 #include "magick/color-private.h"
00048 #include "magick/colorspace.h"
00049 #include "magick/colorspace-private.h"
00050 #include "magick/exception.h"
00051 #include "magick/exception-private.h"
00052 #include "magick/image.h"
00053 #include "magick/image-private.h"
00054 #include "magick/gem.h"
00055 #include "magick/memory_.h"
00056 #include "magick/monitor.h"
00057 #include "magick/monitor-private.h"
00058 #include "magick/pixel-private.h"
00059 #include "magick/quantize.h"
00060 #include "magick/quantum.h"
00061 #include "magick/string_.h"
00062 #include "magick/utility.h"
00063 
00064 /*
00065   Typedef declarations.
00066 */
00067 typedef struct _TransformPacket
00068 {
00069   MagickRealType
00070     x,
00071     y,
00072     z;
00073 } TransformPacket;
00074 
00075 /*
00076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00077 %                                                                             %
00078 %                                                                             %
00079 %                                                                             %
00080 +     R G B T r a n s f o r m I m a g e                                       %
00081 %                                                                             %
00082 %                                                                             %
00083 %                                                                             %
00084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00085 %
00086 %  RGBTransformImage() converts the reference image from RGB to an alternate
00087 %  colorspace.  The transformation matrices are not the standard ones: the
00088 %  weights are rescaled to normalized the range of the transformed values to
00089 %  be [0..QuantumRange].
00090 %
00091 %  The format of the RGBTransformImage method is:
00092 %
00093 %      MagickBooleanType RGBTransformImage(Image *image,
00094 %        const ColorspaceType colorspace)
00095 %
00096 %  A description of each parameter follows:
00097 %
00098 %    o image: the image.
00099 %
00100 %    o colorspace: the colorspace to transform the image to.
00101 %
00102 */
00103 
00104 static inline void ConvertRGBToXYZ(const Quantum red,const Quantum green,
00105   const Quantum blue,double *X,double *Y,double *Z)
00106 {
00107   double
00108     b,
00109     g,
00110     r;
00111 
00112   assert(X != (double *) NULL);
00113   assert(Y != (double *) NULL);
00114   assert(Z != (double *) NULL);
00115   r=QuantumScale*red;
00116   g=QuantumScale*green;
00117   b=QuantumScale*blue;
00118   *X=0.4124240*r+0.3575790*g+0.1804640*b;
00119   *Y=0.2126560*r+0.7151580*g+0.0721856*b;
00120   *Z=0.0193324*r+0.1191930*g+0.9504440*b;
00121 }
00122 
00123 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
00124   double *L,double *a,double *b)
00125 {
00126   double
00127     x,
00128     y,
00129     z;
00130 
00131   assert(L != (double *) NULL);
00132   assert(a != (double *) NULL);
00133   assert(b != (double *) NULL);
00134   x=X/0.9504559271;
00135   if (x > (216/24389.0))
00136     x=pow(x,1.0/3.0);
00137   else 
00138     x=(7.787*x)+(16.0/116.0);
00139   y=Y/1.00000;
00140   if (y > (216/24389.0))
00141     y=pow(y,1.0/3.0);
00142   else
00143     y=(7.787*y)+(16.0/116.0);
00144   z=Z/1.0890577508;
00145   if (z > (216/24389.0))
00146     z=pow(z,1.0/3.0);
00147   else
00148     z=(7.787*z)+(16.0/116.0);
00149   *L=0.5*((1.160*y)-0.160+1.0);
00150   *a=0.5*(5.000*(x-y)+1.0);
00151   *b=0.5*(2.000*(y-z)+1.0);
00152 }
00153 
00154 MagickExport MagickBooleanType RGBTransformImage(Image *image,
00155   const ColorspaceType colorspace)
00156 {
00157 #define RGBTransformImageTag  "RGBTransform/Image"
00158 
00159   ExceptionInfo
00160     *exception;
00161 
00162   long
00163     progress,
00164     y;
00165 
00166   MagickBooleanType
00167     status,
00168     sync;
00169 
00170   PrimaryInfo
00171     primary_info;
00172 
00173   register long
00174     i;
00175 
00176   TransformPacket
00177     *x_map,
00178     *y_map,
00179     *z_map;
00180 
00181   ViewInfo
00182     **image_view;
00183 
00184   assert(image != (Image *) NULL);
00185   assert(image->signature == MagickSignature);
00186   if (image->debug != MagickFalse)
00187     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00188   assert(colorspace != RGBColorspace);
00189   assert(colorspace != TransparentColorspace);
00190   assert(colorspace != UndefinedColorspace);
00191   switch (image->colorspace)
00192   {
00193     case GRAYColorspace:
00194     case Rec601LumaColorspace:
00195     case Rec709LumaColorspace:
00196     case RGBColorspace:
00197     case TransparentColorspace:
00198       break;
00199     default:
00200     {
00201       (void) SetImageColorspace(image,image->colorspace);
00202       break;
00203     }
00204   }
00205   image->colorspace=colorspace;
00206   status=MagickTrue;
00207   progress=0;
00208   exception=(&image->exception);
00209   switch (colorspace)
00210   {
00211     case CMYColorspace:
00212     {
00213       /*
00214         Convert RGB to CMY colorspace.
00215       */
00216       if (image->storage_class == PseudoClass)
00217         {
00218           if (SyncImage(image) == MagickFalse)
00219             return(MagickFalse);
00220           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00221             return(MagickFalse);
00222         }
00223       image_view=AcquireCacheViewThreadSet(image);
00224 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00225   #pragma omp parallel for schedule(dynamic,8) shared(status)
00226 #endif
00227       for (y=0; y < (long) image->rows; y++)
00228       {
00229         register long
00230           id,
00231           x;
00232 
00233         register PixelPacket
00234           *q;
00235 
00236         if (status == MagickFalse)
00237           continue;
00238         id=GetCacheViewThreadId();
00239         q=GetCacheViewAuthenticPixels(image_view[id],0,y,image->columns,1,
00240           exception);
00241         if (q == (PixelPacket *) NULL)
00242           {
00243             status=MagickFalse;
00244             continue;
00245           }
00246         for (x=0; x < (long) image->columns; x++)
00247         {
00248           q->red=RoundToQuantum((MagickRealType) (QuantumRange-q->red));
00249           q->green=RoundToQuantum((MagickRealType) (QuantumRange-q->green));
00250           q->blue=RoundToQuantum((MagickRealType) (QuantumRange-q->blue));
00251           q++;
00252         }
00253         sync=SyncCacheViewAuthenticPixels(image_view[id],exception);
00254         if (sync == MagickFalse)
00255           status=MagickFalse;
00256       }
00257       image_view=DestroyCacheViewThreadSet(image_view);
00258       image->type=image->matte == MagickFalse ? ColorSeparationType :
00259         ColorSeparationMatteType;
00260       return(status);
00261     }
00262     case CMYKColorspace:
00263     {
00264       MagickPixelPacket
00265         zero;
00266 
00267       /*
00268         Convert RGB to CMYK colorspace.
00269       */
00270       if (image->storage_class == PseudoClass)
00271         {
00272           if (SyncImage(image) == MagickFalse)
00273             return(MagickFalse);
00274           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00275             return(MagickFalse);
00276         }
00277       GetMagickPixelPacket(image,&zero);
00278       image_view=AcquireCacheViewThreadSet(image);
00279 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00280   #pragma omp parallel for schedule(dynamic,8) shared(status)
00281 #endif
00282       for (y=0; y < (long) image->rows; y++)
00283       {
00284         MagickPixelPacket
00285           pixel;
00286 
00287         register IndexPacket
00288           *indexes;
00289 
00290         register long
00291           id,
00292           x;
00293 
00294         register PixelPacket
00295           *q;
00296 
00297         if (status == MagickFalse)
00298           continue;
00299         id=GetCacheViewThreadId();
00300         q=GetCacheViewAuthenticPixels(image_view[id],0,y,image->columns,1,
00301           exception);
00302         if (q == (PixelPacket *) NULL)
00303           {
00304             status=MagickFalse;
00305             continue;
00306           }
00307         indexes=GetCacheViewAuthenticIndexes(image_view[id]);
00308         pixel=zero;
00309         for (x=0; x < (long) image->columns; x++)
00310         {
00311           SetMagickPixelPacket(image,q,indexes+x,&pixel);
00312           ConvertRGBToCMYK(&pixel);
00313           SetPixelPacket(image,&pixel,q,indexes+x);
00314           q++;
00315         }
00316         sync=SyncCacheViewAuthenticPixels(image_view[id],exception);
00317         if (sync == MagickFalse)
00318           status=MagickFalse;
00319       }
00320       image_view=DestroyCacheViewThreadSet(image_view);
00321       image->type=image->matte == MagickFalse ? ColorSeparationType :
00322         ColorSeparationMatteType;
00323       return(status);
00324     }
00325     case HSBColorspace:
00326     {
00327       /*
00328         Transform image from RGB to HSB.
00329       */
00330       if (image->storage_class == PseudoClass)
00331         {
00332           if (SyncImage(image) == MagickFalse)
00333             return(MagickFalse);
00334           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00335             return(MagickFalse);
00336         }
00337       image_view=AcquireCacheViewThreadSet(image);
00338 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00339   #pragma omp parallel for schedule(dynamic,8) shared(status)
00340 #endif
00341       for (y=0; y < (long) image->rows; y++)
00342       {
00343         double
00344           brightness,
00345           hue,
00346           saturation;
00347 
00348         register long
00349           id,
00350           x;
00351 
00352         register PixelPacket
00353           *q;
00354 
00355         if (status == MagickFalse)
00356           continue;
00357         id=GetCacheViewThreadId();
00358         q=GetCacheViewAuthenticPixels(image_view[id],0,y,image->columns,1,
00359           exception);
00360         if (q == (PixelPacket *) NULL)
00361           {
00362             status=MagickFalse;
00363             continue;
00364           }
00365         hue=0.0;
00366         saturation=0.0;
00367         brightness=0.0;
00368         for (x=0; x < (long) image->columns; x++)
00369         {
00370           ConvertRGBToHSB(q->red,q->green,q->blue,&hue,&saturation,&brightness);
00371           q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
00372           q->green=RoundToQuantum((MagickRealType) QuantumRange*saturation);
00373           q->blue=RoundToQuantum((MagickRealType) QuantumRange*brightness);
00374           q++;
00375         }
00376         sync=SyncCacheViewAuthenticPixels(image_view[id],exception);
00377         if (sync == MagickFalse)
00378           status=MagickFalse;
00379       }
00380       image_view=DestroyCacheViewThreadSet(image_view);
00381       return(status);
00382     }
00383     case HSLColorspace:
00384     {
00385       /*
00386         Transform image from RGB to HSL.
00387       */
00388       if (image->storage_class == PseudoClass)
00389         {
00390           if (SyncImage(image) == MagickFalse)
00391             return(MagickFalse);
00392           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00393             return(MagickFalse);
00394         }
00395       image_view=AcquireCacheViewThreadSet(image);
00396 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00397   #pragma omp parallel for schedule(dynamic,8) shared(status)
00398 #endif
00399       for (y=0; y < (long) image->rows; y++)
00400       {
00401         double
00402           hue,
00403           lightness,
00404           saturation;
00405 
00406         register long
00407           id,
00408           x;
00409 
00410         register PixelPacket
00411           *q;
00412 
00413         if (status == MagickFalse)
00414           continue;
00415         id=GetCacheViewThreadId();
00416         q=GetCacheViewAuthenticPixels(image_view[id],0,y,image->columns,1,
00417           exception);
00418         if (q == (PixelPacket *) NULL)
00419           {
00420             status=MagickFalse;
00421             continue;
00422           }
00423         hue=0.0;
00424         saturation=0.0;
00425         lightness=0.0;
00426         for (x=0; x < (long) image->columns; x++)
00427         {
00428           ConvertRGBToHSL(q->red,q->green,q->blue,&hue,&saturation,&lightness);
00429           q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
00430           q->green=RoundToQuantum((MagickRealType) QuantumRange*saturation);
00431           q->blue=RoundToQuantum((MagickRealType) QuantumRange*lightness);
00432           q++;
00433         }
00434         sync=SyncCacheViewAuthenticPixels(image_view[id],exception);
00435         if (sync == MagickFalse)
00436           status=MagickFalse;
00437       }
00438       image_view=DestroyCacheViewThreadSet(image_view);
00439       return(status);
00440     }
00441     case HWBColorspace:
00442     {
00443       /*
00444         Transform image from RGB to HWB.
00445       */
00446       if (image->storage_class == PseudoClass)
00447         {
00448           if (SyncImage(image) == MagickFalse)
00449             return(MagickFalse);
00450           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00451             return(MagickFalse);
00452         }
00453       image_view=AcquireCacheViewThreadSet(image);
00454 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00455   #pragma omp parallel for schedule(dynamic,8) shared(status)
00456 #endif
00457       for (y=0; y < (long) image->rows; y++)
00458       {
00459         double
00460           blackness,
00461           hue,
00462           whiteness;
00463 
00464         register long
00465           id,
00466           x;
00467 
00468         register PixelPacket
00469           *q;
00470 
00471         if (status == MagickFalse)
00472           continue;
00473         id=GetCacheViewThreadId();
00474         q=GetCacheViewAuthenticPixels(image_view[id],0,y,image->columns,1,
00475           exception);
00476         if (q == (PixelPacket *) NULL)
00477           {
00478             status=MagickFalse;
00479             continue;
00480           }
00481         hue=0.0;
00482         whiteness=0.0;
00483         blackness=0.0;
00484         for (x=0; x < (long) image->columns; x++)
00485         {
00486           ConvertRGBToHWB(q->red,q->green,q->blue,&hue,&whiteness,&blackness);
00487           q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
00488           q->green=RoundToQuantum((MagickRealType) QuantumRange*whiteness);
00489           q->blue=RoundToQuantum((MagickRealType) QuantumRange*blackness);
00490           q++;
00491         }
00492         sync=SyncCacheViewAuthenticPixels(image_view[id],exception);
00493         if (sync == MagickFalse)
00494           status=MagickFalse;
00495       }
00496       image_view=DestroyCacheViewThreadSet(image_view);
00497       return(status);
00498     }
00499     case LabColorspace:
00500     {
00501       /*
00502         Transform image from RGB to Lab.
00503       */
00504       if (image->storage_class == PseudoClass)
00505         {
00506           if (SyncImage(image) == MagickFalse)
00507             return(MagickFalse);
00508           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
00509             return(MagickFalse);
00510         }
00511       image_view=AcquireCacheViewThreadSet(image);
00512 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00513   #pragma omp parallel for schedule(dynamic,8) shared(status)
00514 #endif
00515       for (y=0; y < (long) image->rows; y++)
00516       {
00517         double
00518           a,
00519           b,
00520           L,
00521           X,
00522           Y,
00523           Z;
00524 
00525         register long
00526           id,
00527           x;
00528 
00529         register PixelPacket
00530           *q;
00531 
00532         if (status == MagickFalse)
00533           continue;
00534         id=GetCacheViewThreadId();
00535         q=GetCacheViewAuthenticPixels(image_view[id],0,y,image->columns,1,
00536           exception);
00537         if (q == (PixelPacket *) NULL)
00538           {
00539             status=MagickFalse;
00540             continue;
00541           }
00542         L=0.0;
00543         a=0.0;
00544         b=0.0;
00545         X=0.0;
00546         Y=0.0;
00547         Z=0.0;
00548         for (x=0; x < (long) image->columns; x++)
00549         {
00550           ConvertRGBToXYZ(q->red,q->green,q->blue,&X,&Y,&Z);
00551           ConvertXYZToLab(X,Y,Z,&L,&a,&b);
00552           q->red=RoundToQuantum((MagickRealType) QuantumRange*L);
00553           q->green=RoundToQuantum((MagickRealType) QuantumRange*a);
00554           q->blue=RoundToQuantum((MagickRealType) QuantumRange*b);
00555           q++;
00556         }
00557         sync=SyncCacheViewAuthenticPixels(image_view[id],exception);
00558         if (sync == MagickFalse)
00559           status=MagickFalse;
00560       }
00561       image_view=DestroyCacheViewThreadSet(image_view);
00562       return(status);
00563     }
00564     case LogColorspace:
00565     {
00566 #define ReferenceBlack  95.0
00567 #define ReferenceWhite  685.0
00568 #define DisplayGamma  (1.0/1.7)
00569 
00570       const char
00571         *value;
00572 
00573       double
00574         black,
00575         density,
00576         gamma,
00577         reference_black,
00578         reference_white;
00579 
00580       Quantum
00581         *logmap;
00582 
00583       /*
00584         Transform RGB to Log colorspace.
00585       */
00586       density=2.03728;
00587       gamma=DisplayGamma;
00588       value=GetImageProperty(image,"gamma");
00589       if (value != (const char *) NULL)
00590         gamma=1.0/atof(value) != 0.0 ? atof(value) : 1.0;
00591       reference_black=ReferenceBlack;
00592       value=GetImageProperty(image,"reference-black");
00593       if (value != (const char *) NULL)
00594         reference_black=atof(value);
00595       reference_white=ReferenceWhite;
00596       value=GetImageProperty(image,"reference-white");
00597       if (value != (const char *) NULL)
00598         reference_white=atof(value);
00599       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00600         sizeof(*logmap));
00601       if (logmap == (Quantum *) NULL)
00602         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00603           image->filename);
00604       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
00605         0.002/0.6);
00606 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00607   #pragma omp parallel for schedule(dynamic,8)
00608 #endif
00609       for (i=0; i <= (long) MaxMap; i++)
00610         logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+
00611           log10(black+((MagickRealType) i/MaxMap)*(1.0-black))/((gamma/density)*
00612           0.002/0.6))/1024.0+0.5));
00613       image_view=AcquireCacheViewThreadSet(image);
00614 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00615   #pragma omp parallel for schedule(dynamic,8) shared(status)
00616 #endif
00617       for (y=0; y < (long) image->rows; y++)
00618       {
00619         register long
00620           id,
00621           x;
00622 
00623         register PixelPacket
00624           *q;
00625 
00626         if (status == MagickFalse)
00627           continue;
00628         id=GetCacheViewThreadId();
00629         q=GetCacheViewAuthenticPixels(image_view[id],0,y,image->columns,1,
00630           exception);
00631         if (q == (PixelPacket *) NULL)
00632           {
00633             status=MagickFalse;
00634             continue;
00635           }
00636         for (x=(long) image->columns; x != 0; x--)
00637         {
00638           q->red=logmap[ScaleQuantumToMap(q->red)];
00639           q->green=logmap[ScaleQuantumToMap(q->green)];
00640           q->blue=logmap[ScaleQuantumToMap(q->blue)];
00641           q++;
00642         }
00643         sync=SyncCacheViewAuthenticPixels(image_view[id],exception);
00644         if (sync == MagickFalse)
00645           status=MagickFalse;
00646       }
00647       image_view=DestroyCacheViewThreadSet(image_view);
00648       logmap=(Quantum *) RelinquishMagickMemory(logmap);
00649       return(status);
00650     }
00651     default:
00652       break;
00653   }
00654   /*
00655     Allocate the tables.
00656   */
00657   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00658     sizeof(*x_map));
00659   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00660     sizeof(*y_map));
00661   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
00662     sizeof(*z_map));
00663   if ((x_map == (TransformPacket *) NULL) ||
00664       (y_map == (TransformPacket *) NULL) ||
00665       (z_map == (TransformPacket *) NULL))
00666     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00667       image->filename);
00668   (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
00669   switch (colorspace)
00670   {
00671     case OHTAColorspace:
00672     {
00673       /*
00674         Initialize OHTA tables:
00675 
00676           I1 = 0.33333*R+0.33334*G+0.33333*B
00677           I2 = 0.50000*R+0.00000*G-0.50000*B
00678           I3 =-0.25000*R+0.50000*G-0.25000*B
00679 
00680         I and Q, normally -0.5 through 0.5, are normalized to the range 0
00681         through QuantumRange.
00682       */
00683       primary_info.y=(double) (MaxMap+1.0)/2.0;
00684       primary_info.z=(double) (MaxMap+1.0)/2.0;
00685 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00686   #pragma omp parallel for schedule(dynamic,8)
00687 #endif
00688       for (i=0; i <= (long) MaxMap; i++)
00689       {
00690         x_map[i].x=0.33333f*(MagickRealType) i;
00691         y_map[i].x=0.33334f*(MagickRealType) i;
00692         z_map[i].x=0.33333f*(MagickRealType) i;
00693         x_map[i].y=0.50000f*(MagickRealType) i;
00694         y_map[i].y=0.00000f*(MagickRealType) i;
00695         z_map[i].y=(-0.50000f)*(MagickRealType) i;
00696         x_map[i].z=(-0.25000f)*(MagickRealType) i;
00697         y_map[i].z=0.50000f*(MagickRealType) i;
00698         z_map[i].z=(-0.25000f)*(MagickRealType) i;
00699       }
00700       break;
00701     }
00702     case Rec601LumaColorspace:
00703     case GRAYColorspace:
00704     {
00705       /*
00706         Initialize Rec601 luma tables:
00707 
00708           G = 0.29900*R+0.58700*G+0.11400*B
00709       */
00710 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00711   #pragma omp parallel for schedule(dynamic,8)
00712 #endif
00713       for (i=0; i <= (long) MaxMap; i++)
00714       {
00715         x_map[i].x=0.29900f*(MagickRealType) i;
00716         y_map[i].x=0.58700f*(MagickRealType) i;
00717         z_map[i].x=0.11400f*(MagickRealType) i;
00718         x_map[i].y=0.29900f*(MagickRealType) i;
00719         y_map[i].y=0.58700f*(MagickRealType) i;
00720         z_map[i].y=0.11400f*(MagickRealType) i;
00721         x_map[i].z=0.29900f*(MagickRealType) i;
00722         y_map[i].z=0.58700f*(MagickRealType) i;
00723         z_map[i].z=0.11400f*(MagickRealType) i;
00724       }
00725       image->type=GrayscaleType;
00726       break;
00727     }
00728     case Rec601YCbCrColorspace:
00729     case YCbCrColorspace:
00730     {
00731       /*
00732         Initialize YCbCr tables (ITU-R BT.601):
00733 
00734           Y =  0.299000*R+0.587000*G+0.114000*B
00735           Cb= -0.168736*R-0.331264*G+0.500000*B
00736           Cr=  0.500000*R-0.418688*G-0.081312*B
00737 
00738         Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
00739         through QuantumRange.
00740       */
00741       primary_info.y=(double) (MaxMap+1.0)/2.0;
00742       primary_info.z=(double) (MaxMap+1.0)/2.0;
00743 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00744   #pragma omp parallel for schedule(dynamic,8)
00745 #endif
00746       for (i=0; i <= (long) MaxMap; i++)
00747       {
00748         x_map[i].x=0.299000f*(MagickRealType) i;
00749         y_map[i].x=0.587000f*(MagickRealType) i;
00750         z_map[i].x=0.114000f*(MagickRealType) i;
00751         x_map[i].y=(-0.168730f)*(MagickRealType) i;
00752         y_map[i].y=(-0.331264f)*(MagickRealType) i;
00753         z_map[i].y=0.500000f*(MagickRealType) i;
00754         x_map[i].z=0.500000f*(MagickRealType) i;
00755         y_map[i].z=(-0.418688f)*(MagickRealType) i;
00756         z_map[i].z=(-0.081312f)*(MagickRealType) i;
00757       }
00758       break;
00759     }
00760     case Rec709LumaColorspace:
00761     {
00762       /*
00763         Initialize Rec709 luma tables:
00764 
00765           G = 0.21260*R+0.71520*G+0.07220*B
00766       */
00767 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00768   #pragma omp parallel for schedule(dynamic,8)
00769 #endif
00770       for (i=0; i <= (long) MaxMap; i++)
00771       {
00772         x_map[i].x=0.21260f*(MagickRealType) i;
00773         y_map[i].x=0.71520f*(MagickRealType) i;
00774         z_map[i].x=0.07220f*(MagickRealType) i;
00775         x_map[i].y=0.21260f*(MagickRealType) i;
00776         y_map[i].y=0.71520f*(MagickRealType) i;
00777         z_map[i].y=0.07220f*(MagickRealType) i;
00778         x_map[i].z=0.21260f*(MagickRealType) i;
00779         y_map[i].z=0.71520f*(MagickRealType) i;
00780         z_map[i].z=0.07220f*(MagickRealType) i;
00781       }
00782       break;
00783     }
00784     case Rec709YCbCrColorspace:
00785     {
00786       /*
00787         Initialize YCbCr tables (ITU-R BT.709):
00788 
00789           Y =  0.212600*R+0.715200*G+0.072200*B
00790           Cb= -0.114572*R-0.385428*G+0.500000*B
00791           Cr=  0.500000*R-0.454153*G-0.045847*B
00792 
00793         Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
00794         through QuantumRange.
00795       */
00796       primary_info.y=(double) (MaxMap+1.0)/2.0;
00797       primary_info.z=(double) (MaxMap+1.0)/2.0;
00798 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00799   #pragma omp parallel for schedule(dynamic,8)
00800 #endif
00801       for (i=0; i <= (long) MaxMap; i++)
00802       {
00803         x_map[i].x=0.212600f*(MagickRealType) i;
00804         y_map[i].x=0.715200f*(MagickRealType) i;
00805         z_map[i].x=0.072200f*(MagickRealType) i;
00806         x_map[i].y=(-0.114572f)*(MagickRealType) i;
00807         y_map[i].y=(-0.385428f)*(MagickRealType) i;
00808         z_map[i].y=0.500000f*(MagickRealType) i;
00809         x_map[i].z=0.500000f*(MagickRealType) i;
00810         y_map[i].z=(-0.454153f)*(MagickRealType) i;
00811         z_map[i].z=(-0.045847f)*(MagickRealType) i;
00812       }
00813       break;
00814     }
00815     case sRGBColorspace:
00816     {
00817       /*
00818         Linear RGB to nonlinear sRGB (http://www.w3.org/Graphics/Color/sRGB):
00819 
00820           R = 1.0*R+0.0*G+0.0*B
00821           G = 0.0*R+0.1*G+0.0*B
00822           B = 0.0*R+0.0*G+1.0*B
00823       */
00824 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00825   #pragma omp parallel for schedule(dynamic,8)
00826 #endif
00827       for (i=0; i <= (long) MaxMap; i++)
00828       {
00829         MagickRealType
00830           v;
00831 
00832         v=(MagickRealType) i/(MagickRealType) MaxMap;
00833         if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.03928f)
00834           v/=12.92f;
00835         else
00836           v=(MagickRealType) MaxMap*pow((((double) i/MaxMap)+0.055)/1.055,2.4);
00837         x_map[i].x=1.0f*v;
00838         y_map[i].x=0.0f*v;
00839         z_map[i].x=0.0f*v;
00840         x_map[i].y=0.0f*v;
00841         y_map[i].y=1.0f*v;
00842         z_map[i].y=0.0f*v;
00843         x_map[i].z=0.0f*v;
00844         y_map[i].z=0.0f*v;
00845         z_map[i].z=1.0f*v;
00846       }
00847       break;
00848     }
00849     case XYZColorspace:
00850     {
00851       /*
00852         Initialize CIE XYZ tables (ITU-R 709 RGB):
00853 
00854           X = 0.4124240*R+0.3575790*G+0.1804640*B
00855           Y = 0.2126560*R+0.7151580*G+0.0721856*B
00856           Z = 0.0193324*R+0.1191930*G+0.9504440*B
00857       */
00858 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00859   #pragma omp parallel for schedule(dynamic,8)
00860 #endif
00861       for (i=0; i <= (long) MaxMap; i++)
00862       {
00863         x_map[i].x=0.4124240f*(MagickRealType) i;
00864         y_map[i].x=0.3575790f*(MagickRealType) i;
00865         z_map[i].x=0.1804640f*(MagickRealType) i;
00866         x_map[i].y=0.2126560f*(MagickRealType) i;
00867         y_map[i].y=0.7151580f*(MagickRealType) i;
00868         z_map[i].y=0.0721856f*(MagickRealType) i;
00869         x_map[i].z=0.0193324f*(MagickRealType) i;
00870         y_map[i].z=0.1191930f*(MagickRealType) i;
00871         z_map[i].z=0.9504440f*(MagickRealType) i;
00872       }
00873       break;
00874     }
00875     case YCCColorspace:
00876     {
00877       /*
00878         Initialize YCC tables:
00879 
00880           Y =  0.29900*R+0.58700*G+0.11400*B
00881           C1= -0.29900*R-0.58700*G+0.88600*B
00882           C2=  0.70100*R-0.58700*G-0.11400*B
00883 
00884         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
00885       */
00886       primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
00887       primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
00888       for (i=0; i <= (long) (0.018*MaxMap); i++)
00889       {
00890         x_map[i].x=0.003962014134275617f*(MagickRealType) i;
00891         y_map[i].x=0.007778268551236748f*(MagickRealType) i;
00892         z_map[i].x=0.001510600706713781f*(MagickRealType) i;
00893         x_map[i].y=(-0.002426619775463276f)*(MagickRealType) i;
00894         y_map[i].y=(-0.004763965913702149f)*(MagickRealType) i;
00895         z_map[i].y=0.007190585689165425f*(MagickRealType) i;
00896         x_map[i].z=0.006927257754597858f*(MagickRealType) i;
00897         y_map[i].z=(-0.005800713697502058f)*(MagickRealType) i;
00898         z_map[i].z=(-0.0011265440570958f)*(MagickRealType) i;
00899       }
00900       for ( ; i <= (long) MaxMap; i++)
00901       {
00902         x_map[i].x=0.2201118963486454*(1.099f*(MagickRealType) i-0.099f);
00903         y_map[i].x=0.4321260306242638*(1.099f*(MagickRealType) i-0.099f);
00904         z_map[i].x=0.08392226148409894*(1.099f*(MagickRealType) i-0.099f);
00905         x_map[i].y=(-0.1348122097479598)*(1.099f*(MagickRealType) i-0.099f);
00906         y_map[i].y=(-0.2646647729834528)*(1.099f*(MagickRealType) i-0.099f);
00907         z_map[i].y=0.3994769827314126*(1.099f*(MagickRealType) i-0.099f);
00908         x_map[i].z=0.3848476530332144*(1.099f*(MagickRealType) i-0.099f);
00909         y_map[i].z=(-0.3222618720834477)*(1.099f*(MagickRealType) i-0.099f);
00910         z_map[i].z=(-0.06258578094976668)*(1.099f*(MagickRealType) i-0.099f);
00911       }
00912       break;
00913     }
00914     case YIQColorspace:
00915     {
00916       /*
00917         Initialize YIQ tables:
00918 
00919           Y = 0.29900*R+0.58700*G+0.11400*B
00920           I = 0.59600*R-0.27400*G-0.32200*B
00921           Q = 0.21100*R-0.52300*G+0.31200*B
00922 
00923         I and Q, normally -0.5 through 0.5, are normalized to the range 0
00924         through QuantumRange.
00925       */
00926       primary_info.y=(double) (MaxMap+1.0)/2.0;
00927       primary_info.z=(double) (MaxMap+1.0)/2.0;
00928 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00929   #pragma omp parallel for schedule(dynamic,8)
00930 #endif
00931       for (i=0; i <= (long) MaxMap; i++)
00932       {
00933         x_map[i].x=0.29900f*(MagickRealType) i;
00934         y_map[i].x=0.58700f*(MagickRealType) i;
00935         z_map[i].x=0.11400f*(MagickRealType) i;
00936         x_map[i].y=0.59600f*(MagickRealType) i;
00937         y_map[i].y=(-0.27400f)*(MagickRealType) i;
00938         z_map[i].y=(-0.32200f)*(MagickRealType) i;
00939         x_map[i].z=0.21100f*(MagickRealType) i;
00940         y_map[i].z=(-0.52300f)*(MagickRealType) i;
00941         z_map[i].z=0.31200f*(MagickRealType) i;
00942       }
00943       break;
00944     }
00945     case YPbPrColorspace:
00946     {
00947       /*
00948         Initialize YPbPr tables (ITU-R BT.601):
00949 
00950           Y =  0.299000*R+0.587000*G+0.114000*B
00951           Pb= -0.168736*R-0.331264*G+0.500000*B
00952           Pr=  0.500000*R-0.418688*G-0.081312*B
00953 
00954         Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0
00955         through QuantumRange.
00956       */
00957       primary_info.y=(double) (MaxMap+1.0)/2.0;
00958       primary_info.z=(double) (MaxMap+1.0)/2.0;
00959 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00960   #pragma omp parallel for schedule(dynamic,8)
00961 #endif
00962       for (i=0; i <= (long) MaxMap; i++)
00963       {
00964         x_map[i].x=0.299000f*(MagickRealType) i;
00965         y_map[i].x=0.587000f*(MagickRealType) i;
00966         z_map[i].x=0.114000f*(MagickRealType) i;
00967         x_map[i].y=(-0.168736f)*(MagickRealType) i;
00968         y_map[i].y=(-0.331264f)*(MagickRealType) i;
00969         z_map[i].y=0.500000f*(MagickRealType) i;
00970         x_map[i].z=0.500000f*(MagickRealType) i;
00971         y_map[i].z=(-0.418688f)*(MagickRealType) i;
00972         z_map[i].z=(-0.081312f)*(MagickRealType) i;
00973       }
00974       break;
00975     }
00976     case YUVColorspace:
00977     default:
00978     {
00979       /*
00980         Initialize YUV tables:
00981 
00982           Y =  0.29900*R+0.58700*G+0.11400*B
00983           U = -0.14740*R-0.28950*G+0.43690*B
00984           V =  0.61500*R-0.51500*G-0.10000*B
00985 
00986         U and V, normally -0.5 through 0.5, are normalized to the range 0
00987         through QuantumRange.  Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
00988       */
00989       primary_info.y=(double) (MaxMap+1.0)/2.0;
00990       primary_info.z=(double) (MaxMap+1.0)/2.0;
00991 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00992   #pragma omp parallel for schedule(dynamic,8)
00993 #endif
00994       for (i=0; i <= (long)