]> 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   if (SetImageColorspace(image,colorspace) == MagickFalse)
232     return(MagickFalse);
233   status=MagickTrue;
234   progress=0;
235   exception=(&image->exception);
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) == 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)
1182 %
1183 %  A description of each parameter follows:
1184 %
1185 %    o image: the image.
1186 %
1187 %    o colorspace: the colorspace.
1188 %
1189 */
1190 MagickExport MagickBooleanType SetImageColorspace(Image *image,
1191   const ColorspaceType colorspace)
1192 {
1193   image->colorspace=colorspace;
1194   return(MagickTrue);
1195 }
1196 \f
1197 /*
1198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1199 %                                                                             %
1200 %                                                                             %
1201 %                                                                             %
1202 %   T r a n s f o r m I m a g e C o l o r s p a c e                           %
1203 %                                                                             %
1204 %                                                                             %
1205 %                                                                             %
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1207 %
1208 %  TransformImageColorspace() transforms an image colorspace.
1209 %
1210 %  The format of the TransformImageColorspace method is:
1211 %
1212 %      MagickBooleanType TransformImageColorspace(Image *image,
1213 %        const ColorspaceType colorspace)
1214 %
1215 %  A description of each parameter follows:
1216 %
1217 %    o image: the image.
1218 %
1219 %    o colorspace: the colorspace.
1220 %
1221 */
1222 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
1223   const ColorspaceType colorspace)
1224 {
1225   MagickBooleanType
1226     status;
1227
1228   assert(image != (Image *) NULL);
1229   assert(image->signature == MagickSignature);
1230   if (image->debug != MagickFalse)
1231     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1232   if (colorspace == UndefinedColorspace)
1233     return(SetImageColorspace(image,colorspace));
1234   if (image->colorspace == colorspace)
1235     return(MagickTrue);
1236   if ((colorspace == RGBColorspace) ||
1237       (colorspace == sRGBColorspace) ||
1238       (colorspace == TransparentColorspace))
1239     return(TransformRGBImage(image,image->colorspace));
1240   status=MagickTrue;
1241   if (IsRGBColorspace(image->colorspace) == MagickFalse)
1242     status=TransformRGBImage(image,image->colorspace);
1243   if (RGBTransformImage(image,colorspace) == MagickFalse)
1244     status=MagickFalse;
1245   return(status);
1246 }
1247 \f
1248 /*
1249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1250 %                                                                             %
1251 %                                                                             %
1252 %                                                                             %
1253 +     T r a n s f o r m R G B I m a g e                                       %
1254 %                                                                             %
1255 %                                                                             %
1256 %                                                                             %
1257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1258 %
1259 %  TransformRGBImage() converts the reference image from an alternate
1260 %  colorspace to RGB.  The transformation matrices are not the standard ones:
1261 %  the weights are rescaled to normalize the range of the transformed values to
1262 %  be [0..QuantumRange].
1263 %
1264 %  The format of the TransformRGBImage method is:
1265 %
1266 %      MagickBooleanType TransformRGBImage(Image *image,
1267 %        const ColorspaceType colorspace)
1268 %
1269 %  A description of each parameter follows:
1270 %
1271 %    o image: the image.
1272 %
1273 %    o colorspace: the colorspace to transform the image to.
1274 %
1275 */
1276
1277 static double LabF2(double alpha)
1278 {
1279   double
1280     beta;
1281
1282   if (alpha > (24.0/116.0))
1283     return(alpha*alpha*alpha);
1284   beta=(108.0/841.0)*(alpha-(16.0/116.0));
1285   if (beta > 0.0)
1286     return(beta);
1287   return(0.0);
1288 }
1289
1290 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
1291   double *X,double *Y,double *Z)
1292 {
1293
1294   double
1295     x,
1296     y,
1297     z;
1298
1299   assert(X != (double *) NULL);
1300   assert(Y != (double *) NULL);
1301   assert(Z != (double *) NULL);
1302   *X=0.0;
1303   *Y=0.0;
1304   *Z=0.0;
1305   if (L <= 0.0)
1306     return;
1307   y=(100.0*L+16.0)/116.0;
1308   x=y+255.0*0.002*(a > 0.5 ? a-1.0 : a);
1309   z=y-255.0*0.005*(b > 0.5 ? b-1.0 : b);
1310   *X=D50X*LabF2(x);
1311   *Y=D50Y*LabF2(y);
1312   *Z=D50Z*LabF2(z);
1313 }
1314
1315 static inline ssize_t RoundToYCC(const MagickRealType value)
1316 {
1317   if (value <= 0.0)
1318     return(0);
1319   if (value >= 1388.0)
1320     return(1388);
1321   return((ssize_t) (value+0.5));
1322 }
1323
1324 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
1325   Quantum *red,Quantum *green,Quantum *blue)
1326 {
1327   double
1328     b,
1329     g,
1330     r;
1331
1332   /*
1333     Convert XYZ to RGB colorspace.
1334   */
1335   assert(red != (Quantum *) NULL);
1336   assert(green != (Quantum *) NULL);
1337   assert(blue != (Quantum *) NULL);
1338   r=3.2404542*x-1.5371385*y-0.4985314*z;
1339   g=(-0.9692660*x+1.8760108*y+0.0415560*z);
1340   b=0.0556434*x-0.2040259*y+1.0572252*z;
1341   if (r > 0.0031308)
1342     r=1.055*pow(r,1.0/2.4)-0.055;
1343   else
1344     r*=12.92;
1345   if (g > 0.0031308)
1346     g=1.055*pow(g,1.0/2.4)-0.055;
1347   else
1348     g*=12.92;
1349   if (b > 0.0031308)
1350     b=1.055*pow(b,1.0/2.4)-0.055;
1351   else
1352     b*=12.92;
1353   *red=RoundToQuantum((MagickRealType) QuantumRange*r);
1354   *green=RoundToQuantum((MagickRealType) QuantumRange*g);
1355   *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
1356 }
1357
1358 static inline void ConvertCMYKToRGB(PixelInfo *pixel)
1359 {
1360   pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red*
1361     (QuantumRange-pixel->black)+pixel->black);
1362   pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green*
1363     (QuantumRange-pixel->black)+pixel->black);
1364   pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue*
1365     (QuantumRange-pixel->black)+pixel->black);
1366 }
1367
1368 MagickExport MagickBooleanType TransformRGBImage(Image *image,
1369   const ColorspaceType colorspace)
1370 {
1371 #define D50X  (0.9642)
1372 #define D50Y  (1.0)
1373 #define D50Z  (0.8249)
1374 #define TransformRGBImageTag  "Transform/Image"
1375
1376 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1377   static const float
1378     YCCMap[1389] =
1379     {
1380       0.000000f, 0.000720f, 0.001441f, 0.002161f, 0.002882f, 0.003602f,
1381       0.004323f, 0.005043f, 0.005764f, 0.006484f, 0.007205f, 0.007925f,
1382       0.008646f, 0.009366f, 0.010086f, 0.010807f, 0.011527f, 0.012248f,
1383       0.012968f, 0.013689f, 0.014409f, 0.015130f, 0.015850f, 0.016571f,
1384       0.017291f, 0.018012f, 0.018732f, 0.019452f, 0.020173f, 0.020893f,
1385       0.021614f, 0.022334f, 0.023055f, 0.023775f, 0.024496f, 0.025216f,
1386       0.025937f, 0.026657f, 0.027378f, 0.028098f, 0.028818f, 0.029539f,
1387       0.030259f, 0.030980f, 0.031700f, 0.032421f, 0.033141f, 0.033862f,
1388       0.034582f, 0.035303f, 0.036023f, 0.036744f, 0.037464f, 0.038184f,
1389       0.038905f, 0.039625f, 0.040346f, 0.041066f, 0.041787f, 0.042507f,
1390       0.043228f, 0.043948f, 0.044669f, 0.045389f, 0.046110f, 0.046830f,
1391       0.047550f, 0.048271f, 0.048991f, 0.049712f, 0.050432f, 0.051153f,
1392       0.051873f, 0.052594f, 0.053314f, 0.054035f, 0.054755f, 0.055476f,
1393       0.056196f, 0.056916f, 0.057637f, 0.058357f, 0.059078f, 0.059798f,
1394       0.060519f, 0.061239f, 0.061960f, 0.062680f, 0.063401f, 0.064121f,
1395       0.064842f, 0.065562f, 0.066282f, 0.067003f, 0.067723f, 0.068444f,
1396       0.069164f, 0.069885f, 0.070605f, 0.071326f, 0.072046f, 0.072767f,
1397       0.073487f, 0.074207f, 0.074928f, 0.075648f, 0.076369f, 0.077089f,
1398       0.077810f, 0.078530f, 0.079251f, 0.079971f, 0.080692f, 0.081412f,
1399       0.082133f, 0.082853f, 0.083573f, 0.084294f, 0.085014f, 0.085735f,
1400       0.086455f, 0.087176f, 0.087896f, 0.088617f, 0.089337f, 0.090058f,
1401       0.090778f, 0.091499f, 0.092219f, 0.092939f, 0.093660f, 0.094380f,
1402       0.095101f, 0.095821f, 0.096542f, 0.097262f, 0.097983f, 0.098703f,
1403       0.099424f, 0.100144f, 0.100865f, 0.101585f, 0.102305f, 0.103026f,
1404       0.103746f, 0.104467f, 0.105187f, 0.105908f, 0.106628f, 0.107349f,
1405       0.108069f, 0.108790f, 0.109510f, 0.110231f, 0.110951f, 0.111671f,
1406       0.112392f, 0.113112f, 0.113833f, 0.114553f, 0.115274f, 0.115994f,
1407       0.116715f, 0.117435f, 0.118156f, 0.118876f, 0.119597f, 0.120317f,
1408       0.121037f, 0.121758f, 0.122478f, 0.123199f, 0.123919f, 0.124640f,
1409       0.125360f, 0.126081f, 0.126801f, 0.127522f, 0.128242f, 0.128963f,
1410       0.129683f, 0.130403f, 0.131124f, 0.131844f, 0.132565f, 0.133285f,
1411       0.134006f, 0.134726f, 0.135447f, 0.136167f, 0.136888f, 0.137608f,
1412       0.138329f, 0.139049f, 0.139769f, 0.140490f, 0.141210f, 0.141931f,
1413       0.142651f, 0.143372f, 0.144092f, 0.144813f, 0.145533f, 0.146254f,
1414       0.146974f, 0.147695f, 0.148415f, 0.149135f, 0.149856f, 0.150576f,
1415       0.151297f, 0.152017f, 0.152738f, 0.153458f, 0.154179f, 0.154899f,
1416       0.155620f, 0.156340f, 0.157061f, 0.157781f, 0.158501f, 0.159222f,
1417       0.159942f, 0.160663f, 0.161383f, 0.162104f, 0.162824f, 0.163545f,
1418       0.164265f, 0.164986f, 0.165706f, 0.166427f, 0.167147f, 0.167867f,
1419       0.168588f, 0.169308f, 0.170029f, 0.170749f, 0.171470f, 0.172190f,
1420       0.172911f, 0.173631f, 0.174352f, 0.175072f, 0.175793f, 0.176513f,
1421       0.177233f, 0.177954f, 0.178674f, 0.179395f, 0.180115f, 0.180836f,
1422       0.181556f, 0.182277f, 0.182997f, 0.183718f, 0.184438f, 0.185159f,
1423       0.185879f, 0.186599f, 0.187320f, 0.188040f, 0.188761f, 0.189481f,
1424       0.190202f, 0.190922f, 0.191643f, 0.192363f, 0.193084f, 0.193804f,
1425       0.194524f, 0.195245f, 0.195965f, 0.196686f, 0.197406f, 0.198127f,
1426       0.198847f, 0.199568f, 0.200288f, 0.201009f, 0.201729f, 0.202450f,
1427       0.203170f, 0.203890f, 0.204611f, 0.205331f, 0.206052f, 0.206772f,
1428       0.207493f, 0.208213f, 0.208934f, 0.209654f, 0.210375f, 0.211095f,
1429       0.211816f, 0.212536f, 0.213256f, 0.213977f, 0.214697f, 0.215418f,
1430       0.216138f, 0.216859f, 0.217579f, 0.218300f, 0.219020f, 0.219741f,
1431       0.220461f, 0.221182f, 0.221902f, 0.222622f, 0.223343f, 0.224063f,
1432       0.224784f, 0.225504f, 0.226225f, 0.226945f, 0.227666f, 0.228386f,
1433       0.229107f, 0.229827f, 0.230548f, 0.231268f, 0.231988f, 0.232709f,
1434       0.233429f, 0.234150f, 0.234870f, 0.235591f, 0.236311f, 0.237032f,
1435       0.237752f, 0.238473f, 0.239193f, 0.239914f, 0.240634f, 0.241354f,
1436       0.242075f, 0.242795f, 0.243516f, 0.244236f, 0.244957f, 0.245677f,
1437       0.246398f, 0.247118f, 0.247839f, 0.248559f, 0.249280f, 0.250000f,
1438       0.250720f, 0.251441f, 0.252161f, 0.252882f, 0.253602f, 0.254323f,
1439       0.255043f, 0.255764f, 0.256484f, 0.257205f, 0.257925f, 0.258646f,
1440       0.259366f, 0.260086f, 0.260807f, 0.261527f, 0.262248f, 0.262968f,
1441       0.263689f, 0.264409f, 0.265130f, 0.265850f, 0.266571f, 0.267291f,
1442       0.268012f, 0.268732f, 0.269452f, 0.270173f, 0.270893f, 0.271614f,
1443       0.272334f, 0.273055f, 0.273775f, 0.274496f, 0.275216f, 0.275937f,
1444       0.276657f, 0.277378f, 0.278098f, 0.278818f, 0.279539f, 0.280259f,
1445       0.280980f, 0.281700f, 0.282421f, 0.283141f, 0.283862f, 0.284582f,
1446       0.285303f, 0.286023f, 0.286744f, 0.287464f, 0.288184f, 0.288905f,
1447       0.289625f, 0.290346f, 0.291066f, 0.291787f, 0.292507f, 0.293228f,
1448       0.293948f, 0.294669f, 0.295389f, 0.296109f, 0.296830f, 0.297550f,
1449       0.298271f, 0.298991f, 0.299712f, 0.300432f, 0.301153f, 0.301873f,
1450       0.302594f, 0.303314f, 0.304035f, 0.304755f, 0.305476f, 0.306196f,
1451       0.306916f, 0.307637f, 0.308357f, 0.309078f, 0.309798f, 0.310519f,
1452       0.311239f, 0.311960f, 0.312680f, 0.313401f, 0.314121f, 0.314842f,
1453       0.315562f, 0.316282f, 0.317003f, 0.317723f, 0.318444f, 0.319164f,
1454       0.319885f, 0.320605f, 0.321326f, 0.322046f, 0.322767f, 0.323487f,
1455       0.324207f, 0.324928f, 0.325648f, 0.326369f, 0.327089f, 0.327810f,
1456       0.328530f, 0.329251f, 0.329971f, 0.330692f, 0.331412f, 0.332133f,
1457       0.332853f, 0.333573f, 0.334294f, 0.335014f, 0.335735f, 0.336455f,
1458       0.337176f, 0.337896f, 0.338617f, 0.339337f, 0.340058f, 0.340778f,
1459       0.341499f, 0.342219f, 0.342939f, 0.343660f, 0.344380f, 0.345101f,
1460       0.345821f, 0.346542f, 0.347262f, 0.347983f, 0.348703f, 0.349424f,
1461       0.350144f, 0.350865f, 0.351585f, 0.352305f, 0.353026f, 0.353746f,
1462       0.354467f, 0.355187f, 0.355908f, 0.356628f, 0.357349f, 0.358069f,
1463       0.358790f, 0.359510f, 0.360231f, 0.360951f, 0.361671f, 0.362392f,
1464       0.363112f, 0.363833f, 0.364553f, 0.365274f, 0.365994f, 0.366715f,
1465       0.367435f, 0.368156f, 0.368876f, 0.369597f, 0.370317f, 0.371037f,
1466       0.371758f, 0.372478f, 0.373199f, 0.373919f, 0.374640f, 0.375360f,
1467       0.376081f, 0.376801f, 0.377522f, 0.378242f, 0.378963f, 0.379683f,
1468       0.380403f, 0.381124f, 0.381844f, 0.382565f, 0.383285f, 0.384006f,
1469       0.384726f, 0.385447f, 0.386167f, 0.386888f, 0.387608f, 0.388329f,
1470       0.389049f, 0.389769f, 0.390490f, 0.391210f, 0.391931f, 0.392651f,
1471       0.393372f, 0.394092f, 0.394813f, 0.395533f, 0.396254f, 0.396974f,
1472       0.397695f, 0.398415f, 0.399135f, 0.399856f, 0.400576f, 0.401297f,
1473       0.402017f, 0.402738f, 0.403458f, 0.404179f, 0.404899f, 0.405620f,
1474       0.406340f, 0.407061f, 0.407781f, 0.408501f, 0.409222f, 0.409942f,
1475       0.410663f, 0.411383f, 0.412104f, 0.412824f, 0.413545f, 0.414265f,
1476       0.414986f, 0.415706f, 0.416427f, 0.417147f, 0.417867f, 0.418588f,
1477       0.419308f, 0.420029f, 0.420749f, 0.421470f, 0.422190f, 0.422911f,
1478       0.423631f, 0.424352f, 0.425072f, 0.425793f, 0.426513f, 0.427233f,
1479       0.427954f, 0.428674f, 0.429395f, 0.430115f, 0.430836f, 0.431556f,
1480       0.432277f, 0.432997f, 0.433718f, 0.434438f, 0.435158f, 0.435879f,
1481       0.436599f, 0.437320f, 0.438040f, 0.438761f, 0.439481f, 0.440202f,
1482       0.440922f, 0.441643f, 0.442363f, 0.443084f, 0.443804f, 0.444524f,
1483       0.445245f, 0.445965f, 0.446686f, 0.447406f, 0.448127f, 0.448847f,
1484       0.449568f, 0.450288f, 0.451009f, 0.451729f, 0.452450f, 0.453170f,
1485       0.453891f, 0.454611f, 0.455331f, 0.456052f, 0.456772f, 0.457493f,
1486       0.458213f, 0.458934f, 0.459654f, 0.460375f, 0.461095f, 0.461816f,
1487       0.462536f, 0.463256f, 0.463977f, 0.464697f, 0.465418f, 0.466138f,
1488       0.466859f, 0.467579f, 0.468300f, 0.469020f, 0.469741f, 0.470461f,
1489       0.471182f, 0.471902f, 0.472622f, 0.473343f, 0.474063f, 0.474784f,
1490       0.475504f, 0.476225f, 0.476945f, 0.477666f, 0.478386f, 0.479107f,
1491       0.479827f, 0.480548f, 0.481268f, 0.481988f, 0.482709f, 0.483429f,
1492       0.484150f, 0.484870f, 0.485591f, 0.486311f, 0.487032f, 0.487752f,
1493       0.488473f, 0.489193f, 0.489914f, 0.490634f, 0.491354f, 0.492075f,
1494       0.492795f, 0.493516f, 0.494236f, 0.494957f, 0.495677f, 0.496398f,
1495       0.497118f, 0.497839f, 0.498559f, 0.499280f, 0.500000f, 0.500720f,
1496       0.501441f, 0.502161f, 0.502882f, 0.503602f, 0.504323f, 0.505043f,
1497       0.505764f, 0.506484f, 0.507205f, 0.507925f, 0.508646f, 0.509366f,
1498       0.510086f, 0.510807f, 0.511527f, 0.512248f, 0.512968f, 0.513689f,
1499       0.514409f, 0.515130f, 0.515850f, 0.516571f, 0.517291f, 0.518012f,
1500       0.518732f, 0.519452f, 0.520173f, 0.520893f, 0.521614f, 0.522334f,
1501       0.523055f, 0.523775f, 0.524496f, 0.525216f, 0.525937f, 0.526657f,
1502       0.527378f, 0.528098f, 0.528818f, 0.529539f, 0.530259f, 0.530980f,
1503       0.531700f, 0.532421f, 0.533141f, 0.533862f, 0.534582f, 0.535303f,
1504       0.536023f, 0.536744f, 0.537464f, 0.538184f, 0.538905f, 0.539625f,
1505       0.540346f, 0.541066f, 0.541787f, 0.542507f, 0.543228f, 0.543948f,
1506       0.544669f, 0.545389f, 0.546109f, 0.546830f, 0.547550f, 0.548271f,
1507       0.548991f, 0.549712f, 0.550432f, 0.551153f, 0.551873f, 0.552594f,
1508       0.553314f, 0.554035f, 0.554755f, 0.555476f, 0.556196f, 0.556916f,
1509       0.557637f, 0.558357f, 0.559078f, 0.559798f, 0.560519f, 0.561239f,
1510       0.561960f, 0.562680f, 0.563401f, 0.564121f, 0.564842f, 0.565562f,
1511       0.566282f, 0.567003f, 0.567723f, 0.568444f, 0.569164f, 0.569885f,
1512       0.570605f, 0.571326f, 0.572046f, 0.572767f, 0.573487f, 0.574207f,
1513       0.574928f, 0.575648f, 0.576369f, 0.577089f, 0.577810f, 0.578530f,
1514       0.579251f, 0.579971f, 0.580692f, 0.581412f, 0.582133f, 0.582853f,
1515       0.583573f, 0.584294f, 0.585014f, 0.585735f, 0.586455f, 0.587176f,
1516       0.587896f, 0.588617f, 0.589337f, 0.590058f, 0.590778f, 0.591499f,
1517       0.592219f, 0.592939f, 0.593660f, 0.594380f, 0.595101f, 0.595821f,
1518       0.596542f, 0.597262f, 0.597983f, 0.598703f, 0.599424f, 0.600144f,
1519       0.600865f, 0.601585f, 0.602305f, 0.603026f, 0.603746f, 0.604467f,
1520       0.605187f, 0.605908f, 0.606628f, 0.607349f, 0.608069f, 0.608790f,
1521       0.609510f, 0.610231f, 0.610951f, 0.611671f, 0.612392f, 0.613112f,
1522       0.613833f, 0.614553f, 0.615274f, 0.615994f, 0.616715f, 0.617435f,
1523       0.618156f, 0.618876f, 0.619597f, 0.620317f, 0.621037f, 0.621758f,
1524       0.622478f, 0.623199f, 0.623919f, 0.624640f, 0.625360f, 0.626081f,
1525       0.626801f, 0.627522f, 0.628242f, 0.628963f, 0.629683f, 0.630403f,
1526       0.631124f, 0.631844f, 0.632565f, 0.633285f, 0.634006f, 0.634726f,
1527       0.635447f, 0.636167f, 0.636888f, 0.637608f, 0.638329f, 0.639049f,
1528       0.639769f, 0.640490f, 0.641210f, 0.641931f, 0.642651f, 0.643372f,
1529       0.644092f, 0.644813f, 0.645533f, 0.646254f, 0.646974f, 0.647695f,
1530       0.648415f, 0.649135f, 0.649856f, 0.650576f, 0.651297f, 0.652017f,
1531       0.652738f, 0.653458f, 0.654179f, 0.654899f, 0.655620f, 0.656340f,
1532       0.657061f, 0.657781f, 0.658501f, 0.659222f, 0.659942f, 0.660663f,
1533       0.661383f, 0.662104f, 0.662824f, 0.663545f, 0.664265f, 0.664986f,
1534       0.665706f, 0.666427f, 0.667147f, 0.667867f, 0.668588f, 0.669308f,
1535       0.670029f, 0.670749f, 0.671470f, 0.672190f, 0.672911f, 0.673631f,
1536       0.674352f, 0.675072f, 0.675793f, 0.676513f, 0.677233f, 0.677954f,
1537       0.678674f, 0.679395f, 0.680115f, 0.680836f, 0.681556f, 0.682277f,
1538       0.682997f, 0.683718f, 0.684438f, 0.685158f, 0.685879f, 0.686599f,
1539       0.687320f, 0.688040f, 0.688761f, 0.689481f, 0.690202f, 0.690922f,
1540       0.691643f, 0.692363f, 0.693084f, 0.693804f, 0.694524f, 0.695245f,
1541       0.695965f, 0.696686f, 0.697406f, 0.698127f, 0.698847f, 0.699568f,
1542       0.700288f, 0.701009f, 0.701729f, 0.702450f, 0.703170f, 0.703891f,
1543       0.704611f, 0.705331f, 0.706052f, 0.706772f, 0.707493f, 0.708213f,
1544       0.708934f, 0.709654f, 0.710375f, 0.711095f, 0.711816f, 0.712536f,
1545       0.713256f, 0.713977f, 0.714697f, 0.715418f, 0.716138f, 0.716859f,
1546       0.717579f, 0.718300f, 0.719020f, 0.719741f, 0.720461f, 0.721182f,
1547       0.721902f, 0.722622f, 0.723343f, 0.724063f, 0.724784f, 0.725504f,
1548       0.726225f, 0.726945f, 0.727666f, 0.728386f, 0.729107f, 0.729827f,
1549       0.730548f, 0.731268f, 0.731988f, 0.732709f, 0.733429f, 0.734150f,
1550       0.734870f, 0.735591f, 0.736311f, 0.737032f, 0.737752f, 0.738473f,
1551       0.739193f, 0.739914f, 0.740634f, 0.741354f, 0.742075f, 0.742795f,
1552       0.743516f, 0.744236f, 0.744957f, 0.745677f, 0.746398f, 0.747118f,
1553       0.747839f, 0.748559f, 0.749280f, 0.750000f, 0.750720f, 0.751441f,
1554       0.752161f, 0.752882f, 0.753602f, 0.754323f, 0.755043f, 0.755764f,
1555       0.756484f, 0.757205f, 0.757925f, 0.758646f, 0.759366f, 0.760086f,
1556       0.760807f, 0.761527f, 0.762248f, 0.762968f, 0.763689f, 0.764409f,
1557       0.765130f, 0.765850f, 0.766571f, 0.767291f, 0.768012f, 0.768732f,
1558       0.769452f, 0.770173f, 0.770893f, 0.771614f, 0.772334f, 0.773055f,
1559       0.773775f, 0.774496f, 0.775216f, 0.775937f, 0.776657f, 0.777378f,
1560       0.778098f, 0.778818f, 0.779539f, 0.780259f, 0.780980f, 0.781700f,
1561       0.782421f, 0.783141f, 0.783862f, 0.784582f, 0.785303f, 0.786023f,
1562       0.786744f, 0.787464f, 0.788184f, 0.788905f, 0.789625f, 0.790346f,
1563       0.791066f, 0.791787f, 0.792507f, 0.793228f, 0.793948f, 0.794669f,
1564       0.795389f, 0.796109f, 0.796830f, 0.797550f, 0.798271f, 0.798991f,
1565       0.799712f, 0.800432f, 0.801153f, 0.801873f, 0.802594f, 0.803314f,
1566       0.804035f, 0.804755f, 0.805476f, 0.806196f, 0.806916f, 0.807637f,
1567       0.808357f, 0.809078f, 0.809798f, 0.810519f, 0.811239f, 0.811960f,
1568       0.812680f, 0.813401f, 0.814121f, 0.814842f, 0.815562f, 0.816282f,
1569       0.817003f, 0.817723f, 0.818444f, 0.819164f, 0.819885f, 0.820605f,
1570       0.821326f, 0.822046f, 0.822767f, 0.823487f, 0.824207f, 0.824928f,
1571       0.825648f, 0.826369f, 0.827089f, 0.827810f, 0.828530f, 0.829251f,
1572       0.829971f, 0.830692f, 0.831412f, 0.832133f, 0.832853f, 0.833573f,
1573       0.834294f, 0.835014f, 0.835735f, 0.836455f, 0.837176f, 0.837896f,
1574       0.838617f, 0.839337f, 0.840058f, 0.840778f, 0.841499f, 0.842219f,
1575       0.842939f, 0.843660f, 0.844380f, 0.845101f, 0.845821f, 0.846542f,
1576       0.847262f, 0.847983f, 0.848703f, 0.849424f, 0.850144f, 0.850865f,
1577       0.851585f, 0.852305f, 0.853026f, 0.853746f, 0.854467f, 0.855187f,
1578       0.855908f, 0.856628f, 0.857349f, 0.858069f, 0.858790f, 0.859510f,
1579       0.860231f, 0.860951f, 0.861671f, 0.862392f, 0.863112f, 0.863833f,
1580       0.864553f, 0.865274f, 0.865994f, 0.866715f, 0.867435f, 0.868156f,
1581       0.868876f, 0.869597f, 0.870317f, 0.871037f, 0.871758f, 0.872478f,
1582       0.873199f, 0.873919f, 0.874640f, 0.875360f, 0.876081f, 0.876801f,
1583       0.877522f, 0.878242f, 0.878963f, 0.879683f, 0.880403f, 0.881124f,
1584       0.881844f, 0.882565f, 0.883285f, 0.884006f, 0.884726f, 0.885447f,
1585       0.886167f, 0.886888f, 0.887608f, 0.888329f, 0.889049f, 0.889769f,
1586       0.890490f, 0.891210f, 0.891931f, 0.892651f, 0.893372f, 0.894092f,
1587       0.894813f, 0.895533f, 0.896254f, 0.896974f, 0.897695f, 0.898415f,
1588       0.899135f, 0.899856f, 0.900576f, 0.901297f, 0.902017f, 0.902738f,
1589       0.903458f, 0.904179f, 0.904899f, 0.905620f, 0.906340f, 0.907061f,
1590       0.907781f, 0.908501f, 0.909222f, 0.909942f, 0.910663f, 0.911383f,
1591       0.912104f, 0.912824f, 0.913545f, 0.914265f, 0.914986f, 0.915706f,
1592       0.916427f, 0.917147f, 0.917867f, 0.918588f, 0.919308f, 0.920029f,
1593       0.920749f, 0.921470f, 0.922190f, 0.922911f, 0.923631f, 0.924352f,
1594       0.925072f, 0.925793f, 0.926513f, 0.927233f, 0.927954f, 0.928674f,
1595       0.929395f, 0.930115f, 0.930836f, 0.931556f, 0.932277f, 0.932997f,
1596       0.933718f, 0.934438f, 0.935158f, 0.935879f, 0.936599f, 0.937320f,
1597       0.938040f, 0.938761f, 0.939481f, 0.940202f, 0.940922f, 0.941643f,
1598       0.942363f, 0.943084f, 0.943804f, 0.944524f, 0.945245f, 0.945965f,
1599       0.946686f, 0.947406f, 0.948127f, 0.948847f, 0.949568f, 0.950288f,
1600       0.951009f, 0.951729f, 0.952450f, 0.953170f, 0.953891f, 0.954611f,
1601       0.955331f, 0.956052f, 0.956772f, 0.957493f, 0.958213f, 0.958934f,
1602       0.959654f, 0.960375f, 0.961095f, 0.961816f, 0.962536f, 0.963256f,
1603       0.963977f, 0.964697f, 0.965418f, 0.966138f, 0.966859f, 0.967579f,
1604       0.968300f, 0.969020f, 0.969741f, 0.970461f, 0.971182f, 0.971902f,
1605       0.972622f, 0.973343f, 0.974063f, 0.974784f, 0.975504f, 0.976225f,
1606       0.976945f, 0.977666f, 0.978386f, 0.979107f, 0.979827f, 0.980548f,
1607       0.981268f, 0.981988f, 0.982709f, 0.983429f, 0.984150f, 0.984870f,
1608       0.985591f, 0.986311f, 0.987032f, 0.987752f, 0.988473f, 0.989193f,
1609       0.989914f, 0.990634f, 0.991354f, 0.992075f, 0.992795f, 0.993516f,
1610       0.994236f, 0.994957f, 0.995677f, 0.996398f, 0.997118f, 0.997839f,
1611       0.998559f, 0.999280f, 1.000000f
1612     };
1613 #endif
1614
1615   CacheView
1616     *image_view;
1617
1618   ExceptionInfo
1619     *exception;
1620
1621   MagickBooleanType
1622     status;
1623
1624   MagickOffsetType
1625     progress;
1626
1627   register ssize_t
1628     i;
1629
1630   ssize_t
1631     y;
1632
1633   TransformPacket
1634     *y_map,
1635     *x_map,
1636     *z_map;
1637
1638   assert(image != (Image *) NULL);
1639   assert(image->signature == MagickSignature);
1640   if (image->debug != MagickFalse)
1641     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1642   switch (colorspace)
1643   {
1644     case GRAYColorspace:
1645     case Rec601LumaColorspace:
1646     case Rec709LumaColorspace:
1647     case RGBColorspace:
1648     case TransparentColorspace:
1649     case UndefinedColorspace:
1650       return(MagickTrue);
1651     default:
1652       break;
1653   }
1654   status=MagickTrue;
1655   progress=0;
1656   exception=(&image->exception);
1657   switch (colorspace)
1658   {
1659     case CMYColorspace:
1660     {
1661       /*
1662         Transform image from CMY to RGB.
1663       */
1664       if (image->storage_class == PseudoClass)
1665         {
1666           if (SyncImage(image) == MagickFalse)
1667             return(MagickFalse);
1668           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1669             return(MagickFalse);
1670         }
1671       image_view=AcquireCacheView(image);
1672 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1673   #pragma omp parallel for schedule(dynamic,4) shared(status)
1674 #endif
1675       for (y=0; y < (ssize_t) image->rows; y++)
1676       {
1677         MagickBooleanType
1678           sync;
1679
1680         register ssize_t
1681           x;
1682
1683         register Quantum
1684           *restrict q;
1685
1686         if (status == MagickFalse)
1687           continue;
1688         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1689           exception);
1690         if (q == (const Quantum *) NULL)
1691           {
1692             status=MagickFalse;
1693             continue;
1694           }
1695         for (x=0; x < (ssize_t) image->columns; x++)
1696         {
1697           SetPixelRed(image,ClampToQuantum((MagickRealType) (QuantumRange-
1698             GetPixelRed(image,q))),q);
1699           SetPixelGreen(image,ClampToQuantum((MagickRealType) (QuantumRange-
1700             GetPixelGreen(image,q))),q);
1701           SetPixelBlue(image,ClampToQuantum((MagickRealType) (QuantumRange-
1702             GetPixelBlue(image,q))),q);
1703           q+=GetPixelChannels(image);
1704         }
1705         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1706         if (sync == MagickFalse)
1707           status=MagickFalse;
1708       }
1709       image_view=DestroyCacheView(image_view);
1710       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1711         return(MagickFalse);
1712       return(status);
1713     }
1714     case CMYKColorspace:
1715     {
1716       PixelInfo
1717         zero;
1718
1719       /*
1720         Transform image from CMYK to RGB.
1721       */
1722       if (image->storage_class == PseudoClass)
1723         {
1724           if (SyncImage(image) == MagickFalse)
1725             return(MagickFalse);
1726           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1727             return(MagickFalse);
1728         }
1729       GetPixelInfo(image,&zero);
1730       image_view=AcquireCacheView(image);
1731 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1732   #pragma omp parallel for schedule(dynamic,4) shared(status)
1733 #endif
1734       for (y=0; y < (ssize_t) image->rows; y++)
1735       {
1736         MagickBooleanType
1737           sync;
1738
1739         PixelInfo
1740           pixel;
1741
1742         register ssize_t
1743           x;
1744
1745         register Quantum
1746           *restrict q;
1747
1748         if (status == MagickFalse)
1749           continue;
1750         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1751           exception);
1752         if (q == (const Quantum *) NULL)
1753           {
1754             status=MagickFalse;
1755             continue;
1756           }
1757         pixel=zero;
1758         for (x=0; x < (ssize_t) image->columns; x++)
1759         {
1760           SetPixelInfo(image,q,&pixel);
1761           ConvertCMYKToRGB(&pixel);
1762           SetPixelPixelInfo(image,&pixel,q);
1763           q+=GetPixelChannels(image);
1764         }
1765         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1766         if (sync == MagickFalse)
1767           status=MagickFalse;
1768       }
1769       image_view=DestroyCacheView(image_view);
1770       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1771         return(MagickFalse);
1772       return(status);
1773     }
1774     case HSBColorspace:
1775     {
1776       /*
1777         Transform image from HSB to RGB.
1778       */
1779       if (image->storage_class == PseudoClass)
1780         {
1781           if (SyncImage(image) == MagickFalse)
1782             return(MagickFalse);
1783           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1784             return(MagickFalse);
1785         }
1786       image_view=AcquireCacheView(image);
1787 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1788   #pragma omp parallel for schedule(dynamic,4) shared(status)
1789 #endif
1790       for (y=0; y < (ssize_t) image->rows; y++)
1791       {
1792         double
1793           brightness,
1794           hue,
1795           saturation;
1796
1797         MagickBooleanType
1798           sync;
1799
1800         register ssize_t
1801           x;
1802
1803         register Quantum
1804           *restrict q;
1805
1806         if (status == MagickFalse)
1807           continue;
1808         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1809           exception);
1810         if (q == (const Quantum *) NULL)
1811           {
1812             status=MagickFalse;
1813             continue;
1814           }
1815         for (x=0; x < (ssize_t) image->columns; x++)
1816         {
1817           Quantum
1818             blue,
1819             green,
1820             red;
1821
1822           hue=(double) (QuantumScale*GetPixelRed(image,q));
1823           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
1824           brightness=(double) (QuantumScale*GetPixelBlue(image,q));
1825           ConvertHSBToRGB(hue,saturation,brightness,&red,&green,&blue);
1826           SetPixelRed(image,red,q);
1827           SetPixelGreen(image,green,q);
1828           SetPixelBlue(image,blue,q);
1829           q+=GetPixelChannels(image);
1830         }
1831         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1832         if (sync == MagickFalse)
1833           status=MagickFalse;
1834       }
1835       image_view=DestroyCacheView(image_view);
1836       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1837         return(MagickFalse);
1838       return(status);
1839     }
1840     case HSLColorspace:
1841     {
1842       /*
1843         Transform image from HSL to RGB.
1844       */
1845       if (image->storage_class == PseudoClass)
1846         {
1847           if (SyncImage(image) == MagickFalse)
1848             return(MagickFalse);
1849           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1850             return(MagickFalse);
1851         }
1852       image_view=AcquireCacheView(image);
1853 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1854   #pragma omp parallel for schedule(dynamic,4) shared(status)
1855 #endif
1856       for (y=0; y < (ssize_t) image->rows; y++)
1857       {
1858         double
1859           hue,
1860           lightness,
1861           saturation;
1862
1863         MagickBooleanType
1864           sync;
1865
1866         register ssize_t
1867           x;
1868
1869         register Quantum
1870           *restrict q;
1871
1872         if (status == MagickFalse)
1873           continue;
1874         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1875           exception);
1876         if (q == (const Quantum *) NULL)
1877           {
1878             status=MagickFalse;
1879             continue;
1880           }
1881         for (x=0; x < (ssize_t) image->columns; x++)
1882         {
1883           Quantum
1884             blue,
1885             green,
1886             red;
1887
1888           hue=(double) (QuantumScale*GetPixelRed(image,q));
1889           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
1890           lightness=(double) (QuantumScale*GetPixelBlue(image,q));
1891           ConvertHSLToRGB(hue,saturation,lightness,&red,&green,&blue);
1892           SetPixelRed(image,red,q);
1893           SetPixelGreen(image,green,q);
1894           SetPixelBlue(image,blue,q);
1895           q+=GetPixelChannels(image);
1896         }
1897         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1898         if (sync == MagickFalse)
1899           status=MagickFalse;
1900       }
1901       image_view=DestroyCacheView(image_view);
1902       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1903         return(MagickFalse);
1904       return(status);
1905     }
1906     case HWBColorspace:
1907     {
1908       /*
1909         Transform image from HWB to RGB.
1910       */
1911       if (image->storage_class == PseudoClass)
1912         {
1913           if (SyncImage(image) == MagickFalse)
1914             return(MagickFalse);
1915           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1916             return(MagickFalse);
1917         }
1918       image_view=AcquireCacheView(image);
1919 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1920   #pragma omp parallel for schedule(dynamic,4) shared(status)
1921 #endif
1922       for (y=0; y < (ssize_t) image->rows; y++)
1923       {
1924         double
1925           blackness,
1926           hue,
1927           whiteness;
1928
1929         MagickBooleanType
1930           sync;
1931
1932         register ssize_t
1933           x;
1934
1935         register Quantum
1936           *restrict q;
1937
1938         if (status == MagickFalse)
1939           continue;
1940         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1941           exception);
1942         if (q == (const Quantum *) NULL)
1943           {
1944             status=MagickFalse;
1945             continue;
1946           }
1947         for (x=0; x < (ssize_t) image->columns; x++)
1948         {
1949           Quantum
1950             blue,
1951             green,
1952             red;
1953
1954           hue=(double) (QuantumScale*GetPixelRed(image,q));
1955           whiteness=(double) (QuantumScale*GetPixelGreen(image,q));
1956           blackness=(double) (QuantumScale*GetPixelBlue(image,q));
1957           ConvertHWBToRGB(hue,whiteness,blackness,&red,&green,&blue);
1958           SetPixelRed(image,red,q);
1959           SetPixelGreen(image,green,q);
1960           SetPixelBlue(image,blue,q);
1961           q+=GetPixelChannels(image);
1962         }
1963         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1964         if (sync == MagickFalse)
1965           status=MagickFalse;
1966       }
1967       image_view=DestroyCacheView(image_view);
1968       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1969         return(MagickFalse);
1970       return(status);
1971     }
1972     case LabColorspace:
1973     {
1974       /*
1975         Transform image from Lab to RGB.
1976       */
1977       if (image->storage_class == PseudoClass)
1978         {
1979           if (SyncImage(image) == MagickFalse)
1980             return(MagickFalse);
1981           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1982             return(MagickFalse);
1983         }
1984       image_view=AcquireCacheView(image);
1985 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1986   #pragma omp parallel for schedule(dynamic,4) shared(status)
1987 #endif
1988       for (y=0; y < (ssize_t) image->rows; y++)
1989       {
1990         double
1991           a,
1992           b,
1993           L,
1994           X,
1995           Y,
1996           Z;
1997
1998         MagickBooleanType
1999           sync;
2000
2001         register ssize_t
2002           x;
2003
2004         register Quantum
2005           *restrict q;
2006
2007         if (status == MagickFalse)
2008           continue;
2009         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2010           exception);
2011         if (q == (const Quantum *) NULL)
2012           {
2013             status=MagickFalse;
2014             continue;
2015           }
2016         X=0.0;
2017         Y=0.0;
2018         Z=0.0;
2019         for (x=0; x < (ssize_t) image->columns; x++)
2020         {
2021           Quantum
2022             blue,
2023             green,
2024             red;
2025
2026           L=QuantumScale*GetPixelRed(image,q);
2027           a=QuantumScale*GetPixelGreen(image,q);
2028           b=QuantumScale*GetPixelBlue(image,q);
2029           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
2030           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2031           SetPixelRed(image,red,q);
2032           SetPixelGreen(image,green,q);
2033           SetPixelBlue(image,blue,q);
2034           q+=GetPixelChannels(image);
2035         }
2036         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2037         if (sync == MagickFalse)
2038           status=MagickFalse;
2039       }
2040       image_view=DestroyCacheView(image_view);
2041       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
2042         return(MagickFalse);
2043       return(status);
2044     }
2045     case LogColorspace:
2046     {
2047       const char
2048         *value;
2049
2050       double
2051         black,
2052         density,
2053         film_gamma,
2054         gamma,
2055         reference_black,
2056         reference_white;
2057
2058       Quantum
2059         *logmap;
2060
2061       /*
2062         Transform Log to RGB colorspace.
2063       */
2064       density=DisplayGamma;
2065       gamma=DisplayGamma;
2066       value=GetImageProperty(image,"gamma");
2067       if (value != (const char *) NULL)
2068         gamma=1.0/InterpretLocaleValue(value,(char **) NULL) != 0.0 ?
2069           InterpretLocaleValue(value,(char **) NULL) : 1.0;
2070       film_gamma=FilmGamma;
2071       value=GetImageProperty(image,"film-gamma");
2072       if (value != (const char *) NULL)
2073         film_gamma=InterpretLocaleValue(value,(char **) NULL);
2074       reference_black=ReferenceBlack;
2075       value=GetImageProperty(image,"reference-black");
2076       if (value != (const char *) NULL)
2077         reference_black=InterpretLocaleValue(value,(char **) NULL);
2078       reference_white=ReferenceWhite;
2079       value=GetImageProperty(image,"reference-white");
2080       if (value != (const char *) NULL)
2081         reference_white=InterpretLocaleValue(value,(char **) NULL);
2082       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2083         sizeof(*logmap));
2084       if (logmap == (Quantum *) NULL)
2085         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2086           image->filename);
2087       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
2088         0.002/film_gamma);
2089       for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
2090         logmap[i]=(Quantum) 0;
2091       for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0); i++)
2092         logmap[i]=ClampToQuantum((MagickRealType) QuantumRange/(1.0-black)*
2093           (pow(10.0,(1024.0*i/MaxMap-reference_white)*
2094           (gamma/density)*0.002/film_gamma)-black));
2095       for ( ; i <= (ssize_t) MaxMap; i++)
2096         logmap[i]=(Quantum) QuantumRange;
2097       if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2098         return(MagickFalse);
2099       image_view=AcquireCacheView(image);
2100 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2101   #pragma omp parallel for schedule(dynamic,4) shared(status)
2102 #endif
2103       for (y=0; y < (ssize_t) image->rows; y++)
2104       {
2105         MagickBooleanType
2106           sync;
2107
2108         register ssize_t
2109           x;
2110
2111         register Quantum
2112           *restrict q;
2113
2114         if (status == MagickFalse)
2115           continue;
2116         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2117           exception);
2118         if (q == (const Quantum *) NULL)
2119           {
2120             status=MagickFalse;
2121             continue;
2122           }
2123         for (x=(ssize_t) image->columns; x != 0; x--)
2124         {
2125           SetPixelRed(image,logmap[ScaleQuantumToMap(
2126             GetPixelRed(image,q))],q);
2127           SetPixelGreen(image,logmap[ScaleQuantumToMap(
2128             GetPixelGreen(image,q))],q);
2129           SetPixelBlue(image,logmap[ScaleQuantumToMap(
2130             GetPixelBlue(image,q))],q);
2131           q+=GetPixelChannels(image);
2132         }
2133         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2134         if (sync == MagickFalse)
2135           status=MagickFalse;
2136       }
2137       image_view=DestroyCacheView(image_view);
2138       logmap=(Quantum *) RelinquishMagickMemory(logmap);
2139       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
2140         return(MagickFalse);
2141       return(status);
2142     }
2143     default:
2144       break;
2145   }
2146   /*
2147     Allocate the tables.
2148   */
2149   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2150     sizeof(*x_map));
2151   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2152     sizeof(*y_map));
2153   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2154     sizeof(*z_map));
2155   if ((x_map == (TransformPacket *) NULL) ||
2156       (y_map == (TransformPacket *) NULL) ||
2157       (z_map == (TransformPacket *) NULL))
2158     {
2159       if (z_map != (TransformPacket *) NULL)
2160         z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2161       if (y_map != (TransformPacket *) NULL)
2162         y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2163       if (x_map != (TransformPacket *) NULL)
2164         x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2165       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2166         image->filename);
2167     }
2168   switch (colorspace)
2169   {
2170     case OHTAColorspace:
2171     {
2172       /*
2173         Initialize OHTA tables:
2174
2175           R = I1+1.00000*I2-0.66668*I3
2176           G = I1+0.00000*I2+1.33333*I3
2177           B = I1-1.00000*I2-0.66668*I3
2178
2179         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2180         through QuantumRange.
2181       */
2182 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2183   #pragma omp parallel for schedule(dynamic,4)
2184 #endif
2185       for (i=0; i <= (ssize_t) MaxMap; i++)
2186       {
2187         x_map[i].x=(MagickRealType) i;
2188         y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType)
2189           MaxMap);
2190         z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
2191           MaxMap);
2192         x_map[i].y=(MagickRealType) i;
2193         y_map[i].y=0.000000f;
2194         z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType)
2195           MaxMap);
2196         x_map[i].z=(MagickRealType) i;
2197         y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType)
2198           MaxMap);
2199         z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
2200           MaxMap);
2201       }
2202       break;
2203     }
2204     case Rec601YCbCrColorspace:
2205     case YCbCrColorspace:
2206     {
2207       /*
2208         Initialize YCbCr tables:
2209
2210           R = Y            +1.402000*Cr
2211           G = Y-0.344136*Cb-0.714136*Cr
2212           B = Y+1.772000*Cb
2213
2214         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
2215         through QuantumRange.
2216       */
2217 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2218   #pragma omp parallel for schedule(dynamic,4)
2219 #endif
2220       for (i=0; i <= (ssize_t) MaxMap; i++)
2221       {
2222         x_map[i].x=(MagickRealType) i;
2223         y_map[i].x=0.000000f;
2224         z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i-
2225           (MagickRealType) MaxMap);
2226         x_map[i].y=(MagickRealType) i;
2227         y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i-
2228           (MagickRealType) MaxMap);
2229         z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i-
2230           (MagickRealType) MaxMap);
2231         x_map[i].z=(MagickRealType) i;
2232         y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i-
2233           (MagickRealType) MaxMap);
2234         z_map[i].z=0.000000f;
2235       }
2236       break;
2237     }
2238     case Rec709YCbCrColorspace:
2239     {
2240       /*
2241         Initialize YCbCr tables:
2242
2243           R = Y            +1.574800*Cr
2244           G = Y-0.187324*Cb-0.468124*Cr
2245           B = Y+1.855600*Cb
2246
2247         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
2248         through QuantumRange.
2249       */
2250 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2251   #pragma omp parallel for schedule(dynamic,4)
2252 #endif
2253       for (i=0; i <= (ssize_t) MaxMap; i++)
2254       {
2255         x_map[i].x=(MagickRealType) i;
2256         y_map[i].x=0.000000f;
2257         z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i-
2258           (MagickRealType) MaxMap);
2259         x_map[i].y=(MagickRealType) i;
2260         y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i-
2261           (MagickRealType) MaxMap);
2262         z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i-
2263           (MagickRealType) MaxMap);
2264         x_map[i].z=(MagickRealType) i;
2265         y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i-
2266           (MagickRealType) MaxMap);
2267         z_map[i].z=0.00000f;
2268       }
2269       break;
2270     }
2271     case sRGBColorspace:
2272     {
2273       /*
2274         Nonlinear sRGB to linear RGB.
2275
2276           R = 1.0*R+0.0*G+0.0*B
2277           G = 0.0*R+1.0*G+0.0*B
2278           B = 0.0*R+0.0*G+1.0*B
2279       */
2280 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2281   #pragma omp parallel for schedule(dynamic,4)
2282 #endif
2283       for (i=0; i <= (ssize_t) MaxMap; i++)
2284       {
2285         x_map[i].x=1.0f*(MagickRealType) i;
2286         y_map[i].x=0.0f*(MagickRealType) i;
2287         z_map[i].x=0.0f*(MagickRealType) i;
2288         x_map[i].y=0.0f*(MagickRealType) i;
2289         y_map[i].y=1.0f*(MagickRealType) i;
2290         z_map[i].y=0.0f*(MagickRealType) i;
2291         x_map[i].z=0.0f*(MagickRealType) i;
2292         y_map[i].z=0.0f*(MagickRealType) i;
2293         z_map[i].z=1.0f*(MagickRealType) i;
2294       }
2295       break;
2296     }
2297     case XYZColorspace:
2298     {
2299       /*
2300         Initialize CIE XYZ tables (ITU R-709 RGB):
2301
2302           R =  3.2404542*X-1.5371385*Y-0.4985314*Z
2303           G = -0.9692660*X+1.8760108*Y+0.0415560*Z
2304           B =  0.0556434*X-0.2040259*Y+1.057225*Z
2305       */
2306 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2307   #pragma omp parallel for schedule(dynamic,4)
2308 #endif
2309       for (i=0; i <= (ssize_t) MaxMap; i++)
2310       {
2311         x_map[i].x=3.2404542f*(MagickRealType) i;
2312         x_map[i].y=(-0.9692660f)*(MagickRealType) i;
2313         x_map[i].z=0.0556434f*(MagickRealType) i;
2314         y_map[i].x=(-1.5371385f)*(MagickRealType) i;
2315         y_map[i].y=1.8760108f*(MagickRealType) i;
2316         y_map[i].z=(-0.2040259f)*(MagickRealType) i;
2317         z_map[i].x=(-0.4985314f)*(MagickRealType) i;
2318         z_map[i].y=0.0415560f*(MagickRealType) i;
2319         z_map[i].z=1.0572252f*(MagickRealType) i;
2320       }
2321       break;
2322     }
2323     case YCCColorspace:
2324     {
2325       /*
2326         Initialize YCC tables:
2327
2328           R = Y            +1.340762*C2
2329           G = Y-0.317038*C1-0.682243*C2
2330           B = Y+1.632639*C1
2331
2332         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
2333       */
2334 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2335   #pragma omp parallel for schedule(dynamic,4)
2336 #endif
2337       for (i=0; i <= (ssize_t) MaxMap; i++)
2338       {
2339         x_map[i].x=1.3584000f*(MagickRealType) i;
2340         y_map[i].x=0.0000000f;
2341         z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType)
2342           ScaleQuantumToMap(ScaleCharToQuantum(137)));
2343         x_map[i].y=1.3584000f*(MagickRealType) i;
2344         y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType)
2345           ScaleQuantumToMap(ScaleCharToQuantum(156)));
2346         z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType)
2347           ScaleQuantumToMap(ScaleCharToQuantum(137)));
2348         x_map[i].z=1.3584000f*(MagickRealType) i;
2349         y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType)
2350           ScaleQuantumToMap(ScaleCharToQuantum(156)));
2351         z_map[i].z=0.0000000f;
2352       }
2353       break;
2354     }
2355     case YIQColorspace:
2356     {
2357       /*
2358         Initialize YIQ tables:
2359
2360           R = Y+0.95620*I+0.62140*Q
2361           G = Y-0.27270*I-0.64680*Q
2362           B = Y-1.10370*I+1.70060*Q
2363
2364         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2365         through QuantumRange.
2366       */
2367 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2368   #pragma omp parallel for schedule(dynamic,4)
2369 #endif
2370       for (i=0; i <= (ssize_t) MaxMap; i++)
2371       {
2372         x_map[i].x=(MagickRealType) i;
2373         y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType)
2374           MaxMap);
2375         z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType)
2376           MaxMap);
2377         x_map[i].y=(MagickRealType) i;
2378         y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2379           MaxMap);
2380         z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2381           MaxMap);
2382         x_map[i].z=(MagickRealType) i;
2383         y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2384           MaxMap);
2385         z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType)
2386           MaxMap);
2387       }
2388       break;
2389     }
2390     case YPbPrColorspace:
2391     {
2392       /*
2393         Initialize YPbPr tables:
2394
2395           R = Y            +1.402000*C2
2396           G = Y-0.344136*C1+0.714136*C2
2397           B = Y+1.772000*C1
2398
2399         Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
2400         through QuantumRange.
2401       */
2402 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2403   #pragma omp parallel for schedule(dynamic,4)
2404 #endif
2405       for (i=0; i <= (ssize_t) MaxMap; i++)
2406       {
2407         x_map[i].x=(MagickRealType) i;
2408         y_map[i].x=0.000000f;
2409         z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType)
2410           MaxMap);
2411         x_map[i].y=(MagickRealType) i;
2412         y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2413           MaxMap);
2414         z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType)
2415           MaxMap);
2416         x_map[i].z=(MagickRealType) i;
2417         y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType)
2418           MaxMap);
2419         z_map[i].z=0.00000f;
2420       }
2421       break;
2422     }
2423     case YUVColorspace:
2424     default:
2425     {
2426       /*
2427         Initialize YUV tables:
2428
2429           R = Y          +1.13980*V
2430           G = Y-0.39380*U-0.58050*V
2431           B = Y+2.02790*U
2432
2433         U and V, normally -0.5 through 0.5, must be normalized to the range 0
2434         through QuantumRange.
2435       */
2436 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2437   #pragma omp parallel for schedule(dynamic,4)
2438 #endif
2439       for (i=0; i <= (ssize_t) MaxMap; i++)
2440       {
2441         x_map[i].x=(MagickRealType) i;
2442         y_map[i].x=0.00000f;
2443         z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType)
2444           MaxMap);
2445         x_map[i].y=(MagickRealType) i;
2446         y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2447           MaxMap);
2448         z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2449           MaxMap);
2450         x_map[i].z=(MagickRealType) i;
2451         y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType)
2452           MaxMap);
2453         z_map[i].z=0.00000f;
2454       }
2455       break;
2456     }
2457   }
2458   /*
2459     Convert to RGB.
2460   */
2461   switch (image->storage_class)
2462   {
2463     case DirectClass:
2464     default:
2465     {
2466       /*
2467         Convert DirectClass image.
2468       */
2469       image_view=AcquireCacheView(image);
2470 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2471   #pragma omp parallel for schedule(dynamic,4) shared(status)
2472 #endif
2473       for (y=0; y < (ssize_t) image->rows; y++)
2474       {
2475         MagickBooleanType
2476           sync;
2477
2478         PixelInfo
2479           pixel;
2480
2481         register ssize_t
2482           x;
2483
2484         register Quantum
2485           *restrict q;
2486
2487         if (status == MagickFalse)
2488           continue;
2489         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2490           exception);
2491         if (q == (const Quantum *) NULL)
2492           {
2493             status=MagickFalse;
2494             continue;
2495           }
2496         for (x=0; x < (ssize_t) image->columns; x++)
2497         {
2498           register size_t
2499             blue,
2500             green,
2501             red;
2502
2503           red=ScaleQuantumToMap(GetPixelRed(image,q));
2504           green=ScaleQuantumToMap(GetPixelGreen(image,q));
2505           blue=ScaleQuantumToMap(GetPixelBlue(image,q));
2506           pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2507           pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2508           pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2509           switch (colorspace)
2510           {
2511             case YCCColorspace:
2512             {
2513 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2514               pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
2515                 pixel.red)];
2516               pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
2517                 pixel.green)];
2518               pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
2519                 pixel.blue)];
2520 #endif
2521               break;
2522             }
2523             case sRGBColorspace:
2524             {
2525               if ((QuantumScale*pixel.red) <= 0.0031308)
2526                 pixel.red*=12.92f;
2527               else
2528                 pixel.red=(MagickRealType) QuantumRange*(1.055*
2529                   pow(QuantumScale*pixel.red,(1.0/2.4))-0.055);
2530               if ((QuantumScale*pixel.green) <= 0.0031308)
2531                 pixel.green*=12.92f;
2532               else
2533                 pixel.green=(MagickRealType) QuantumRange*(1.055*
2534                   pow(QuantumScale*pixel.green,(1.0/2.4))-0.055);
2535               if ((QuantumScale*pixel.blue) <= 0.0031308)
2536                 pixel.blue*=12.92f;
2537               else
2538                 pixel.blue=(MagickRealType) QuantumRange*(1.055*
2539                   pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055);
2540               break;
2541             }
2542             default:
2543               break;
2544           }
2545           SetPixelRed(image,ScaleMapToQuantum((MagickRealType) MaxMap*
2546             QuantumScale*pixel.red),q);
2547           SetPixelGreen(image,ScaleMapToQuantum((MagickRealType) MaxMap*
2548             QuantumScale*pixel.green),q);
2549           SetPixelBlue(image,ScaleMapToQuantum((MagickRealType) MaxMap*
2550             QuantumScale*pixel.blue),q);
2551           q+=GetPixelChannels(image);
2552         }
2553         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2554         if (sync == MagickFalse)
2555           status=MagickFalse;
2556         if (image->progress_monitor != (MagickProgressMonitor) NULL)
2557           {
2558             MagickBooleanType
2559               proceed;
2560
2561 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2562   #pragma omp critical (MagickCore_TransformRGBImage)
2563 #endif
2564             proceed=SetImageProgress(image,TransformRGBImageTag,progress++,
2565               image->rows);
2566             if (proceed == MagickFalse)
2567               status=MagickFalse;
2568           }
2569       }
2570       image_view=DestroyCacheView(image_view);
2571       break;
2572     }
2573     case PseudoClass:
2574     {
2575       /*
2576         Convert PseudoClass image.
2577       */
2578       image_view=AcquireCacheView(image);
2579 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2580   #pragma omp parallel for schedule(dynamic,4) shared(status)
2581 #endif
2582       for (i=0; i < (ssize_t) image->colors; i++)
2583       {
2584         PixelInfo
2585           pixel;
2586
2587         register size_t
2588           blue,
2589           green,
2590           red;
2591
2592         red=ScaleQuantumToMap(image->colormap[i].red);
2593         green=ScaleQuantumToMap(image->colormap[i].green);
2594         blue=ScaleQuantumToMap(image->colormap[i].blue);
2595         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2596         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2597         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2598         switch (colorspace)
2599         {
2600           case YCCColorspace:
2601           {
2602 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2603             image->colormap[i].red=(Quantum) (QuantumRange*YCCMap[
2604               RoundToYCC(1024.0*QuantumScale*pixel.red)]);
2605             image->colormap[i].green=(Quantum) (QuantumRange*YCCMap[
2606               RoundToYCC(1024.0*QuantumScale*pixel.green)]);
2607             image->colormap[i].blue=(Quantum) (QuantumRange*YCCMap[
2608               RoundToYCC(1024.0*QuantumScale*pixel.blue)]);
2609 #endif
2610             break;
2611           }
2612           case sRGBColorspace:
2613           {
2614             if ((QuantumScale*pixel.red) <= 0.0031308)
2615               pixel.red*=12.92f;
2616             else
2617               pixel.red=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2618                 pixel.red,(1.0/2.4))-0.055);
2619             if ((QuantumScale*pixel.green) <= 0.0031308)
2620               pixel.green*=12.92f;
2621             else
2622               pixel.green=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2623                 pixel.green,(1.0/2.4))-0.055);
2624             if ((QuantumScale*pixel.blue) <= 0.0031308)
2625               pixel.blue*=12.92f;
2626             else
2627               pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2628                 pixel.blue,(1.0/2.4))-0.055);
2629           }
2630           default:
2631           {
2632             image->colormap[i].red=ScaleMapToQuantum((MagickRealType) MaxMap*
2633               QuantumScale*pixel.red);
2634             image->colormap[i].green=ScaleMapToQuantum((MagickRealType) MaxMap*
2635               QuantumScale*pixel.green);
2636             image->colormap[i].blue=ScaleMapToQuantum((MagickRealType) MaxMap*
2637               QuantumScale*pixel.blue);
2638             break;
2639           }
2640         }
2641       }
2642       image_view=DestroyCacheView(image_view);
2643       (void) SyncImage(image);
2644       break;
2645     }
2646   }
2647   /*
2648     Relinquish resources.
2649   */
2650   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2651   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2652   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2653   if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
2654     return(MagickFalse);
2655   return(MagickTrue);
2656 }