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