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