]> granicus.if.org Git - imagemagick/blob - MagickCore/colorspace.c
(no commit message)
[imagemagick] / MagickCore / colorspace.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %     CCCC   OOO   L       OOO   RRRR   SSSSS  PPPP    AAA    CCCC  EEEEE     %
7 %    C      O   O  L      O   O  R   R  SS     P   P  A   A  C      E         %
8 %    C      O   O  L      O   O  RRRR    SSS   PPPP   AAAAA  C      EEE       %
9 %    C      O   O  L      O   O  R R       SS  P      A   A  C      E         %
10 %     CCCC   OOO   LLLLL   OOO   R  R   SSSSS  P      A   A   CCCC  EEEEE     %
11 %                                                                             %
12 %                                                                             %
13 %                     MagickCore Image Colorspace Methods                     %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/property.h"
44 #include "MagickCore/cache.h"
45 #include "MagickCore/cache-private.h"
46 #include "MagickCore/cache-view.h"
47 #include "MagickCore/color.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/colorspace-private.h"
51 #include "MagickCore/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/image.h"
54 #include "MagickCore/image-private.h"
55 #include "MagickCore/gem.h"
56 #include "MagickCore/memory_.h"
57 #include "MagickCore/monitor.h"
58 #include "MagickCore/monitor-private.h"
59 #include "MagickCore/pixel-accessor.h"
60 #include "MagickCore/quantize.h"
61 #include "MagickCore/quantum.h"
62 #include "MagickCore/quantum-private.h"
63 #include "MagickCore/string_.h"
64 #include "MagickCore/string-private.h"
65 #include "MagickCore/utility.h"
66 \f
67 /*
68   Typedef declarations.
69 */
70 typedef struct _TransformPacket
71 {
72   MagickRealType
73     x,
74     y,
75     z;
76 } TransformPacket;
77 \f
78 /*
79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80 %                                                                             %
81 %                                                                             %
82 %                                                                             %
83 +     R G B T r a n s f o r m I m a g e                                       %
84 %                                                                             %
85 %                                                                             %
86 %                                                                             %
87 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88 %
89 %  RGBTransformImage() converts the reference image from RGB to an alternate
90 %  colorspace.  The transformation matrices are not the standard ones: the
91 %  weights are rescaled to normalized the range of the transformed values to
92 %  be [0..QuantumRange].
93 %
94 %  The format of the RGBTransformImage method is:
95 %
96 %      MagickBooleanType RGBTransformImage(Image *image,
97 %        const ColorspaceType colorspace)
98 %
99 %  A description of each parameter follows:
100 %
101 %    o image: the image.
102 %
103 %    o colorspace: the colorspace to transform the image to.
104 %
105 */
106
107 static inline void ConvertRGBToXYZ(const Quantum red,const Quantum green,
108   const Quantum blue,double *X,double *Y,double *Z)
109 {
110   double
111     b,
112     g,
113     r;
114
115   assert(X != (double *) NULL);
116   assert(Y != (double *) NULL);
117   assert(Z != (double *) NULL);
118   r=QuantumScale*red;
119   if (r > 0.04045)
120     r=pow((r+0.055)/1.055,2.4);
121   else
122     r/=12.92;
123   g=QuantumScale*green;
124   if (g > 0.04045)
125     g=pow((g+0.055)/1.055,2.4);
126   else
127     g/=12.92;
128   b=QuantumScale*blue;
129   if (b > 0.04045)
130     b=pow((b+0.055)/1.055,2.4);
131   else
132     b/=12.92;
133   *X=0.4124240*r+0.3575790*g+0.1804640*b;
134   *Y=0.2126560*r+0.7151580*g+0.0721856*b;
135   *Z=0.0193324*r+0.1191930*g+0.9504440*b;
136 }
137
138 static double LabF1(double alpha)
139 {
140
141   if (alpha <= ((24.0/116.0)*(24.0/116.0)*(24.0/116.0)))
142     return((841.0/108.0)*alpha+(16.0/116.0));
143   return(pow(alpha,1.0/3.0));
144 }
145
146 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
147   double *L,double *a,double *b)
148 {
149 #define D50X  (0.9642)
150 #define D50Y  (1.0)
151 #define D50Z  (0.8249)
152
153   double
154     fx,
155     fy,
156     fz;
157
158   assert(L != (double *) NULL);
159   assert(a != (double *) NULL);
160   assert(b != (double *) NULL);
161   *L=0.0;
162   *a=0.5;
163   *b=0.5;
164   if ((X == 0.0) && (Y == 0.0) && (Z == 0.0))
165     return;
166   fx=LabF1(X/D50X);
167   fy=LabF1(Y/D50Y);
168   fz=LabF1(Z/D50Z);
169   *L=(116.0*fy-16.0)/100.0;
170   *a=(500.0*(fx-fy))/255.0;
171   if (*a < 0.0)
172     *a+=1.0;
173   *b=(200.0*(fy-fz))/255.0;
174   if (*b < 0.0)
175     *b+=1.0;
176 }
177
178 MagickExport MagickBooleanType RGBTransformImage(Image *image,
179   const ColorspaceType colorspace)
180 {
181 #define RGBTransformImageTag  "RGBTransform/Image"
182
183   CacheView
184     *image_view;
185
186   ExceptionInfo
187     *exception;
188
189   MagickBooleanType
190     status,
191     sync;
192
193   MagickOffsetType
194     progress;
195
196   PrimaryInfo
197     primary_info;
198
199   register ssize_t
200     i;
201
202   ssize_t
203     y;
204
205   TransformPacket
206     *x_map,
207     *y_map,
208     *z_map;
209
210   assert(image != (Image *) NULL);
211   assert(image->signature == MagickSignature);
212   if (image->debug != MagickFalse)
213     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
214   assert(colorspace != RGBColorspace);
215   assert(colorspace != TransparentColorspace);
216   assert(colorspace != UndefinedColorspace);
217   switch (image->colorspace)
218   {
219     case GRAYColorspace:
220     case Rec601LumaColorspace:
221     case Rec709LumaColorspace:
222     case RGBColorspace:
223     case TransparentColorspace:
224       break;
225     default:
226     {
227       (void) TransformImageColorspace(image,image->colorspace);
228       break;
229     }
230   }
231   exception=(&image->exception);
232   if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
233     return(MagickFalse);
234   status=MagickTrue;
235   progress=0;
236   switch (colorspace)
237   {
238     case CMYColorspace:
239     {
240       /*
241         Convert RGB to CMY colorspace.
242       */
243       if (image->storage_class == PseudoClass)
244         {
245           if (SyncImage(image) == MagickFalse)
246             return(MagickFalse);
247           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
248             return(MagickFalse);
249         }
250       image_view=AcquireCacheView(image);
251 #if defined(MAGICKCORE_OPENMP_SUPPORT)
252   #pragma omp parallel for schedule(dynamic,4) shared(status)
253 #endif
254       for (y=0; y < (ssize_t) image->rows; y++)
255       {
256         register ssize_t
257           x;
258
259         register Quantum
260           *restrict q;
261
262         if (status == MagickFalse)
263           continue;
264         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
265           exception);
266         if (q == (const Quantum *) NULL)
267           {
268             status=MagickFalse;
269             continue;
270           }
271         for (x=0; x < (ssize_t) image->columns; x++)
272         {
273           SetPixelRed(image,ClampToQuantum((MagickRealType) (QuantumRange-
274             GetPixelRed(image,q))),q);
275           SetPixelGreen(image,ClampToQuantum((MagickRealType) (QuantumRange-
276             GetPixelGreen(image,q))),q);
277           SetPixelBlue(image,ClampToQuantum((MagickRealType) (QuantumRange-
278             GetPixelBlue(image,q))),q);
279           q+=GetPixelChannels(image);
280         }
281         sync=SyncCacheViewAuthenticPixels(image_view,exception);
282         if (sync == MagickFalse)
283           status=MagickFalse;
284       }
285       image_view=DestroyCacheView(image_view);
286       image->type=image->matte == MagickFalse ? ColorSeparationType :
287         ColorSeparationMatteType;
288       return(status);
289     }
290     case CMYKColorspace:
291     {
292       PixelInfo
293         zero;
294
295       /*
296         Convert RGB to CMYK colorspace.
297       */
298       if (image->storage_class == PseudoClass)
299         {
300           if (SyncImage(image) == MagickFalse)
301             return(MagickFalse);
302           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
303             return(MagickFalse);
304         }
305       GetPixelInfo(image,&zero);
306       image_view=AcquireCacheView(image);
307 #if defined(MAGICKCORE_OPENMP_SUPPORT)
308   #pragma omp parallel for schedule(dynamic,4) shared(status)
309 #endif
310       for (y=0; y < (ssize_t) image->rows; y++)
311       {
312         PixelInfo
313           pixel;
314
315         register ssize_t
316           x;
317
318         register Quantum
319           *restrict q;
320
321         if (status == MagickFalse)
322           continue;
323         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
324           exception);
325         if (q == (const Quantum *) NULL)
326           {
327             status=MagickFalse;
328             continue;
329           }
330         pixel=zero;
331         for (x=0; x < (ssize_t) image->columns; x++)
332         {
333           SetPixelInfo(image,q,&pixel);
334           ConvertRGBToCMYK(&pixel);
335           SetPixelPixelInfo(image,&pixel,q);
336           q+=GetPixelChannels(image);
337         }
338         sync=SyncCacheViewAuthenticPixels(image_view,exception);
339         if (sync == MagickFalse)
340           status=MagickFalse;
341       }
342       image_view=DestroyCacheView(image_view);
343       image->type=image->matte == MagickFalse ? ColorSeparationType :
344         ColorSeparationMatteType;
345       return(status);
346     }
347     case HSBColorspace:
348     {
349       /*
350         Transform image from RGB to HSB.
351       */
352       if (image->storage_class == PseudoClass)
353         {
354           if (SyncImage(image) == MagickFalse)
355             return(MagickFalse);
356           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
357             return(MagickFalse);
358         }
359       image_view=AcquireCacheView(image);
360 #if defined(MAGICKCORE_OPENMP_SUPPORT)
361   #pragma omp parallel for schedule(dynamic,4) shared(status)
362 #endif
363       for (y=0; y < (ssize_t) image->rows; y++)
364       {
365         double
366           brightness,
367           hue,
368           saturation;
369
370         register ssize_t
371           x;
372
373         register Quantum
374           *restrict q;
375
376         if (status == MagickFalse)
377           continue;
378         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
379           exception);
380         if (q == (const Quantum *) NULL)
381           {
382             status=MagickFalse;
383             continue;
384           }
385         hue=0.0;
386         saturation=0.0;
387         brightness=0.0;
388         for (x=0; x < (ssize_t) image->columns; x++)
389         {
390           ConvertRGBToHSB(GetPixelRed(image,q),GetPixelGreen(image,q),
391             GetPixelBlue(image,q),&hue,&saturation,&brightness);
392           SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
393             hue),q);
394           SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
395             saturation),q);
396           SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
397             brightness),q);
398           q+=GetPixelChannels(image);
399         }
400         sync=SyncCacheViewAuthenticPixels(image_view,exception);
401         if (sync == MagickFalse)
402           status=MagickFalse;
403       }
404       image_view=DestroyCacheView(image_view);
405       return(status);
406     }
407     case HSLColorspace:
408     {
409       /*
410         Transform image from RGB to HSL.
411       */
412       if (image->storage_class == PseudoClass)
413         {
414           if (SyncImage(image) == MagickFalse)
415             return(MagickFalse);
416           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
417             return(MagickFalse);
418         }
419       image_view=AcquireCacheView(image);
420 #if defined(MAGICKCORE_OPENMP_SUPPORT)
421   #pragma omp parallel for schedule(dynamic,4) shared(status)
422 #endif
423       for (y=0; y < (ssize_t) image->rows; y++)
424       {
425         double
426           hue,
427           lightness,
428           saturation;
429
430         register ssize_t
431           x;
432
433         register Quantum
434           *restrict q;
435
436         if (status == MagickFalse)
437           continue;
438         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
439           exception);
440         if (q == (const Quantum *) NULL)
441           {
442             status=MagickFalse;
443             continue;
444           }
445         hue=0.0;
446         saturation=0.0;
447         lightness=0.0;
448         for (x=0; x < (ssize_t) image->columns; x++)
449         {
450           ConvertRGBToHSL(GetPixelRed(image,q),GetPixelGreen(image,q),
451             GetPixelBlue(image,q),&hue,&saturation,&lightness);
452           SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
453             hue),q);
454           SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
455             saturation),q);
456           SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
457             lightness),q);
458           q+=GetPixelChannels(image);
459         }
460         sync=SyncCacheViewAuthenticPixels(image_view,exception);
461         if (sync == MagickFalse)
462           status=MagickFalse;
463       }
464       image_view=DestroyCacheView(image_view);
465       return(status);
466     }
467     case HWBColorspace:
468     {
469       /*
470         Transform image from RGB to HWB.
471       */
472       if (image->storage_class == PseudoClass)
473         {
474           if (SyncImage(image) == MagickFalse)
475             return(MagickFalse);
476           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
477             return(MagickFalse);
478         }
479       image_view=AcquireCacheView(image);
480 #if defined(MAGICKCORE_OPENMP_SUPPORT)
481   #pragma omp parallel for schedule(dynamic,4) shared(status)
482 #endif
483       for (y=0; y < (ssize_t) image->rows; y++)
484       {
485         double
486           blackness,
487           hue,
488           whiteness;
489
490         register ssize_t
491           x;
492
493         register Quantum
494           *restrict q;
495
496         if (status == MagickFalse)
497           continue;
498         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
499           exception);
500         if (q == (const Quantum *) NULL)
501           {
502             status=MagickFalse;
503             continue;
504           }
505         hue=0.0;
506         whiteness=0.0;
507         blackness=0.0;
508         for (x=0; x < (ssize_t) image->columns; x++)
509         {
510           ConvertRGBToHWB(GetPixelRed(image,q),GetPixelGreen(image,q),
511             GetPixelBlue(image,q),&hue,&whiteness,&blackness);
512           SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
513             hue),q);
514           SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
515             whiteness),q);
516           SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
517             blackness),q);
518           q+=GetPixelChannels(image);
519         }
520         sync=SyncCacheViewAuthenticPixels(image_view,exception);
521         if (sync == MagickFalse)
522           status=MagickFalse;
523       }
524       image_view=DestroyCacheView(image_view);
525       return(status);
526     }
527     case LabColorspace:
528     {
529       /*
530         Transform image from RGB to Lab.
531       */
532       if (image->storage_class == PseudoClass)
533         {
534           if (SyncImage(image) == MagickFalse)
535             return(MagickFalse);
536           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
537             return(MagickFalse);
538         }
539       image_view=AcquireCacheView(image);
540 #if defined(MAGICKCORE_OPENMP_SUPPORT)
541   #pragma omp parallel for schedule(dynamic,4) shared(status)
542 #endif
543       for (y=0; y < (ssize_t) image->rows; y++)
544       {
545         double
546           a,
547           b,
548           L,
549           X,
550           Y,
551           Z;
552
553         register ssize_t
554           x;
555
556         register Quantum
557           *restrict q;
558
559         if (status == MagickFalse)
560           continue;
561         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
562           exception);
563         if (q == (const Quantum *) NULL)
564           {
565             status=MagickFalse;
566             continue;
567           }
568         L=0.0;
569         a=0.0;
570         b=0.0;
571         X=0.0;
572         Y=0.0;
573         Z=0.0;
574         for (x=0; x < (ssize_t) image->columns; x++)
575         {
576           ConvertRGBToXYZ(GetPixelRed(image,q),GetPixelGreen(image,q),
577             GetPixelBlue(image,q),&X,&Y,&Z);
578           ConvertXYZToLab(X,Y,Z,&L,&a,&b);
579           SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
580             L),q);
581           SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
582             a),q);
583           SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
584             b),q);
585           q+=GetPixelChannels(image);
586         }
587         sync=SyncCacheViewAuthenticPixels(image_view,exception);
588         if (sync == MagickFalse)
589           status=MagickFalse;
590       }
591       image_view=DestroyCacheView(image_view);
592       return(status);
593     }
594     case LogColorspace:
595     {
596 #define DisplayGamma  (1.0/1.7)
597 #define FilmGamma  0.6
598 #define ReferenceBlack  95.0
599 #define ReferenceWhite  685.0
600
601       const char
602         *value;
603
604       double
605         black,
606         density,
607         film_gamma,
608         gamma,
609         reference_black,
610         reference_white;
611
612       Quantum
613         *logmap;
614
615       /*
616         Transform RGB to Log colorspace.
617       */
618       density=DisplayGamma;
619       gamma=DisplayGamma;
620       value=GetImageProperty(image,"gamma");
621       if (value != (const char *) NULL)
622         gamma=1.0/InterpretLocaleValue(value,(char **) NULL) != 0.0 ?
623           InterpretLocaleValue(value,(char **) NULL) : 1.0;
624       film_gamma=FilmGamma;
625       value=GetImageProperty(image,"film-gamma");
626       if (value != (const char *) NULL)
627         film_gamma=InterpretLocaleValue(value,(char **) NULL);
628       reference_black=ReferenceBlack;
629       value=GetImageProperty(image,"reference-black");
630       if (value != (const char *) NULL)
631         reference_black=InterpretLocaleValue(value,(char **) NULL);
632       reference_white=ReferenceWhite;
633       value=GetImageProperty(image,"reference-white");
634       if (value != (const char *) NULL)
635         reference_white=InterpretLocaleValue(value,(char **) NULL);
636       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
637         sizeof(*logmap));
638       if (logmap == (Quantum *) NULL)
639         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
640           image->filename);
641       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
642         0.002/film_gamma);
643 #if defined(MAGICKCORE_OPENMP_SUPPORT)
644   #pragma omp parallel for schedule(dynamic,4)
645 #endif
646       for (i=0; i <= (ssize_t) MaxMap; i++)
647         logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+
648           log10(black+((MagickRealType) i/MaxMap)*(1.0-black))/((gamma/density)*
649           0.002/film_gamma))/1024.0));
650       image_view=AcquireCacheView(image);
651 #if defined(MAGICKCORE_OPENMP_SUPPORT)
652   #pragma omp parallel for schedule(dynamic,4) shared(status)
653 #endif
654       for (y=0; y < (ssize_t) image->rows; y++)
655       {
656         register ssize_t
657           x;
658
659         register Quantum
660           *restrict q;
661
662         if (status == MagickFalse)
663           continue;
664         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
665           exception);
666         if (q == (const Quantum *) NULL)
667           {
668             status=MagickFalse;
669             continue;
670           }
671         for (x=(ssize_t) image->columns; x != 0; x--)
672         {
673           SetPixelRed(image,logmap[ScaleQuantumToMap(
674             GetPixelRed(image,q))],q);
675           SetPixelGreen(image,logmap[ScaleQuantumToMap(
676             GetPixelGreen(image,q))],q);
677           SetPixelBlue(image,logmap[ScaleQuantumToMap(
678             GetPixelBlue(image,q))],q);
679           q+=GetPixelChannels(image);
680         }
681         sync=SyncCacheViewAuthenticPixels(image_view,exception);
682         if (sync == MagickFalse)
683           status=MagickFalse;
684       }
685       image_view=DestroyCacheView(image_view);
686       logmap=(Quantum *) RelinquishMagickMemory(logmap);
687       return(status);
688     }
689     default:
690       break;
691   }
692   /*
693     Allocate the tables.
694   */
695   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
696     sizeof(*x_map));
697   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
698     sizeof(*y_map));
699   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
700     sizeof(*z_map));
701   if ((x_map == (TransformPacket *) NULL) ||
702       (y_map == (TransformPacket *) NULL) ||
703       (z_map == (TransformPacket *) NULL))
704     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
705       image->filename);
706   (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
707   switch (colorspace)
708   {
709     case OHTAColorspace:
710     {
711       /*
712         Initialize OHTA tables:
713
714           I1 = 0.33333*R+0.33334*G+0.33333*B
715           I2 = 0.50000*R+0.00000*G-0.50000*B
716           I3 =-0.25000*R+0.50000*G-0.25000*B
717
718         I and Q, normally -0.5 through 0.5, are normalized to the range 0
719         through QuantumRange.
720       */
721       primary_info.y=(double) (MaxMap+1.0)/2.0;
722       primary_info.z=(double) (MaxMap+1.0)/2.0;
723 #if defined(MAGICKCORE_OPENMP_SUPPORT)
724   #pragma omp parallel for schedule(dynamic,4)
725 #endif
726       for (i=0; i <= (ssize_t) MaxMap; i++)
727       {
728         x_map[i].x=0.33333f*(MagickRealType) i;
729         y_map[i].x=0.33334f*(MagickRealType) i;
730         z_map[i].x=0.33333f*(MagickRealType) i;
731         x_map[i].y=0.50000f*(MagickRealType) i;
732         y_map[i].y=0.00000f*(MagickRealType) i;
733         z_map[i].y=(-0.50000f)*(MagickRealType) i;
734         x_map[i].z=(-0.25000f)*(MagickRealType) i;
735         y_map[i].z=0.50000f*(MagickRealType) i;
736         z_map[i].z=(-0.25000f)*(MagickRealType) i;
737       }
738       break;
739     }
740     case Rec601LumaColorspace:
741     case GRAYColorspace:
742     {
743       /*
744         Initialize Rec601 luma tables:
745
746           G = 0.29900*R+0.58700*G+0.11400*B
747       */
748 #if defined(MAGICKCORE_OPENMP_SUPPORT)
749   #pragma omp parallel for schedule(dynamic,4)
750 #endif
751       for (i=0; i <= (ssize_t) MaxMap; i++)
752       {
753         x_map[i].x=0.29900f*(MagickRealType) i;
754         y_map[i].x=0.58700f*(MagickRealType) i;
755         z_map[i].x=0.11400f*(MagickRealType) i;
756         x_map[i].y=0.29900f*(MagickRealType) i;
757         y_map[i].y=0.58700f*(MagickRealType) i;
758         z_map[i].y=0.11400f*(MagickRealType) i;
759         x_map[i].z=0.29900f*(MagickRealType) i;
760         y_map[i].z=0.58700f*(MagickRealType) i;
761         z_map[i].z=0.11400f*(MagickRealType) i;
762       }
763       image->type=GrayscaleType;
764       break;
765     }
766     case Rec601YCbCrColorspace:
767     case YCbCrColorspace:
768     {
769       /*
770         Initialize YCbCr tables (ITU-R BT.601):
771
772           Y =  0.299000*R+0.587000*G+0.114000*B
773           Cb= -0.168736*R-0.331264*G+0.500000*B
774           Cr=  0.500000*R-0.418688*G-0.081312*B
775
776         Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
777         through QuantumRange.
778       */
779       primary_info.y=(double) (MaxMap+1.0)/2.0;
780       primary_info.z=(double) (MaxMap+1.0)/2.0;
781 #if defined(MAGICKCORE_OPENMP_SUPPORT)
782   #pragma omp parallel for schedule(dynamic,4)
783 #endif
784       for (i=0; i <= (ssize_t) MaxMap; i++)
785       {
786         x_map[i].x=0.299000f*(MagickRealType) i;
787         y_map[i].x=0.587000f*(MagickRealType) i;
788         z_map[i].x=0.114000f*(MagickRealType) i;
789         x_map[i].y=(-0.168730f)*(MagickRealType) i;
790         y_map[i].y=(-0.331264f)*(MagickRealType) i;
791         z_map[i].y=0.500000f*(MagickRealType) i;
792         x_map[i].z=0.500000f*(MagickRealType) i;
793         y_map[i].z=(-0.418688f)*(MagickRealType) i;
794         z_map[i].z=(-0.081312f)*(MagickRealType) i;
795       }
796       break;
797     }
798     case Rec709LumaColorspace:
799     {
800       /*
801         Initialize Rec709 luma tables:
802
803           G = 0.21260*R+0.71520*G+0.07220*B
804       */
805 #if defined(MAGICKCORE_OPENMP_SUPPORT)
806   #pragma omp parallel for schedule(dynamic,4)
807 #endif
808       for (i=0; i <= (ssize_t) MaxMap; i++)
809       {
810         x_map[i].x=0.21260f*(MagickRealType) i;
811         y_map[i].x=0.71520f*(MagickRealType) i;
812         z_map[i].x=0.07220f*(MagickRealType) i;
813         x_map[i].y=0.21260f*(MagickRealType) i;
814         y_map[i].y=0.71520f*(MagickRealType) i;
815         z_map[i].y=0.07220f*(MagickRealType) i;
816         x_map[i].z=0.21260f*(MagickRealType) i;
817         y_map[i].z=0.71520f*(MagickRealType) i;
818         z_map[i].z=0.07220f*(MagickRealType) i;
819       }
820       break;
821     }
822     case Rec709YCbCrColorspace:
823     {
824       /*
825         Initialize YCbCr tables (ITU-R BT.709):
826
827           Y =  0.212600*R+0.715200*G+0.072200*B
828           Cb= -0.114572*R-0.385428*G+0.500000*B
829           Cr=  0.500000*R-0.454153*G-0.045847*B
830
831         Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
832         through QuantumRange.
833       */
834       primary_info.y=(double) (MaxMap+1.0)/2.0;
835       primary_info.z=(double) (MaxMap+1.0)/2.0;
836 #if defined(MAGICKCORE_OPENMP_SUPPORT)
837   #pragma omp parallel for schedule(dynamic,4)
838 #endif
839       for (i=0; i <= (ssize_t) MaxMap; i++)
840       {
841         x_map[i].x=0.212600f*(MagickRealType) i;
842         y_map[i].x=0.715200f*(MagickRealType) i;
843         z_map[i].x=0.072200f*(MagickRealType) i;
844         x_map[i].y=(-0.114572f)*(MagickRealType) i;
845         y_map[i].y=(-0.385428f)*(MagickRealType) i;
846         z_map[i].y=0.500000f*(MagickRealType) i;
847         x_map[i].z=0.500000f*(MagickRealType) i;
848         y_map[i].z=(-0.454153f)*(MagickRealType) i;
849         z_map[i].z=(-0.045847f)*(MagickRealType) i;
850       }
851       break;
852     }
853     case sRGBColorspace:
854     {
855       /*
856         Nonlinear sRGB to linear RGB (http://www.w3.org/Graphics/Color/sRGB):
857
858           R = 1.0*R+0.0*G+0.0*B
859           G = 0.0*R+0.1*G+0.0*B
860           B = 0.0*R+0.0*G+1.0*B
861       */
862 #if defined(MAGICKCORE_OPENMP_SUPPORT)
863   #pragma omp parallel for schedule(dynamic,4)
864 #endif
865       for (i=0; i <= (ssize_t) MaxMap; i++)
866       {
867         MagickRealType
868           v;
869
870         v=(MagickRealType) i/(MagickRealType) MaxMap;
871         if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.04045f)
872           v/=12.92f;
873         else
874           v=(MagickRealType) pow((((double) i/MaxMap)+0.055)/1.055,2.4);
875         x_map[i].x=1.0f*MaxMap*v;
876         y_map[i].x=0.0f*MaxMap*v;
877         z_map[i].x=0.0f*MaxMap*v;
878         x_map[i].y=0.0f*MaxMap*v;
879         y_map[i].y=1.0f*MaxMap*v;
880         z_map[i].y=0.0f*MaxMap*v;
881         x_map[i].z=0.0f*MaxMap*v;
882         y_map[i].z=0.0f*MaxMap*v;
883         z_map[i].z=1.0f*MaxMap*v;
884       }
885       break;
886     }
887     case XYZColorspace:
888     {
889       /*
890         Initialize CIE XYZ tables (ITU-R 709 RGB):
891
892           X = 0.4124564*R+0.3575761*G+0.1804375*B
893           Y = 0.2126729*R+0.7151522*G+0.0721750*B
894           Z = 0.0193339*R+0.1191920*G+0.9503041*B
895       */
896 #if defined(MAGICKCORE_OPENMP_SUPPORT)
897   #pragma omp parallel for schedule(dynamic,4)
898 #endif
899       for (i=0; i <= (ssize_t) MaxMap; i++)
900       {
901         x_map[i].x=0.4124564f*(MagickRealType) i;
902         y_map[i].x=0.3575761f*(MagickRealType) i;
903         z_map[i].x=0.1804375f*(MagickRealType) i;
904         x_map[i].y=0.2126729f*(MagickRealType) i;
905         y_map[i].y=0.7151522f*(MagickRealType) i;
906         z_map[i].y=0.0721750f*(MagickRealType) i;
907         x_map[i].z=0.0193339f*(MagickRealType) i;
908         y_map[i].z=0.1191920f*(MagickRealType) i;
909         z_map[i].z=0.9503041f*(MagickRealType) i;
910       }
911       break;
912     }
913     case YCCColorspace:
914     {
915       /*
916         Initialize YCC tables:
917
918           Y =  0.29900*R+0.58700*G+0.11400*B
919           C1= -0.29900*R-0.58700*G+0.88600*B
920           C2=  0.70100*R-0.58700*G-0.11400*B
921
922         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
923       */
924       primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
925       primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
926       for (i=0; i <= (ssize_t) (0.018*MaxMap); i++)
927       {
928         x_map[i].x=0.003962014134275617f*(MagickRealType) i;
929         y_map[i].x=0.007778268551236748f*(MagickRealType) i;
930         z_map[i].x=0.001510600706713781f*(MagickRealType) i;
931         x_map[i].y=(-0.002426619775463276f)*(MagickRealType) i;
932         y_map[i].y=(-0.004763965913702149f)*(MagickRealType) i;
933         z_map[i].y=0.007190585689165425f*(MagickRealType) i;
934         x_map[i].z=0.006927257754597858f*(MagickRealType) i;
935         y_map[i].z=(-0.005800713697502058f)*(MagickRealType) i;
936         z_map[i].z=(-0.0011265440570958f)*(MagickRealType) i;
937       }
938       for ( ; i <= (ssize_t) MaxMap; i++)
939       {
940         x_map[i].x=0.2201118963486454*(1.099f*(MagickRealType) i-0.099f);
941         y_map[i].x=0.4321260306242638*(1.099f*(MagickRealType) i-0.099f);
942         z_map[i].x=0.08392226148409894*(1.099f*(MagickRealType) i-0.099f);
943         x_map[i].y=(-0.1348122097479598)*(1.099f*(MagickRealType) i-0.099f);
944         y_map[i].y=(-0.2646647729834528)*(1.099f*(MagickRealType) i-0.099f);
945         z_map[i].y=0.3994769827314126*(1.099f*(MagickRealType) i-0.099f);
946         x_map[i].z=0.3848476530332144*(1.099f*(MagickRealType) i-0.099f);
947         y_map[i].z=(-0.3222618720834477)*(1.099f*(MagickRealType) i-0.099f);
948         z_map[i].z=(-0.06258578094976668)*(1.099f*(MagickRealType) i-0.099f);
949       }
950       break;
951     }
952     case YIQColorspace:
953     {
954       /*
955         Initialize YIQ tables:
956
957           Y = 0.29900*R+0.58700*G+0.11400*B
958           I = 0.59600*R-0.27400*G-0.32200*B
959           Q = 0.21100*R-0.52300*G+0.31200*B
960
961         I and Q, normally -0.5 through 0.5, are normalized to the range 0
962         through QuantumRange.
963       */
964       primary_info.y=(double) (MaxMap+1.0)/2.0;
965       primary_info.z=(double) (MaxMap+1.0)/2.0;
966 #if defined(MAGICKCORE_OPENMP_SUPPORT)
967   #pragma omp parallel for schedule(dynamic,4)
968 #endif
969       for (i=0; i <= (ssize_t) MaxMap; i++)
970       {
971         x_map[i].x=0.29900f*(MagickRealType) i;
972         y_map[i].x=0.58700f*(MagickRealType) i;
973         z_map[i].x=0.11400f*(MagickRealType) i;
974         x_map[i].y=0.59600f*(MagickRealType) i;
975         y_map[i].y=(-0.27400f)*(MagickRealType) i;
976         z_map[i].y=(-0.32200f)*(MagickRealType) i;
977         x_map[i].z=0.21100f*(MagickRealType) i;
978         y_map[i].z=(-0.52300f)*(MagickRealType) i;
979         z_map[i].z=0.31200f*(MagickRealType) i;
980       }
981       break;
982     }
983     case YPbPrColorspace:
984     {
985       /*
986         Initialize YPbPr tables (ITU-R BT.601):
987
988           Y =  0.299000*R+0.587000*G+0.114000*B
989           Pb= -0.168736*R-0.331264*G+0.500000*B
990           Pr=  0.500000*R-0.418688*G-0.081312*B
991
992         Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0
993         through QuantumRange.
994       */
995       primary_info.y=(double) (MaxMap+1.0)/2.0;
996       primary_info.z=(double) (MaxMap+1.0)/2.0;
997 #if defined(MAGICKCORE_OPENMP_SUPPORT)
998   #pragma omp parallel for schedule(dynamic,4)
999 #endif
1000       for (i=0; i <= (ssize_t) MaxMap; i++)
1001       {
1002         x_map[i].x=0.299000f*(MagickRealType) i;
1003         y_map[i].x=0.587000f*(MagickRealType) i;
1004         z_map[i].x=0.114000f*(MagickRealType) i;
1005         x_map[i].y=(-0.168736f)*(MagickRealType) i;
1006         y_map[i].y=(-0.331264f)*(MagickRealType) i;
1007         z_map[i].y=0.500000f*(MagickRealType) i;
1008         x_map[i].z=0.500000f*(MagickRealType) i;
1009         y_map[i].z=(-0.418688f)*(MagickRealType) i;
1010         z_map[i].z=(-0.081312f)*(MagickRealType) i;
1011       }
1012       break;
1013     }
1014     case YUVColorspace:
1015     default:
1016     {
1017       /*
1018         Initialize YUV tables:
1019
1020           Y =  0.29900*R+0.58700*G+0.11400*B
1021           U = -0.14740*R-0.28950*G+0.43690*B
1022           V =  0.61500*R-0.51500*G-0.10000*B
1023
1024         U and V, normally -0.5 through 0.5, are normalized to the range 0
1025         through QuantumRange.  Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
1026       */
1027       primary_info.y=(double) (MaxMap+1.0)/2.0;
1028       primary_info.z=(double) (MaxMap+1.0)/2.0;
1029 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1030   #pragma omp parallel for schedule(dynamic,4)
1031 #endif
1032       for (i=0; i <= (ssize_t) MaxMap; i++)
1033       {
1034         x_map[i].x=0.29900f*(MagickRealType) i;
1035         y_map[i].x=0.58700f*(MagickRealType) i;
1036         z_map[i].x=0.11400f*(MagickRealType) i;
1037         x_map[i].y=(-0.14740f)*(MagickRealType) i;
1038         y_map[i].y=(-0.28950f)*(MagickRealType) i;
1039         z_map[i].y=0.43690f*(MagickRealType) i;
1040         x_map[i].z=0.61500f*(MagickRealType) i;
1041         y_map[i].z=(-0.51500f)*(MagickRealType) i;
1042         z_map[i].z=(-0.10000f)*(MagickRealType) i;
1043       }
1044       break;
1045     }
1046   }
1047   /*
1048     Convert from RGB.
1049   */
1050   switch (image->storage_class)
1051   {
1052     case DirectClass:
1053     default:
1054     {
1055       /*
1056         Convert DirectClass image.
1057       */
1058       image_view=AcquireCacheView(image);
1059 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1060   #pragma omp parallel for schedule(dynamic,4) shared(status)
1061 #endif
1062       for (y=0; y < (ssize_t) image->rows; y++)
1063       {
1064         PixelInfo
1065           pixel;
1066
1067         register ssize_t
1068           x;
1069
1070         register Quantum
1071           *restrict q;
1072
1073         register size_t
1074           blue,
1075           green,
1076           red;
1077
1078         if (status == MagickFalse)
1079           continue;
1080         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1081           exception);
1082         if (q == (const Quantum *) NULL)
1083           {
1084             status=MagickFalse;
1085             continue;
1086           }
1087         for (x=0; x < (ssize_t) image->columns; x++)
1088         {
1089           red=ScaleQuantumToMap(GetPixelRed(image,q));
1090           green=ScaleQuantumToMap(GetPixelGreen(image,q));
1091           blue=ScaleQuantumToMap(GetPixelBlue(image,q));
1092           pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
1093             (MagickRealType) primary_info.x;
1094           pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
1095             (MagickRealType) primary_info.y;
1096           pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
1097             (MagickRealType) primary_info.z;
1098           SetPixelRed(image,ScaleMapToQuantum(pixel.red),q);
1099           SetPixelGreen(image,ScaleMapToQuantum(pixel.green),q);
1100           SetPixelBlue(image,ScaleMapToQuantum(pixel.blue),q);
1101           q+=GetPixelChannels(image);
1102         }
1103         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1104         if (sync == MagickFalse)
1105           status=MagickFalse;
1106         if (image->progress_monitor != (MagickProgressMonitor) NULL)
1107           {
1108             MagickBooleanType
1109               proceed;
1110
1111 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1112   #pragma omp critical (MagickCore_RGBTransformImage)
1113 #endif
1114             proceed=SetImageProgress(image,RGBTransformImageTag,progress++,
1115               image->rows);
1116             if (proceed == MagickFalse)
1117               status=MagickFalse;
1118           }
1119       }
1120       image_view=DestroyCacheView(image_view);
1121       break;
1122     }
1123     case PseudoClass:
1124     {
1125       register size_t
1126         blue,
1127         green,
1128         red;
1129
1130       /*
1131         Convert PseudoClass image.
1132       */
1133       image_view=AcquireCacheView(image);
1134       for (i=0; i < (ssize_t) image->colors; i++)
1135       {
1136         PixelInfo
1137           pixel;
1138
1139         red=ScaleQuantumToMap(image->colormap[i].red);
1140         green=ScaleQuantumToMap(image->colormap[i].green);
1141         blue=ScaleQuantumToMap(image->colormap[i].blue);
1142         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
1143         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
1144         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
1145         image->colormap[i].red=ScaleMapToQuantum(pixel.red);
1146         image->colormap[i].green=ScaleMapToQuantum(pixel.green);
1147         image->colormap[i].blue=ScaleMapToQuantum(pixel.blue);
1148       }
1149       image_view=DestroyCacheView(image_view);
1150       (void) SyncImage(image);
1151       break;
1152     }
1153   }
1154   /*
1155     Relinquish resources.
1156   */
1157   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1158   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1159   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1160   if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
1161     return(MagickFalse);
1162   return(status);
1163 }
1164 \f
1165 /*
1166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1167 %                                                                             %
1168 %                                                                             %
1169 %                                                                             %
1170 %   S e t I m a g e C o l o r s p a c e                                       %
1171 %                                                                             %
1172 %                                                                             %
1173 %                                                                             %
1174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1175 %
1176 %  SetImageColorspace() sets the colorspace member of the Image structure.
1177 %
1178 %  The format of the SetImageColorspace method is:
1179 %
1180 %      MagickBooleanType SetImageColorspace(Image *image,
1181 %        const ColorspaceType colorspace,ExceptiionInfo *exception)
1182 %
1183 %  A description of each parameter follows:
1184 %
1185 %    o image: the image.
1186 %
1187 %    o colorspace: the colorspace.
1188 %
1189 %   o exception: return any errors or warnings in this structure.
1190 %
1191 */
1192 MagickExport MagickBooleanType SetImageColorspace(Image *image,
1193   const ColorspaceType colorspace,ExceptionInfo *exception)
1194 {
1195   image->colorspace=colorspace;
1196   return(SyncImagePixelCache(image,exception));
1197 }
1198 \f
1199 /*
1200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1201 %                                                                             %
1202 %                                                                             %
1203 %                                                                             %
1204 %   T r a n s f o r m I m a g e C o l o r s p a c e                           %
1205 %                                                                             %
1206 %                                                                             %
1207 %                                                                             %
1208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209 %
1210 %  TransformImageColorspace() transforms an image colorspace.
1211 %
1212 %  The format of the TransformImageColorspace method is:
1213 %
1214 %      MagickBooleanType TransformImageColorspace(Image *image,
1215 %        const ColorspaceType colorspace)
1216 %
1217 %  A description of each parameter follows:
1218 %
1219 %    o image: the image.
1220 %
1221 %    o colorspace: the colorspace.
1222 %
1223 */
1224 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
1225   const ColorspaceType colorspace)
1226 {
1227   MagickBooleanType
1228     status;
1229
1230   assert(image != (Image *) NULL);
1231   assert(image->signature == MagickSignature);
1232   if (image->debug != MagickFalse)
1233     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1234   if (colorspace == UndefinedColorspace)
1235     return(SetImageColorspace(image,colorspace,&image->exception));
1236   if (image->colorspace == colorspace)
1237     return(MagickTrue);
1238   if ((colorspace == RGBColorspace) || (colorspace == TransparentColorspace))
1239     return(TransformRGBImage(image,image->colorspace));
1240   status=MagickTrue;
1241   if ((image->colorspace != RGBColorspace) &&
1242       (image->colorspace != TransparentColorspace) &&
1243       (image->colorspace != GRAYColorspace))
1244     status=TransformRGBImage(image,image->colorspace);
1245   if (RGBTransformImage(image,colorspace) == MagickFalse)
1246     status=MagickFalse;
1247   return(status);
1248 }
1249 \f
1250 /*
1251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1252 %                                                                             %
1253 %                                                                             %
1254 %                                                                             %
1255 +     T r a n s f o r m R G B I m a g e                                       %
1256 %                                                                             %
1257 %                                                                             %
1258 %                                                                             %
1259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1260 %
1261 %  TransformRGBImage() converts the reference image from an alternate
1262 %  colorspace to RGB.  The transformation matrices are not the standard ones:
1263 %  the weights are rescaled to normalize the range of the transformed values to
1264 %  be [0..QuantumRange].
1265 %
1266 %  The format of the TransformRGBImage method is:
1267 %
1268 %      MagickBooleanType TransformRGBImage(Image *image,
1269 %        const ColorspaceType colorspace)
1270 %
1271 %  A description of each parameter follows:
1272 %
1273 %    o image: the image.
1274 %
1275 %    o colorspace: the colorspace to transform the image to.
1276 %
1277 */
1278
1279 static double LabF2(double alpha)
1280 {
1281   double
1282     beta;
1283
1284   if (alpha > (24.0/116.0))
1285     return(alpha*alpha*alpha);
1286   beta=(108.0/841.0)*(alpha-(16.0/116.0));
1287   if (beta > 0.0)
1288     return(beta);
1289   return(0.0);
1290 }
1291
1292 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
1293   double *X,double *Y,double *Z)
1294 {
1295
1296   double
1297     x,
1298     y,
1299     z;
1300
1301   assert(X != (double *) NULL);
1302   assert(Y != (double *) NULL);
1303   assert(Z != (double *) NULL);
1304   *X=0.0;
1305   *Y=0.0;
1306   *Z=0.0;
1307   if (L <= 0.0)
1308     return;
1309   y=(100.0*L+16.0)/116.0;
1310   x=y+255.0*0.002*(a > 0.5 ? a-1.0 : a);
1311   z=y-255.0*0.005*(b > 0.5 ? b-1.0 : b);
1312   *X=D50X*LabF2(x);
1313   *Y=D50Y*LabF2(y);
1314   *Z=D50Z*LabF2(z);
1315 }
1316
1317 static inline ssize_t RoundToYCC(const MagickRealType value)
1318 {
1319   if (value <= 0.0)
1320     return(0);
1321   if (value >= 1388.0)
1322     return(1388);
1323   return((ssize_t) (value+0.5));
1324 }
1325
1326 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
1327   Quantum *red,Quantum *green,Quantum *blue)
1328 {
1329   double
1330     b,
1331     g,
1332     r;
1333
1334   /*
1335     Convert XYZ to RGB colorspace.
1336   */
1337   assert(red != (Quantum *) NULL);
1338   assert(green != (Quantum *) NULL);
1339   assert(blue != (Quantum *) NULL);
1340   r=3.2404542*x-1.5371385*y-0.4985314*z;
1341   g=(-0.9692660*x+1.8760108*y+0.0415560*z);
1342   b=0.0556434*x-0.2040259*y+1.0572252*z;
1343   if (r > 0.0031308)
1344     r=1.055*pow(r,1.0/2.4)-0.055;
1345   else
1346     r*=12.92;
1347   if (g > 0.0031308)
1348     g=1.055*pow(g,1.0/2.4)-0.055;
1349   else
1350     g*=12.92;
1351   if (b > 0.0031308)
1352     b=1.055*pow(b,1.0/2.4)-0.055;
1353   else
1354     b*=12.92;
1355   *red=RoundToQuantum((MagickRealType) QuantumRange*r);
1356   *green=RoundToQuantum((MagickRealType) QuantumRange*g);
1357   *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
1358 }
1359
1360 static inline void ConvertCMYKToRGB(PixelInfo *pixel)
1361 {
1362   pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red*
1363     (QuantumRange-pixel->black)+pixel->black);
1364   pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green*
1365     (QuantumRange-pixel->black)+pixel->black);
1366   pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue*
1367     (QuantumRange-pixel->black)+pixel->black);
1368 }
1369
1370 MagickExport MagickBooleanType TransformRGBImage(Image *image,
1371   const ColorspaceType colorspace)
1372 {
1373 #define D50X  (0.9642)
1374 #define D50Y  (1.0)
1375 #define D50Z  (0.8249)
1376 #define TransformRGBImageTag  "Transform/Image"
1377
1378 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1379   static const float
1380     YCCMap[1389] =
1381     {
1382       0.000000f, 0.000720f, 0.001441f, 0.002161f, 0.002882f, 0.003602f,
1383       0.004323f, 0.005043f, 0.005764f, 0.006484f, 0.007205f, 0.007925f,
1384       0.008646f, 0.009366f, 0.010086f, 0.010807f, 0.011527f, 0.012248f,
1385       0.012968f, 0.013689f, 0.014409f, 0.015130f, 0.015850f, 0.016571f,
1386       0.017291f, 0.018012f, 0.018732f, 0.019452f, 0.020173f, 0.020893f,
1387       0.021614f, 0.022334f, 0.023055f, 0.023775f, 0.024496f, 0.025216f,
1388       0.025937f, 0.026657f, 0.027378f, 0.028098f, 0.028818f, 0.029539f,
1389       0.030259f, 0.030980f, 0.031700f, 0.032421f, 0.033141f, 0.033862f,
1390       0.034582f, 0.035303f, 0.036023f, 0.036744f, 0.037464f, 0.038184f,
1391       0.038905f, 0.039625f, 0.040346f, 0.041066f, 0.041787f, 0.042507f,
1392       0.043228f, 0.043948f, 0.044669f, 0.045389f, 0.046110f, 0.046830f,
1393       0.047550f, 0.048271f, 0.048991f, 0.049712f, 0.050432f, 0.051153f,
1394       0.051873f, 0.052594f, 0.053314f, 0.054035f, 0.054755f, 0.055476f,
1395       0.056196f, 0.056916f, 0.057637f, 0.058357f, 0.059078f, 0.059798f,
1396       0.060519f, 0.061239f, 0.061960f, 0.062680f, 0.063401f, 0.064121f,
1397       0.064842f, 0.065562f, 0.066282f, 0.067003f, 0.067723f, 0.068444f,
1398       0.069164f, 0.069885f, 0.070605f, 0.071326f, 0.072046f, 0.072767f,
1399       0.073487f, 0.074207f, 0.074928f, 0.075648f, 0.076369f, 0.077089f,
1400       0.077810f, 0.078530f, 0.079251f, 0.079971f, 0.080692f, 0.081412f,
1401       0.082133f, 0.082853f, 0.083573f, 0.084294f, 0.085014f, 0.085735f,
1402       0.086455f, 0.087176f, 0.087896f, 0.088617f, 0.089337f, 0.090058f,
1403       0.090778f, 0.091499f, 0.092219f, 0.092939f, 0.093660f, 0.094380f,
1404       0.095101f, 0.095821f, 0.096542f, 0.097262f, 0.097983f, 0.098703f,
1405       0.099424f, 0.100144f, 0.100865f, 0.101585f, 0.102305f, 0.103026f,
1406       0.103746f, 0.104467f, 0.105187f, 0.105908f, 0.106628f, 0.107349f,
1407       0.108069f, 0.108790f, 0.109510f, 0.110231f, 0.110951f, 0.111671f,
1408       0.112392f, 0.113112f, 0.113833f, 0.114553f, 0.115274f, 0.115994f,
1409       0.116715f, 0.117435f, 0.118156f, 0.118876f, 0.119597f, 0.120317f,
1410       0.121037f, 0.121758f, 0.122478f, 0.123199f, 0.123919f, 0.124640f,
1411       0.125360f, 0.126081f, 0.126801f, 0.127522f, 0.128242f, 0.128963f,
1412       0.129683f, 0.130403f, 0.131124f, 0.131844f, 0.132565f, 0.133285f,
1413       0.134006f, 0.134726f, 0.135447f, 0.136167f, 0.136888f, 0.137608f,
1414       0.138329f, 0.139049f, 0.139769f, 0.140490f, 0.141210f, 0.141931f,
1415       0.142651f, 0.143372f, 0.144092f, 0.144813f, 0.145533f, 0.146254f,
1416       0.146974f, 0.147695f, 0.148415f, 0.149135f, 0.149856f, 0.150576f,
1417       0.151297f, 0.152017f, 0.152738f, 0.153458f, 0.154179f, 0.154899f,
1418       0.155620f, 0.156340f, 0.157061f, 0.157781f, 0.158501f, 0.159222f,
1419       0.159942f, 0.160663f, 0.161383f, 0.162104f, 0.162824f, 0.163545f,
1420       0.164265f, 0.164986f, 0.165706f, 0.166427f, 0.167147f, 0.167867f,
1421       0.168588f, 0.169308f, 0.170029f, 0.170749f, 0.171470f, 0.172190f,
1422       0.172911f, 0.173631f, 0.174352f, 0.175072f, 0.175793f, 0.176513f,
1423       0.177233f, 0.177954f, 0.178674f, 0.179395f, 0.180115f, 0.180836f,
1424       0.181556f, 0.182277f, 0.182997f, 0.183718f, 0.184438f, 0.185159f,
1425       0.185879f, 0.186599f, 0.187320f, 0.188040f, 0.188761f, 0.189481f,
1426       0.190202f, 0.190922f, 0.191643f, 0.192363f, 0.193084f, 0.193804f,
1427       0.194524f, 0.195245f, 0.195965f, 0.196686f, 0.197406f, 0.198127f,
1428       0.198847f, 0.199568f, 0.200288f, 0.201009f, 0.201729f, 0.202450f,
1429       0.203170f, 0.203890f, 0.204611f, 0.205331f, 0.206052f, 0.206772f,
1430       0.207493f, 0.208213f, 0.208934f, 0.209654f, 0.210375f, 0.211095f,
1431       0.211816f, 0.212536f, 0.213256f, 0.213977f, 0.214697f, 0.215418f,
1432       0.216138f, 0.216859f, 0.217579f, 0.218300f, 0.219020f, 0.219741f,
1433       0.220461f, 0.221182f, 0.221902f, 0.222622f, 0.223343f, 0.224063f,
1434       0.224784f, 0.225504f, 0.226225f, 0.226945f, 0.227666f, 0.228386f,
1435       0.229107f, 0.229827f, 0.230548f, 0.231268f, 0.231988f, 0.232709f,
1436       0.233429f, 0.234150f, 0.234870f, 0.235591f, 0.236311f, 0.237032f,
1437       0.237752f, 0.238473f, 0.239193f, 0.239914f, 0.240634f, 0.241354f,
1438       0.242075f, 0.242795f, 0.243516f, 0.244236f, 0.244957f, 0.245677f,
1439       0.246398f, 0.247118f, 0.247839f, 0.248559f, 0.249280f, 0.250000f,
1440       0.250720f, 0.251441f, 0.252161f, 0.252882f, 0.253602f, 0.254323f,
1441       0.255043f, 0.255764f, 0.256484f, 0.257205f, 0.257925f, 0.258646f,
1442       0.259366f, 0.260086f, 0.260807f, 0.261527f, 0.262248f, 0.262968f,
1443       0.263689f, 0.264409f, 0.265130f, 0.265850f, 0.266571f, 0.267291f,
1444       0.268012f, 0.268732f, 0.269452f, 0.270173f, 0.270893f, 0.271614f,
1445       0.272334f, 0.273055f, 0.273775f, 0.274496f, 0.275216f, 0.275937f,
1446       0.276657f, 0.277378f, 0.278098f, 0.278818f, 0.279539f, 0.280259f,
1447       0.280980f, 0.281700f, 0.282421f, 0.283141f, 0.283862f, 0.284582f,
1448       0.285303f, 0.286023f, 0.286744f, 0.287464f, 0.288184f, 0.288905f,
1449       0.289625f, 0.290346f, 0.291066f, 0.291787f, 0.292507f, 0.293228f,
1450       0.293948f, 0.294669f, 0.295389f, 0.296109f, 0.296830f, 0.297550f,
1451       0.298271f, 0.298991f, 0.299712f, 0.300432f, 0.301153f, 0.301873f,
1452       0.302594f, 0.303314f, 0.304035f, 0.304755f, 0.305476f, 0.306196f,
1453       0.306916f, 0.307637f, 0.308357f, 0.309078f, 0.309798f, 0.310519f,
1454       0.311239f, 0.311960f, 0.312680f, 0.313401f, 0.314121f, 0.314842f,
1455       0.315562f, 0.316282f, 0.317003f, 0.317723f, 0.318444f, 0.319164f,
1456       0.319885f, 0.320605f, 0.321326f, 0.322046f, 0.322767f, 0.323487f,
1457       0.324207f, 0.324928f, 0.325648f, 0.326369f, 0.327089f, 0.327810f,
1458       0.328530f, 0.329251f, 0.329971f, 0.330692f, 0.331412f, 0.332133f,
1459       0.332853f, 0.333573f, 0.334294f, 0.335014f, 0.335735f, 0.336455f,
1460       0.337176f, 0.337896f, 0.338617f, 0.339337f, 0.340058f, 0.340778f,
1461       0.341499f, 0.342219f, 0.342939f, 0.343660f, 0.344380f, 0.345101f,
1462       0.345821f, 0.346542f, 0.347262f, 0.347983f, 0.348703f, 0.349424f,
1463       0.350144f, 0.350865f, 0.351585f, 0.352305f, 0.353026f, 0.353746f,
1464       0.354467f, 0.355187f, 0.355908f, 0.356628f, 0.357349f, 0.358069f,
1465       0.358790f, 0.359510f, 0.360231f, 0.360951f, 0.361671f, 0.362392f,
1466       0.363112f, 0.363833f, 0.364553f, 0.365274f, 0.365994f, 0.366715f,
1467       0.367435f, 0.368156f, 0.368876f, 0.369597f, 0.370317f, 0.371037f,
1468       0.371758f, 0.372478f, 0.373199f, 0.373919f, 0.374640f, 0.375360f,
1469       0.376081f, 0.376801f, 0.377522f, 0.378242f, 0.378963f, 0.379683f,
1470       0.380403f, 0.381124f, 0.381844f, 0.382565f, 0.383285f, 0.384006f,
1471       0.384726f, 0.385447f, 0.386167f, 0.386888f, 0.387608f, 0.388329f,
1472       0.389049f, 0.389769f, 0.390490f, 0.391210f, 0.391931f, 0.392651f,
1473       0.393372f, 0.394092f, 0.394813f, 0.395533f, 0.396254f, 0.396974f,
1474       0.397695f, 0.398415f, 0.399135f, 0.399856f, 0.400576f, 0.401297f,
1475       0.402017f, 0.402738f, 0.403458f, 0.404179f, 0.404899f, 0.405620f,
1476       0.406340f, 0.407061f, 0.407781f, 0.408501f, 0.409222f, 0.409942f,
1477       0.410663f, 0.411383f, 0.412104f, 0.412824f, 0.413545f, 0.414265f,
1478       0.414986f, 0.415706f, 0.416427f, 0.417147f, 0.417867f, 0.418588f,
1479       0.419308f, 0.420029f, 0.420749f, 0.421470f, 0.422190f, 0.422911f,
1480       0.423631f, 0.424352f, 0.425072f, 0.425793f, 0.426513f, 0.427233f,
1481       0.427954f, 0.428674f, 0.429395f, 0.430115f, 0.430836f, 0.431556f,
1482       0.432277f, 0.432997f, 0.433718f, 0.434438f, 0.435158f, 0.435879f,
1483       0.436599f, 0.437320f, 0.438040f, 0.438761f, 0.439481f, 0.440202f,
1484       0.440922f, 0.441643f, 0.442363f, 0.443084f, 0.443804f, 0.444524f,
1485       0.445245f, 0.445965f, 0.446686f, 0.447406f, 0.448127f, 0.448847f,
1486       0.449568f, 0.450288f, 0.451009f, 0.451729f, 0.452450f, 0.453170f,
1487       0.453891f, 0.454611f, 0.455331f, 0.456052f, 0.456772f, 0.457493f,
1488       0.458213f, 0.458934f, 0.459654f, 0.460375f, 0.461095f, 0.461816f,
1489       0.462536f, 0.463256f, 0.463977f, 0.464697f, 0.465418f, 0.466138f,
1490       0.466859f, 0.467579f, 0.468300f, 0.469020f, 0.469741f, 0.470461f,
1491       0.471182f, 0.471902f, 0.472622f, 0.473343f, 0.474063f, 0.474784f,
1492       0.475504f, 0.476225f, 0.476945f, 0.477666f, 0.478386f, 0.479107f,
1493       0.479827f, 0.480548f, 0.481268f, 0.481988f, 0.482709f, 0.483429f,
1494       0.484150f, 0.484870f, 0.485591f, 0.486311f, 0.487032f, 0.487752f,
1495       0.488473f, 0.489193f, 0.489914f, 0.490634f, 0.491354f, 0.492075f,
1496       0.492795f, 0.493516f, 0.494236f, 0.494957f, 0.495677f, 0.496398f,
1497       0.497118f, 0.497839f, 0.498559f, 0.499280f, 0.500000f, 0.500720f,
1498       0.501441f, 0.502161f, 0.502882f, 0.503602f, 0.504323f, 0.505043f,
1499       0.505764f, 0.506484f, 0.507205f, 0.507925f, 0.508646f, 0.509366f,
1500       0.510086f, 0.510807f, 0.511527f, 0.512248f, 0.512968f, 0.513689f,
1501       0.514409f, 0.515130f, 0.515850f, 0.516571f, 0.517291f, 0.518012f,
1502       0.518732f, 0.519452f, 0.520173f, 0.520893f, 0.521614f, 0.522334f,
1503       0.523055f, 0.523775f, 0.524496f, 0.525216f, 0.525937f, 0.526657f,
1504       0.527378f, 0.528098f, 0.528818f, 0.529539f, 0.530259f, 0.530980f,
1505       0.531700f, 0.532421f, 0.533141f, 0.533862f, 0.534582f, 0.535303f,
1506       0.536023f, 0.536744f, 0.537464f, 0.538184f, 0.538905f, 0.539625f,
1507       0.540346f, 0.541066f, 0.541787f, 0.542507f, 0.543228f, 0.543948f,
1508       0.544669f, 0.545389f, 0.546109f, 0.546830f, 0.547550f, 0.548271f,
1509       0.548991f, 0.549712f, 0.550432f, 0.551153f, 0.551873f, 0.552594f,
1510       0.553314f, 0.554035f, 0.554755f, 0.555476f, 0.556196f, 0.556916f,
1511       0.557637f, 0.558357f, 0.559078f, 0.559798f, 0.560519f, 0.561239f,
1512       0.561960f, 0.562680f, 0.563401f, 0.564121f, 0.564842f, 0.565562f,
1513       0.566282f, 0.567003f, 0.567723f, 0.568444f, 0.569164f, 0.569885f,
1514       0.570605f, 0.571326f, 0.572046f, 0.572767f, 0.573487f, 0.574207f,
1515       0.574928f, 0.575648f, 0.576369f, 0.577089f, 0.577810f, 0.578530f,
1516       0.579251f, 0.579971f, 0.580692f, 0.581412f, 0.582133f, 0.582853f,
1517       0.583573f, 0.584294f, 0.585014f, 0.585735f, 0.586455f, 0.587176f,
1518       0.587896f, 0.588617f, 0.589337f, 0.590058f, 0.590778f, 0.591499f,
1519       0.592219f, 0.592939f, 0.593660f, 0.594380f, 0.595101f, 0.595821f,
1520       0.596542f, 0.597262f, 0.597983f, 0.598703f, 0.599424f, 0.600144f,
1521       0.600865f, 0.601585f, 0.602305f, 0.603026f, 0.603746f, 0.604467f,
1522       0.605187f, 0.605908f, 0.606628f, 0.607349f, 0.608069f, 0.608790f,
1523       0.609510f, 0.610231f, 0.610951f, 0.611671f, 0.612392f, 0.613112f,
1524       0.613833f, 0.614553f, 0.615274f, 0.615994f, 0.616715f, 0.617435f,
1525       0.618156f, 0.618876f, 0.619597f, 0.620317f, 0.621037f, 0.621758f,
1526       0.622478f, 0.623199f, 0.623919f, 0.624640f, 0.625360f, 0.626081f,
1527       0.626801f, 0.627522f, 0.628242f, 0.628963f, 0.629683f, 0.630403f,
1528       0.631124f, 0.631844f, 0.632565f, 0.633285f, 0.634006f, 0.634726f,
1529       0.635447f, 0.636167f, 0.636888f, 0.637608f, 0.638329f, 0.639049f,
1530       0.639769f, 0.640490f, 0.641210f, 0.641931f, 0.642651f, 0.643372f,
1531       0.644092f, 0.644813f, 0.645533f, 0.646254f, 0.646974f, 0.647695f,
1532       0.648415f, 0.649135f, 0.649856f, 0.650576f, 0.651297f, 0.652017f,
1533       0.652738f, 0.653458f, 0.654179f, 0.654899f, 0.655620f, 0.656340f,
1534       0.657061f, 0.657781f, 0.658501f, 0.659222f, 0.659942f, 0.660663f,
1535       0.661383f, 0.662104f, 0.662824f, 0.663545f, 0.664265f, 0.664986f,
1536       0.665706f, 0.666427f, 0.667147f, 0.667867f, 0.668588f, 0.669308f,
1537       0.670029f, 0.670749f, 0.671470f, 0.672190f, 0.672911f, 0.673631f,
1538       0.674352f, 0.675072f, 0.675793f, 0.676513f, 0.677233f, 0.677954f,
1539       0.678674f, 0.679395f, 0.680115f, 0.680836f, 0.681556f, 0.682277f,
1540       0.682997f, 0.683718f, 0.684438f, 0.685158f, 0.685879f, 0.686599f,
1541       0.687320f, 0.688040f, 0.688761f, 0.689481f, 0.690202f, 0.690922f,
1542       0.691643f, 0.692363f, 0.693084f, 0.693804f, 0.694524f, 0.695245f,
1543       0.695965f, 0.696686f, 0.697406f, 0.698127f, 0.698847f, 0.699568f,
1544       0.700288f, 0.701009f, 0.701729f, 0.702450f, 0.703170f, 0.703891f,
1545       0.704611f, 0.705331f, 0.706052f, 0.706772f, 0.707493f, 0.708213f,
1546       0.708934f, 0.709654f, 0.710375f, 0.711095f, 0.711816f, 0.712536f,
1547       0.713256f, 0.713977f, 0.714697f, 0.715418f, 0.716138f, 0.716859f,
1548       0.717579f, 0.718300f, 0.719020f, 0.719741f, 0.720461f, 0.721182f,
1549       0.721902f, 0.722622f, 0.723343f, 0.724063f, 0.724784f, 0.725504f,
1550       0.726225f, 0.726945f, 0.727666f, 0.728386f, 0.729107f, 0.729827f,
1551       0.730548f, 0.731268f, 0.731988f, 0.732709f, 0.733429f, 0.734150f,
1552       0.734870f, 0.735591f, 0.736311f, 0.737032f, 0.737752f, 0.738473f,
1553       0.739193f, 0.739914f, 0.740634f, 0.741354f, 0.742075f, 0.742795f,
1554       0.743516f, 0.744236f, 0.744957f, 0.745677f, 0.746398f, 0.747118f,
1555       0.747839f, 0.748559f, 0.749280f, 0.750000f, 0.750720f, 0.751441f,
1556       0.752161f, 0.752882f, 0.753602f, 0.754323f, 0.755043f, 0.755764f,
1557       0.756484f, 0.757205f, 0.757925f, 0.758646f, 0.759366f, 0.760086f,
1558       0.760807f, 0.761527f, 0.762248f, 0.762968f, 0.763689f, 0.764409f,
1559       0.765130f, 0.765850f, 0.766571f, 0.767291f, 0.768012f, 0.768732f,
1560       0.769452f, 0.770173f, 0.770893f, 0.771614f, 0.772334f, 0.773055f,
1561       0.773775f, 0.774496f, 0.775216f, 0.775937f, 0.776657f, 0.777378f,
1562       0.778098f, 0.778818f, 0.779539f, 0.780259f, 0.780980f, 0.781700f,
1563       0.782421f, 0.783141f, 0.783862f, 0.784582f, 0.785303f, 0.786023f,
1564       0.786744f, 0.787464f, 0.788184f, 0.788905f, 0.789625f, 0.790346f,
1565       0.791066f, 0.791787f, 0.792507f, 0.793228f, 0.793948f, 0.794669f,
1566       0.795389f, 0.796109f, 0.796830f, 0.797550f, 0.798271f, 0.798991f,
1567       0.799712f, 0.800432f, 0.801153f, 0.801873f, 0.802594f, 0.803314f,
1568       0.804035f, 0.804755f, 0.805476f, 0.806196f, 0.806916f, 0.807637f,
1569       0.808357f, 0.809078f, 0.809798f, 0.810519f, 0.811239f, 0.811960f,
1570       0.812680f, 0.813401f, 0.814121f, 0.814842f, 0.815562f, 0.816282f,
1571       0.817003f, 0.817723f, 0.818444f, 0.819164f, 0.819885f, 0.820605f,
1572       0.821326f, 0.822046f, 0.822767f, 0.823487f, 0.824207f, 0.824928f,
1573       0.825648f, 0.826369f, 0.827089f, 0.827810f, 0.828530f, 0.829251f,
1574       0.829971f, 0.830692f, 0.831412f, 0.832133f, 0.832853f, 0.833573f,
1575       0.834294f, 0.835014f, 0.835735f, 0.836455f, 0.837176f, 0.837896f,
1576       0.838617f, 0.839337f, 0.840058f, 0.840778f, 0.841499f, 0.842219f,
1577       0.842939f, 0.843660f, 0.844380f, 0.845101f, 0.845821f, 0.846542f,
1578       0.847262f, 0.847983f, 0.848703f, 0.849424f, 0.850144f, 0.850865f,
1579       0.851585f, 0.852305f, 0.853026f, 0.853746f, 0.854467f, 0.855187f,
1580       0.855908f, 0.856628f, 0.857349f, 0.858069f, 0.858790f, 0.859510f,
1581       0.860231f, 0.860951f, 0.861671f, 0.862392f, 0.863112f, 0.863833f,
1582       0.864553f, 0.865274f, 0.865994f, 0.866715f, 0.867435f, 0.868156f,
1583       0.868876f, 0.869597f, 0.870317f, 0.871037f, 0.871758f, 0.872478f,
1584       0.873199f, 0.873919f, 0.874640f, 0.875360f, 0.876081f, 0.876801f,
1585       0.877522f, 0.878242f, 0.878963f, 0.879683f, 0.880403f, 0.881124f,
1586       0.881844f, 0.882565f, 0.883285f, 0.884006f, 0.884726f, 0.885447f,
1587       0.886167f, 0.886888f, 0.887608f, 0.888329f, 0.889049f, 0.889769f,
1588       0.890490f, 0.891210f, 0.891931f, 0.892651f, 0.893372f, 0.894092f,
1589       0.894813f, 0.895533f, 0.896254f, 0.896974f, 0.897695f, 0.898415f,
1590       0.899135f, 0.899856f, 0.900576f, 0.901297f, 0.902017f, 0.902738f,
1591       0.903458f, 0.904179f, 0.904899f, 0.905620f, 0.906340f, 0.907061f,
1592       0.907781f, 0.908501f, 0.909222f, 0.909942f, 0.910663f, 0.911383f,
1593       0.912104f, 0.912824f, 0.913545f, 0.914265f, 0.914986f, 0.915706f,
1594       0.916427f, 0.917147f, 0.917867f, 0.918588f, 0.919308f, 0.920029f,
1595       0.920749f, 0.921470f, 0.922190f, 0.922911f, 0.923631f, 0.924352f,
1596       0.925072f, 0.925793f, 0.926513f, 0.927233f, 0.927954f, 0.928674f,
1597       0.929395f, 0.930115f, 0.930836f, 0.931556f, 0.932277f, 0.932997f,
1598       0.933718f, 0.934438f, 0.935158f, 0.935879f, 0.936599f, 0.937320f,
1599       0.938040f, 0.938761f, 0.939481f, 0.940202f, 0.940922f, 0.941643f,
1600       0.942363f, 0.943084f, 0.943804f, 0.944524f, 0.945245f, 0.945965f,
1601       0.946686f, 0.947406f, 0.948127f, 0.948847f, 0.949568f, 0.950288f,
1602       0.951009f, 0.951729f, 0.952450f, 0.953170f, 0.953891f, 0.954611f,
1603       0.955331f, 0.956052f, 0.956772f, 0.957493f, 0.958213f, 0.958934f,
1604       0.959654f, 0.960375f, 0.961095f, 0.961816f, 0.962536f, 0.963256f,
1605       0.963977f, 0.964697f, 0.965418f, 0.966138f, 0.966859f, 0.967579f,
1606       0.968300f, 0.969020f, 0.969741f, 0.970461f, 0.971182f, 0.971902f,
1607       0.972622f, 0.973343f, 0.974063f, 0.974784f, 0.975504f, 0.976225f,
1608       0.976945f, 0.977666f, 0.978386f, 0.979107f, 0.979827f, 0.980548f,
1609       0.981268f, 0.981988f, 0.982709f, 0.983429f, 0.984150f, 0.984870f,
1610       0.985591f, 0.986311f, 0.987032f, 0.987752f, 0.988473f, 0.989193f,
1611       0.989914f, 0.990634f, 0.991354f, 0.992075f, 0.992795f, 0.993516f,
1612       0.994236f, 0.994957f, 0.995677f, 0.996398f, 0.997118f, 0.997839f,
1613       0.998559f, 0.999280f, 1.000000f
1614     };
1615 #endif
1616
1617   CacheView
1618     *image_view;
1619
1620   ExceptionInfo
1621     *exception;
1622
1623   MagickBooleanType
1624     status;
1625
1626   MagickOffsetType
1627     progress;
1628
1629   register ssize_t
1630     i;
1631
1632   ssize_t
1633     y;
1634
1635   TransformPacket
1636     *y_map,
1637     *x_map,
1638     *z_map;
1639
1640   assert(image != (Image *) NULL);
1641   assert(image->signature == MagickSignature);
1642   if (image->debug != MagickFalse)
1643     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1644   switch (colorspace)
1645   {
1646     case GRAYColorspace:
1647     case Rec601LumaColorspace:
1648     case Rec709LumaColorspace:
1649     case RGBColorspace:
1650     case TransparentColorspace:
1651     case UndefinedColorspace:
1652       return(MagickTrue);
1653     default:
1654       break;
1655   }
1656   status=MagickTrue;
1657   progress=0;
1658   exception=(&image->exception);
1659   switch (colorspace)
1660   {
1661     case CMYColorspace:
1662     {
1663       /*
1664         Transform image from CMY to RGB.
1665       */
1666       if (image->storage_class == PseudoClass)
1667         {
1668           if (SyncImage(image) == MagickFalse)
1669             return(MagickFalse);
1670           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1671             return(MagickFalse);
1672         }
1673       image_view=AcquireCacheView(image);
1674 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1675   #pragma omp parallel for schedule(dynamic,4) shared(status)
1676 #endif
1677       for (y=0; y < (ssize_t) image->rows; y++)
1678       {
1679         MagickBooleanType
1680           sync;
1681
1682         register ssize_t
1683           x;
1684
1685         register Quantum
1686           *restrict q;
1687
1688         if (status == MagickFalse)
1689           continue;
1690         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1691           exception);
1692         if (q == (const Quantum *) NULL)
1693           {
1694             status=MagickFalse;
1695             continue;
1696           }
1697         for (x=0; x < (ssize_t) image->columns; x++)
1698         {
1699           SetPixelRed(image,ClampToQuantum((MagickRealType) (QuantumRange-
1700             GetPixelRed(image,q))),q);
1701           SetPixelGreen(image,ClampToQuantum((MagickRealType) (QuantumRange-
1702             GetPixelGreen(image,q))),q);
1703           SetPixelBlue(image,ClampToQuantum((MagickRealType) (QuantumRange-
1704             GetPixelBlue(image,q))),q);
1705           q+=GetPixelChannels(image);
1706         }
1707         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1708         if (sync == MagickFalse)
1709           status=MagickFalse;
1710       }
1711       image_view=DestroyCacheView(image_view);
1712       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
1713         return(MagickFalse);
1714       return(status);
1715     }
1716     case CMYKColorspace:
1717     {
1718       PixelInfo
1719         zero;
1720
1721       /*
1722         Transform image from CMYK to RGB.
1723       */
1724       if (image->storage_class == PseudoClass)
1725         {
1726           if (SyncImage(image) == MagickFalse)
1727             return(MagickFalse);
1728           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1729             return(MagickFalse);
1730         }
1731       GetPixelInfo(image,&zero);
1732       image_view=AcquireCacheView(image);
1733 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1734   #pragma omp parallel for schedule(dynamic,4) shared(status)
1735 #endif
1736       for (y=0; y < (ssize_t) image->rows; y++)
1737       {
1738         MagickBooleanType
1739           sync;
1740
1741         PixelInfo
1742           pixel;
1743
1744         register ssize_t
1745           x;
1746
1747         register Quantum
1748           *restrict q;
1749
1750         if (status == MagickFalse)
1751           continue;
1752         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1753           exception);
1754         if (q == (const Quantum *) NULL)
1755           {
1756             status=MagickFalse;
1757             continue;
1758           }
1759         pixel=zero;
1760         for (x=0; x < (ssize_t) image->columns; x++)
1761         {
1762           SetPixelInfo(image,q,&pixel);
1763           ConvertCMYKToRGB(&pixel);
1764           SetPixelPixelInfo(image,&pixel,q);
1765           q+=GetPixelChannels(image);
1766         }
1767         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1768         if (sync == MagickFalse)
1769           status=MagickFalse;
1770       }
1771       image_view=DestroyCacheView(image_view);
1772       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
1773         return(MagickFalse);
1774       return(status);
1775     }
1776     case HSBColorspace:
1777     {
1778       /*
1779         Transform image from HSB to RGB.
1780       */
1781       if (image->storage_class == PseudoClass)
1782         {
1783           if (SyncImage(image) == MagickFalse)
1784             return(MagickFalse);
1785           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1786             return(MagickFalse);
1787         }
1788       image_view=AcquireCacheView(image);
1789 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1790   #pragma omp parallel for schedule(dynamic,4) shared(status)
1791 #endif
1792       for (y=0; y < (ssize_t) image->rows; y++)
1793       {
1794         double
1795           brightness,
1796           hue,
1797           saturation;
1798
1799         MagickBooleanType
1800           sync;
1801
1802         register ssize_t
1803           x;
1804
1805         register Quantum
1806           *restrict q;
1807
1808         if (status == MagickFalse)
1809           continue;
1810         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1811           exception);
1812         if (q == (const Quantum *) NULL)
1813           {
1814             status=MagickFalse;
1815             continue;
1816           }
1817         for (x=0; x < (ssize_t) image->columns; x++)
1818         {
1819           Quantum
1820             blue,
1821             green,
1822             red;
1823
1824           hue=(double) (QuantumScale*GetPixelRed(image,q));
1825           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
1826           brightness=(double) (QuantumScale*GetPixelBlue(image,q));
1827           ConvertHSBToRGB(hue,saturation,brightness,&red,&green,&blue);
1828           SetPixelRed(image,red,q);
1829           SetPixelGreen(image,green,q);
1830           SetPixelBlue(image,blue,q);
1831           q+=GetPixelChannels(image);
1832         }
1833         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1834         if (sync == MagickFalse)
1835           status=MagickFalse;
1836       }
1837       image_view=DestroyCacheView(image_view);
1838       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
1839         return(MagickFalse);
1840       return(status);
1841     }
1842     case HSLColorspace:
1843     {
1844       /*
1845         Transform image from HSL to RGB.
1846       */
1847       if (image->storage_class == PseudoClass)
1848         {
1849           if (SyncImage(image) == MagickFalse)
1850             return(MagickFalse);
1851           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1852             return(MagickFalse);
1853         }
1854       image_view=AcquireCacheView(image);
1855 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1856   #pragma omp parallel for schedule(dynamic,4) shared(status)
1857 #endif
1858       for (y=0; y < (ssize_t) image->rows; y++)
1859       {
1860         double
1861           hue,
1862           lightness,
1863           saturation;
1864
1865         MagickBooleanType
1866           sync;
1867
1868         register ssize_t
1869           x;
1870
1871         register Quantum
1872           *restrict q;
1873
1874         if (status == MagickFalse)
1875           continue;
1876         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1877           exception);
1878         if (q == (const Quantum *) NULL)
1879           {
1880             status=MagickFalse;
1881             continue;
1882           }
1883         for (x=0; x < (ssize_t) image->columns; x++)
1884         {
1885           Quantum
1886             blue,
1887             green,
1888             red;
1889
1890           hue=(double) (QuantumScale*GetPixelRed(image,q));
1891           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
1892           lightness=(double) (QuantumScale*GetPixelBlue(image,q));
1893           ConvertHSLToRGB(hue,saturation,lightness,&red,&green,&blue);
1894           SetPixelRed(image,red,q);
1895           SetPixelGreen(image,green,q);
1896           SetPixelBlue(image,blue,q);
1897           q+=GetPixelChannels(image);
1898         }
1899         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1900         if (sync == MagickFalse)
1901           status=MagickFalse;
1902       }
1903       image_view=DestroyCacheView(image_view);
1904       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
1905         return(MagickFalse);
1906       return(status);
1907     }
1908     case HWBColorspace:
1909     {
1910       /*
1911         Transform image from HWB to RGB.
1912       */
1913       if (image->storage_class == PseudoClass)
1914         {
1915           if (SyncImage(image) == MagickFalse)
1916             return(MagickFalse);
1917           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1918             return(MagickFalse);
1919         }
1920       image_view=AcquireCacheView(image);
1921 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1922   #pragma omp parallel for schedule(dynamic,4) shared(status)
1923 #endif
1924       for (y=0; y < (ssize_t) image->rows; y++)
1925       {
1926         double
1927           blackness,
1928           hue,
1929           whiteness;
1930
1931         MagickBooleanType
1932           sync;
1933
1934         register ssize_t
1935           x;
1936
1937         register Quantum
1938           *restrict q;
1939
1940         if (status == MagickFalse)
1941           continue;
1942         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1943           exception);
1944         if (q == (const Quantum *) NULL)
1945           {
1946             status=MagickFalse;
1947             continue;
1948           }
1949         for (x=0; x < (ssize_t) image->columns; x++)
1950         {
1951           Quantum
1952             blue,
1953             green,
1954             red;
1955
1956           hue=(double) (QuantumScale*GetPixelRed(image,q));
1957           whiteness=(double) (QuantumScale*GetPixelGreen(image,q));
1958           blackness=(double) (QuantumScale*GetPixelBlue(image,q));
1959           ConvertHWBToRGB(hue,whiteness,blackness,&red,&green,&blue);
1960           SetPixelRed(image,red,q);
1961           SetPixelGreen(image,green,q);
1962           SetPixelBlue(image,blue,q);
1963           q+=GetPixelChannels(image);
1964         }
1965         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1966         if (sync == MagickFalse)
1967           status=MagickFalse;
1968       }
1969       image_view=DestroyCacheView(image_view);
1970       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
1971         return(MagickFalse);
1972       return(status);
1973     }
1974     case LabColorspace:
1975     {
1976       /*
1977         Transform image from Lab to RGB.
1978       */
1979       if (image->storage_class == PseudoClass)
1980         {
1981           if (SyncImage(image) == MagickFalse)
1982             return(MagickFalse);
1983           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1984             return(MagickFalse);
1985         }
1986       image_view=AcquireCacheView(image);
1987 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1988   #pragma omp parallel for schedule(dynamic,4) shared(status)
1989 #endif
1990       for (y=0; y < (ssize_t) image->rows; y++)
1991       {
1992         double
1993           a,
1994           b,
1995           L,
1996           X,
1997           Y,
1998           Z;
1999
2000         MagickBooleanType
2001           sync;
2002
2003         register ssize_t
2004           x;
2005
2006         register Quantum
2007           *restrict q;
2008
2009         if (status == MagickFalse)
2010           continue;
2011         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2012           exception);
2013         if (q == (const Quantum *) NULL)
2014           {
2015             status=MagickFalse;
2016             continue;
2017           }
2018         X=0.0;
2019         Y=0.0;
2020         Z=0.0;
2021         for (x=0; x < (ssize_t) image->columns; x++)
2022         {
2023           Quantum
2024             blue,
2025             green,
2026             red;
2027
2028           L=QuantumScale*GetPixelRed(image,q);
2029           a=QuantumScale*GetPixelGreen(image,q);
2030           b=QuantumScale*GetPixelBlue(image,q);
2031           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
2032           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2033           SetPixelRed(image,red,q);
2034           SetPixelGreen(image,green,q);
2035           SetPixelBlue(image,blue,q);
2036           q+=GetPixelChannels(image);
2037         }
2038         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2039         if (sync == MagickFalse)
2040           status=MagickFalse;
2041       }
2042       image_view=DestroyCacheView(image_view);
2043       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
2044         return(MagickFalse);
2045       return(status);
2046     }
2047     case LogColorspace:
2048     {
2049       const char
2050         *value;
2051
2052       double
2053         black,
2054         density,
2055         film_gamma,
2056         gamma,
2057         reference_black,
2058         reference_white;
2059
2060       Quantum
2061         *logmap;
2062
2063       /*
2064         Transform Log to RGB colorspace.
2065       */
2066       density=DisplayGamma;
2067       gamma=DisplayGamma;
2068       value=GetImageProperty(image,"gamma");
2069       if (value != (const char *) NULL)
2070         gamma=1.0/InterpretLocaleValue(value,(char **) NULL) != 0.0 ?
2071           InterpretLocaleValue(value,(char **) NULL) : 1.0;
2072       film_gamma=FilmGamma;
2073       value=GetImageProperty(image,"film-gamma");
2074       if (value != (const char *) NULL)
2075         film_gamma=InterpretLocaleValue(value,(char **) NULL);
2076       reference_black=ReferenceBlack;
2077       value=GetImageProperty(image,"reference-black");
2078       if (value != (const char *) NULL)
2079         reference_black=InterpretLocaleValue(value,(char **) NULL);
2080       reference_white=ReferenceWhite;
2081       value=GetImageProperty(image,"reference-white");
2082       if (value != (const char *) NULL)
2083         reference_white=InterpretLocaleValue(value,(char **) NULL);
2084       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2085         sizeof(*logmap));
2086       if (logmap == (Quantum *) NULL)
2087         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2088           image->filename);
2089       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
2090         0.002/film_gamma);
2091       for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
2092         logmap[i]=(Quantum) 0;
2093       for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0); i++)
2094         logmap[i]=ClampToQuantum((MagickRealType) QuantumRange/(1.0-black)*
2095           (pow(10.0,(1024.0*i/MaxMap-reference_white)*
2096           (gamma/density)*0.002/film_gamma)-black));
2097       for ( ; i <= (ssize_t) MaxMap; i++)
2098         logmap[i]=(Quantum) QuantumRange;
2099       if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2100         return(MagickFalse);
2101       image_view=AcquireCacheView(image);
2102 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2103   #pragma omp parallel for schedule(dynamic,4) shared(status)
2104 #endif
2105       for (y=0; y < (ssize_t) image->rows; y++)
2106       {
2107         MagickBooleanType
2108           sync;
2109
2110         register ssize_t
2111           x;
2112
2113         register Quantum
2114           *restrict q;
2115
2116         if (status == MagickFalse)
2117           continue;
2118         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2119           exception);
2120         if (q == (const Quantum *) NULL)
2121           {
2122             status=MagickFalse;
2123             continue;
2124           }
2125         for (x=(ssize_t) image->columns; x != 0; x--)
2126         {
2127           SetPixelRed(image,logmap[ScaleQuantumToMap(
2128             GetPixelRed(image,q))],q);
2129           SetPixelGreen(image,logmap[ScaleQuantumToMap(
2130             GetPixelGreen(image,q))],q);
2131           SetPixelBlue(image,logmap[ScaleQuantumToMap(
2132             GetPixelBlue(image,q))],q);
2133           q+=GetPixelChannels(image);
2134         }
2135         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2136         if (sync == MagickFalse)
2137           status=MagickFalse;
2138       }
2139       image_view=DestroyCacheView(image_view);
2140       logmap=(Quantum *) RelinquishMagickMemory(logmap);
2141       if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
2142         return(MagickFalse);
2143       return(status);
2144     }
2145     default:
2146       break;
2147   }
2148   /*
2149     Allocate the tables.
2150   */
2151   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2152     sizeof(*x_map));
2153   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2154     sizeof(*y_map));
2155   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2156     sizeof(*z_map));
2157   if ((x_map == (TransformPacket *) NULL) ||
2158       (y_map == (TransformPacket *) NULL) ||
2159       (z_map == (TransformPacket *) NULL))
2160     {
2161       if (z_map != (TransformPacket *) NULL)
2162         z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2163       if (y_map != (TransformPacket *) NULL)
2164         y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2165       if (x_map != (TransformPacket *) NULL)
2166         x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2167       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2168         image->filename);
2169     }
2170   switch (colorspace)
2171   {
2172     case OHTAColorspace:
2173     {
2174       /*
2175         Initialize OHTA tables:
2176
2177           R = I1+1.00000*I2-0.66668*I3
2178           G = I1+0.00000*I2+1.33333*I3
2179           B = I1-1.00000*I2-0.66668*I3
2180
2181         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2182         through QuantumRange.
2183       */
2184 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2185   #pragma omp parallel for schedule(dynamic,4)
2186 #endif
2187       for (i=0; i <= (ssize_t) MaxMap; i++)
2188       {
2189         x_map[i].x=(MagickRealType) i;
2190         y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType)
2191           MaxMap);
2192         z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
2193           MaxMap);
2194         x_map[i].y=(MagickRealType) i;
2195         y_map[i].y=0.000000f;
2196         z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType)
2197           MaxMap);
2198         x_map[i].z=(MagickRealType) i;
2199         y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType)
2200           MaxMap);
2201         z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
2202           MaxMap);
2203       }
2204       break;
2205     }
2206     case Rec601YCbCrColorspace:
2207     case YCbCrColorspace:
2208     {
2209       /*
2210         Initialize YCbCr tables:
2211
2212           R = Y            +1.402000*Cr
2213           G = Y-0.344136*Cb-0.714136*Cr
2214           B = Y+1.772000*Cb
2215
2216         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
2217         through QuantumRange.
2218       */
2219 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2220   #pragma omp parallel for schedule(dynamic,4)
2221 #endif
2222       for (i=0; i <= (ssize_t) MaxMap; i++)
2223       {
2224         x_map[i].x=(MagickRealType) i;
2225         y_map[i].x=0.000000f;
2226         z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i-
2227           (MagickRealType) MaxMap);
2228         x_map[i].y=(MagickRealType) i;
2229         y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i-
2230           (MagickRealType) MaxMap);
2231         z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i-
2232           (MagickRealType) MaxMap);
2233         x_map[i].z=(MagickRealType) i;
2234         y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i-
2235           (MagickRealType) MaxMap);
2236         z_map[i].z=0.000000f;
2237       }
2238       break;
2239     }
2240     case Rec709YCbCrColorspace:
2241     {
2242       /*
2243         Initialize YCbCr tables:
2244
2245           R = Y            +1.574800*Cr
2246           G = Y-0.187324*Cb-0.468124*Cr
2247           B = Y+1.855600*Cb
2248
2249         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
2250         through QuantumRange.
2251       */
2252 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2253   #pragma omp parallel for schedule(dynamic,4)
2254 #endif
2255       for (i=0; i <= (ssize_t) MaxMap; i++)
2256       {
2257         x_map[i].x=(MagickRealType) i;
2258         y_map[i].x=0.000000f;
2259         z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i-
2260           (MagickRealType) MaxMap);
2261         x_map[i].y=(MagickRealType) i;
2262         y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i-
2263           (MagickRealType) MaxMap);
2264         z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i-
2265           (MagickRealType) MaxMap);
2266         x_map[i].z=(MagickRealType) i;
2267         y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i-
2268           (MagickRealType) MaxMap);
2269         z_map[i].z=0.00000f;
2270       }
2271       break;
2272     }
2273     case sRGBColorspace:
2274     {
2275       /*
2276         Nonlinear sRGB to linear RGB.
2277
2278           R = 1.0*R+0.0*G+0.0*B
2279           G = 0.0*R+1.0*G+0.0*B
2280           B = 0.0*R+0.0*G+1.0*B
2281       */
2282 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2283   #pragma omp parallel for schedule(dynamic,4)
2284 #endif
2285       for (i=0; i <= (ssize_t) MaxMap; i++)
2286       {
2287         x_map[i].x=1.0f*(MagickRealType) i;
2288         y_map[i].x=0.0f*(MagickRealType) i;
2289         z_map[i].x=0.0f*(MagickRealType) i;
2290         x_map[i].y=0.0f*(MagickRealType) i;
2291         y_map[i].y=1.0f*(MagickRealType) i;
2292         z_map[i].y=0.0f*(MagickRealType) i;
2293         x_map[i].z=0.0f*(MagickRealType) i;
2294         y_map[i].z=0.0f*(MagickRealType) i;
2295         z_map[i].z=1.0f*(MagickRealType) i;
2296       }
2297       break;
2298     }
2299     case XYZColorspace:
2300     {
2301       /*
2302         Initialize CIE XYZ tables (ITU R-709 RGB):
2303
2304           R =  3.2404542*X-1.5371385*Y-0.4985314*Z
2305           G = -0.9692660*X+1.8760108*Y+0.0415560*Z
2306           B =  0.0556434*X-0.2040259*Y+1.057225*Z
2307       */
2308 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2309   #pragma omp parallel for schedule(dynamic,4)
2310 #endif
2311       for (i=0; i <= (ssize_t) MaxMap; i++)
2312       {
2313         x_map[i].x=3.2404542f*(MagickRealType) i;
2314         x_map[i].y=(-0.9692660f)*(MagickRealType) i;
2315         x_map[i].z=0.0556434f*(MagickRealType) i;
2316         y_map[i].x=(-1.5371385f)*(MagickRealType) i;
2317         y_map[i].y=1.8760108f*(MagickRealType) i;
2318         y_map[i].z=(-0.2040259f)*(MagickRealType) i;
2319         z_map[i].x=(-0.4985314f)*(MagickRealType) i;
2320         z_map[i].y=0.0415560f*(MagickRealType) i;
2321         z_map[i].z=1.0572252f*(MagickRealType) i;
2322       }
2323       break;
2324     }
2325     case YCCColorspace:
2326     {
2327       /*
2328         Initialize YCC tables:
2329
2330           R = Y            +1.340762*C2
2331           G = Y-0.317038*C1-0.682243*C2
2332           B = Y+1.632639*C1
2333
2334         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
2335       */
2336 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2337   #pragma omp parallel for schedule(dynamic,4)
2338 #endif
2339       for (i=0; i <= (ssize_t) MaxMap; i++)
2340       {
2341         x_map[i].x=1.3584000f*(MagickRealType) i;
2342         y_map[i].x=0.0000000f;
2343         z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType)
2344           ScaleQuantumToMap(ScaleCharToQuantum(137)));
2345         x_map[i].y=1.3584000f*(MagickRealType) i;
2346         y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType)
2347           ScaleQuantumToMap(ScaleCharToQuantum(156)));
2348         z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType)
2349           ScaleQuantumToMap(ScaleCharToQuantum(137)));
2350         x_map[i].z=1.3584000f*(MagickRealType) i;
2351         y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType)
2352           ScaleQuantumToMap(ScaleCharToQuantum(156)));
2353         z_map[i].z=0.0000000f;
2354       }
2355       break;
2356     }
2357     case YIQColorspace:
2358     {
2359       /*
2360         Initialize YIQ tables:
2361
2362           R = Y+0.95620*I+0.62140*Q
2363           G = Y-0.27270*I-0.64680*Q
2364           B = Y-1.10370*I+1.70060*Q
2365
2366         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2367         through QuantumRange.
2368       */
2369 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2370   #pragma omp parallel for schedule(dynamic,4)
2371 #endif
2372       for (i=0; i <= (ssize_t) MaxMap; i++)
2373       {
2374         x_map[i].x=(MagickRealType) i;
2375         y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType)
2376           MaxMap);
2377         z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType)
2378           MaxMap);
2379         x_map[i].y=(MagickRealType) i;
2380         y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2381           MaxMap);
2382         z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2383           MaxMap);
2384         x_map[i].z=(MagickRealType) i;
2385         y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2386           MaxMap);
2387         z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType)
2388           MaxMap);
2389       }
2390       break;
2391     }
2392     case YPbPrColorspace:
2393     {
2394       /*
2395         Initialize YPbPr tables:
2396
2397           R = Y            +1.402000*C2
2398           G = Y-0.344136*C1+0.714136*C2
2399           B = Y+1.772000*C1
2400
2401         Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
2402         through QuantumRange.
2403       */
2404 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2405   #pragma omp parallel for schedule(dynamic,4)
2406 #endif
2407       for (i=0; i <= (ssize_t) MaxMap; i++)
2408       {
2409         x_map[i].x=(MagickRealType) i;
2410         y_map[i].x=0.000000f;
2411         z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType)
2412           MaxMap);
2413         x_map[i].y=(MagickRealType) i;
2414         y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2415           MaxMap);
2416         z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType)
2417           MaxMap);
2418         x_map[i].z=(MagickRealType) i;
2419         y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType)
2420           MaxMap);
2421         z_map[i].z=0.00000f;
2422       }
2423       break;
2424     }
2425     case YUVColorspace:
2426     default:
2427     {
2428       /*
2429         Initialize YUV tables:
2430
2431           R = Y          +1.13980*V
2432           G = Y-0.39380*U-0.58050*V
2433           B = Y+2.02790*U
2434
2435         U and V, normally -0.5 through 0.5, must be normalized to the range 0
2436         through QuantumRange.
2437       */
2438 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2439   #pragma omp parallel for schedule(dynamic,4)
2440 #endif
2441       for (i=0; i <= (ssize_t) MaxMap; i++)
2442       {
2443         x_map[i].x=(MagickRealType) i;
2444         y_map[i].x=0.00000f;
2445         z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType)
2446           MaxMap);
2447         x_map[i].y=(MagickRealType) i;
2448         y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2449           MaxMap);
2450         z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2451           MaxMap);
2452         x_map[i].z=(MagickRealType) i;
2453         y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType)
2454           MaxMap);
2455         z_map[i].z=0.00000f;
2456       }
2457       break;
2458     }
2459   }
2460   /*
2461     Convert to RGB.
2462   */
2463   switch (image->storage_class)
2464   {
2465     case DirectClass:
2466     default:
2467     {
2468       /*
2469         Convert DirectClass image.
2470       */
2471       image_view=AcquireCacheView(image);
2472 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2473   #pragma omp parallel for schedule(dynamic,4) shared(status)
2474 #endif
2475       for (y=0; y < (ssize_t) image->rows; y++)
2476       {
2477         MagickBooleanType
2478           sync;
2479
2480         PixelInfo
2481           pixel;
2482
2483         register ssize_t
2484           x;
2485
2486         register Quantum
2487           *restrict q;
2488
2489         if (status == MagickFalse)
2490           continue;
2491         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2492           exception);
2493         if (q == (const Quantum *) NULL)
2494           {
2495             status=MagickFalse;
2496             continue;
2497           }
2498         for (x=0; x < (ssize_t) image->columns; x++)
2499         {
2500           register size_t
2501             blue,
2502             green,
2503             red;
2504
2505           red=ScaleQuantumToMap(GetPixelRed(image,q));
2506           green=ScaleQuantumToMap(GetPixelGreen(image,q));
2507           blue=ScaleQuantumToMap(GetPixelBlue(image,q));
2508           pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2509           pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2510           pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2511           switch (colorspace)
2512           {
2513             case YCCColorspace:
2514             {
2515 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2516               pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
2517                 pixel.red)];
2518               pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
2519                 pixel.green)];
2520               pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
2521                 pixel.blue)];
2522 #endif
2523               break;
2524             }
2525             case sRGBColorspace:
2526             {
2527               if ((QuantumScale*pixel.red) <= 0.0031308)
2528                 pixel.red*=12.92f;
2529               else
2530                 pixel.red=(MagickRealType) QuantumRange*(1.055*
2531                   pow(QuantumScale*pixel.red,(1.0/2.4))-0.055);
2532               if ((QuantumScale*pixel.green) <= 0.0031308)
2533                 pixel.green*=12.92f;
2534               else
2535                 pixel.green=(MagickRealType) QuantumRange*(1.055*
2536                   pow(QuantumScale*pixel.green,(1.0/2.4))-0.055);
2537               if ((QuantumScale*pixel.blue) <= 0.0031308)
2538                 pixel.blue*=12.92f;
2539               else
2540                 pixel.blue=(MagickRealType) QuantumRange*(1.055*
2541                   pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055);
2542               break;
2543             }
2544             default:
2545               break;
2546           }
2547           SetPixelRed(image,ScaleMapToQuantum((MagickRealType) MaxMap*
2548             QuantumScale*pixel.red),q);
2549           SetPixelGreen(image,ScaleMapToQuantum((MagickRealType) MaxMap*
2550             QuantumScale*pixel.green),q);
2551           SetPixelBlue(image,ScaleMapToQuantum((MagickRealType) MaxMap*
2552             QuantumScale*pixel.blue),q);
2553           q+=GetPixelChannels(image);
2554         }
2555         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2556         if (sync == MagickFalse)
2557           status=MagickFalse;
2558         if (image->progress_monitor != (MagickProgressMonitor) NULL)
2559           {
2560             MagickBooleanType
2561               proceed;
2562
2563 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2564   #pragma omp critical (MagickCore_TransformRGBImage)
2565 #endif
2566             proceed=SetImageProgress(image,TransformRGBImageTag,progress++,
2567               image->rows);
2568             if (proceed == MagickFalse)
2569               status=MagickFalse;
2570           }
2571       }
2572       image_view=DestroyCacheView(image_view);
2573       break;
2574     }
2575     case PseudoClass:
2576     {
2577       /*
2578         Convert PseudoClass image.
2579       */
2580       image_view=AcquireCacheView(image);
2581 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2582   #pragma omp parallel for schedule(dynamic,4) shared(status)
2583 #endif
2584       for (i=0; i < (ssize_t) image->colors; i++)
2585       {
2586         PixelInfo
2587           pixel;
2588
2589         register size_t
2590           blue,
2591           green,
2592           red;
2593
2594         red=ScaleQuantumToMap(image->colormap[i].red);
2595         green=ScaleQuantumToMap(image->colormap[i].green);
2596         blue=ScaleQuantumToMap(image->colormap[i].blue);
2597         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2598         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2599         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2600         switch (colorspace)
2601         {
2602           case YCCColorspace:
2603           {
2604 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2605             image->colormap[i].red=(Quantum) (QuantumRange*YCCMap[
2606               RoundToYCC(1024.0*QuantumScale*pixel.red)]);
2607             image->colormap[i].green=(Quantum) (QuantumRange*YCCMap[
2608               RoundToYCC(1024.0*QuantumScale*pixel.green)]);
2609             image->colormap[i].blue=(Quantum) (QuantumRange*YCCMap[
2610               RoundToYCC(1024.0*QuantumScale*pixel.blue)]);
2611 #endif
2612             break;
2613           }
2614           case sRGBColorspace:
2615           {
2616             if ((QuantumScale*pixel.red) <= 0.0031308)
2617               pixel.red*=12.92f;
2618             else
2619               pixel.red=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2620                 pixel.red,(1.0/2.4))-0.055);
2621             if ((QuantumScale*pixel.green) <= 0.0031308)
2622               pixel.green*=12.92f;
2623             else
2624               pixel.green=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2625                 pixel.green,(1.0/2.4))-0.055);
2626             if ((QuantumScale*pixel.blue) <= 0.0031308)
2627               pixel.blue*=12.92f;
2628             else
2629               pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2630                 pixel.blue,(1.0/2.4))-0.055);
2631           }
2632           default:
2633           {
2634             image->colormap[i].red=ScaleMapToQuantum((MagickRealType) MaxMap*
2635               QuantumScale*pixel.red);
2636             image->colormap[i].green=ScaleMapToQuantum((MagickRealType) MaxMap*
2637               QuantumScale*pixel.green);
2638             image->colormap[i].blue=ScaleMapToQuantum((MagickRealType) MaxMap*
2639               QuantumScale*pixel.blue);
2640             break;
2641           }
2642         }
2643       }
2644       image_view=DestroyCacheView(image_view);
2645       (void) SyncImage(image);
2646       break;
2647     }
2648   }
2649   /*
2650     Relinquish resources.
2651   */
2652   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2653   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2654   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2655   if (SetImageColorspace(image,RGBColorspace,exception) == MagickFalse)
2656     return(MagickFalse);
2657   return(MagickTrue);
2658 }