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