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