]> granicus.if.org Git - imagemagick/blob - magick/colorspace.c
(no commit message)
[imagemagick] / magick / 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-2009 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 "magick/studio.h"
43 #include "magick/property.h"
44 #include "magick/cache.h"
45 #include "magick/cache-private.h"
46 #include "magick/cache-view.h"
47 #include "magick/color.h"
48 #include "magick/color-private.h"
49 #include "magick/colorspace.h"
50 #include "magick/colorspace-private.h"
51 #include "magick/exception.h"
52 #include "magick/exception-private.h"
53 #include "magick/image.h"
54 #include "magick/image-private.h"
55 #include "magick/gem.h"
56 #include "magick/memory_.h"
57 #include "magick/monitor.h"
58 #include "magick/monitor-private.h"
59 #include "magick/pixel-private.h"
60 #include "magick/quantize.h"
61 #include "magick/quantum.h"
62 #include "magick/string_.h"
63 #include "magick/utility.h"
64 \f
65 /*
66   Typedef declarations.
67 */
68 typedef struct _TransformPacket
69 {
70   MagickRealType
71     x,
72     y,
73     z;
74 } TransformPacket;
75 \f
76 /*
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 %                                                                             %
79 %                                                                             %
80 %                                                                             %
81 +     R G B T r a n s f o r m I m a g e                                       %
82 %                                                                             %
83 %                                                                             %
84 %                                                                             %
85 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86 %
87 %  RGBTransformImage() converts the reference image from RGB to an alternate
88 %  colorspace.  The transformation matrices are not the standard ones: the
89 %  weights are rescaled to normalized the range of the transformed values to
90 %  be [0..QuantumRange].
91 %
92 %  The format of the RGBTransformImage method is:
93 %
94 %      MagickBooleanType RGBTransformImage(Image *image,
95 %        const ColorspaceType colorspace)
96 %
97 %  A description of each parameter follows:
98 %
99 %    o image: the image.
100 %
101 %    o colorspace: the colorspace to transform the image to.
102 %
103 */
104
105 static inline void ConvertRGBToXYZ(const Quantum red,const Quantum green,
106   const Quantum blue,double *X,double *Y,double *Z)
107 {
108   double
109     b,
110     g,
111     r;
112
113   assert(X != (double *) NULL);
114   assert(Y != (double *) NULL);
115   assert(Z != (double *) NULL);
116   r=QuantumScale*red;
117   g=QuantumScale*green;
118   b=QuantumScale*blue;
119   *X=0.4124240*r+0.3575790*g+0.1804640*b;
120   *Y=0.2126560*r+0.7151580*g+0.0721856*b;
121   *Z=0.0193324*r+0.1191930*g+0.9504440*b;
122 }
123
124 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
125   double *L,double *a,double *b)
126 {
127   double
128     x,
129     y,
130     z;
131
132   assert(L != (double *) NULL);
133   assert(a != (double *) NULL);
134   assert(b != (double *) NULL);
135   x=X/0.9504559271;
136   if (x > (216/24389.0))
137     x=pow(x,1.0/3.0);
138   else
139     x=(7.787*x)+(16.0/116.0);
140   y=Y/1.00000;
141   if (y > (216/24389.0))
142     y=pow(y,1.0/3.0);
143   else
144     y=(7.787*y)+(16.0/116.0);
145   z=Z/1.0890577508;
146   if (z > (216/24389.0))
147     z=pow(z,1.0/3.0);
148   else
149     z=(7.787*z)+(16.0/116.0);
150   *L=0.5*((1.160*y)-0.160+1.0);
151   *a=0.5*(5.000*(x-y)+1.0);
152   *b=0.5*(2.000*(y-z)+1.0);
153 }
154
155 MagickExport MagickBooleanType RGBTransformImage(Image *image,
156   const ColorspaceType colorspace)
157 {
158 #define RGBTransformImageTag  "RGBTransform/Image"
159
160   ExceptionInfo
161     *exception;
162
163   long
164     progress,
165     y;
166
167   MagickBooleanType
168     status,
169     sync;
170
171   PrimaryInfo
172     primary_info;
173
174   register long
175     i;
176
177   TransformPacket
178     *x_map,
179     *y_map,
180     *z_map;
181
182   CacheView
183     *image_view;
184
185   assert(image != (Image *) NULL);
186   assert(image->signature == MagickSignature);
187   if (image->debug != MagickFalse)
188     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
189   assert(colorspace != RGBColorspace);
190   assert(colorspace != TransparentColorspace);
191   assert(colorspace != UndefinedColorspace);
192   switch (image->colorspace)
193   {
194     case GRAYColorspace:
195     case Rec601LumaColorspace:
196     case Rec709LumaColorspace:
197     case RGBColorspace:
198     case TransparentColorspace:
199       break;
200     default:
201     {
202       (void) TransformImageColorspace(image,image->colorspace);
203       break;
204     }
205   }
206   if (SetImageColorspace(image,colorspace) == MagickFalse)
207     return(MagickFalse);
208   status=MagickTrue;
209   progress=0;
210   exception=(&image->exception);
211   switch (colorspace)
212   {
213     case CMYColorspace:
214     {
215       /*
216         Convert RGB to CMY colorspace.
217       */
218       if (image->storage_class == PseudoClass)
219         {
220           if (SyncImage(image) == MagickFalse)
221             return(MagickFalse);
222           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
223             return(MagickFalse);
224         }
225       image_view=AcquireCacheView(image);
226 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
227   #pragma omp parallel for shared(status)
228 #endif
229       for (y=0; y < (long) image->rows; y++)
230       {
231         register long
232           x;
233
234         register PixelPacket
235           *__restrict q;
236
237         if (status == MagickFalse)
238           continue;
239         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
240           exception);
241         if (q == (PixelPacket *) NULL)
242           {
243             status=MagickFalse;
244             continue;
245           }
246         for (x=0; x < (long) image->columns; x++)
247         {
248           q->red=RoundToQuantum((MagickRealType) (QuantumRange-q->red));
249           q->green=RoundToQuantum((MagickRealType) (QuantumRange-q->green));
250           q->blue=RoundToQuantum((MagickRealType) (QuantumRange-q->blue));
251           q++;
252         }
253         sync=SyncCacheViewAuthenticPixels(image_view,exception);
254         if (sync == MagickFalse)
255           status=MagickFalse;
256       }
257       image_view=DestroyCacheView(image_view);
258       image->type=image->matte == MagickFalse ? ColorSeparationType :
259         ColorSeparationMatteType;
260       return(status);
261     }
262     case CMYKColorspace:
263     {
264       MagickPixelPacket
265         zero;
266
267       /*
268         Convert RGB to CMYK colorspace.
269       */
270       if (image->storage_class == PseudoClass)
271         {
272           if (SyncImage(image) == MagickFalse)
273             return(MagickFalse);
274           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
275             return(MagickFalse);
276         }
277       GetMagickPixelPacket(image,&zero);
278       image_view=AcquireCacheView(image);
279 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
280   #pragma omp parallel for shared(status)
281 #endif
282       for (y=0; y < (long) image->rows; y++)
283       {
284         MagickPixelPacket
285           pixel;
286
287         register IndexPacket
288           *__restrict indexes;
289
290         register long
291           x;
292
293         register PixelPacket
294           *__restrict q;
295
296         if (status == MagickFalse)
297           continue;
298         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
299           exception);
300         if (q == (PixelPacket *) NULL)
301           {
302             status=MagickFalse;
303             continue;
304           }
305         indexes=GetCacheViewAuthenticIndexQueue(image_view);
306         pixel=zero;
307         for (x=0; x < (long) image->columns; x++)
308         {
309           SetMagickPixelPacket(image,q,indexes+x,&pixel);
310           ConvertRGBToCMYK(&pixel);
311           SetPixelPacket(image,&pixel,q,indexes+x);
312           q++;
313         }
314         sync=SyncCacheViewAuthenticPixels(image_view,exception);
315         if (sync == MagickFalse)
316           status=MagickFalse;
317       }
318       image_view=DestroyCacheView(image_view);
319       image->type=image->matte == MagickFalse ? ColorSeparationType :
320         ColorSeparationMatteType;
321       return(status);
322     }
323     case HSBColorspace:
324     {
325       /*
326         Transform image from RGB to HSB.
327       */
328       if (image->storage_class == PseudoClass)
329         {
330           if (SyncImage(image) == MagickFalse)
331             return(MagickFalse);
332           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
333             return(MagickFalse);
334         }
335       image_view=AcquireCacheView(image);
336 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
337   #pragma omp parallel for shared(status)
338 #endif
339       for (y=0; y < (long) image->rows; y++)
340       {
341         double
342           brightness,
343           hue,
344           saturation;
345
346         register long
347           x;
348
349         register PixelPacket
350           *__restrict q;
351
352         if (status == MagickFalse)
353           continue;
354         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
355           exception);
356         if (q == (PixelPacket *) NULL)
357           {
358             status=MagickFalse;
359             continue;
360           }
361         hue=0.0;
362         saturation=0.0;
363         brightness=0.0;
364         for (x=0; x < (long) image->columns; x++)
365         {
366           ConvertRGBToHSB(q->red,q->green,q->blue,&hue,&saturation,&brightness);
367           q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
368           q->green=RoundToQuantum((MagickRealType) QuantumRange*saturation);
369           q->blue=RoundToQuantum((MagickRealType) QuantumRange*brightness);
370           q++;
371         }
372         sync=SyncCacheViewAuthenticPixels(image_view,exception);
373         if (sync == MagickFalse)
374           status=MagickFalse;
375       }
376       image_view=DestroyCacheView(image_view);
377       return(status);
378     }
379     case HSLColorspace:
380     {
381       /*
382         Transform image from RGB to HSL.
383       */
384       if (image->storage_class == PseudoClass)
385         {
386           if (SyncImage(image) == MagickFalse)
387             return(MagickFalse);
388           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
389             return(MagickFalse);
390         }
391       image_view=AcquireCacheView(image);
392 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
393   #pragma omp parallel for shared(status)
394 #endif
395       for (y=0; y < (long) image->rows; y++)
396       {
397         double
398           hue,
399           lightness,
400           saturation;
401
402         register long
403           x;
404
405         register PixelPacket
406           *__restrict q;
407
408         if (status == MagickFalse)
409           continue;
410         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
411           exception);
412         if (q == (PixelPacket *) NULL)
413           {
414             status=MagickFalse;
415             continue;
416           }
417         hue=0.0;
418         saturation=0.0;
419         lightness=0.0;
420         for (x=0; x < (long) image->columns; x++)
421         {
422           ConvertRGBToHSL(q->red,q->green,q->blue,&hue,&saturation,&lightness);
423           q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
424           q->green=RoundToQuantum((MagickRealType) QuantumRange*saturation);
425           q->blue=RoundToQuantum((MagickRealType) QuantumRange*lightness);
426           q++;
427         }
428         sync=SyncCacheViewAuthenticPixels(image_view,exception);
429         if (sync == MagickFalse)
430           status=MagickFalse;
431       }
432       image_view=DestroyCacheView(image_view);
433       return(status);
434     }
435     case HWBColorspace:
436     {
437       /*
438         Transform image from RGB to HWB.
439       */
440       if (image->storage_class == PseudoClass)
441         {
442           if (SyncImage(image) == MagickFalse)
443             return(MagickFalse);
444           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
445             return(MagickFalse);
446         }
447       image_view=AcquireCacheView(image);
448 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
449   #pragma omp parallel for shared(status)
450 #endif
451       for (y=0; y < (long) image->rows; y++)
452       {
453         double
454           blackness,
455           hue,
456           whiteness;
457
458         register long
459           x;
460
461         register PixelPacket
462           *__restrict q;
463
464         if (status == MagickFalse)
465           continue;
466         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
467           exception);
468         if (q == (PixelPacket *) NULL)
469           {
470             status=MagickFalse;
471             continue;
472           }
473         hue=0.0;
474         whiteness=0.0;
475         blackness=0.0;
476         for (x=0; x < (long) image->columns; x++)
477         {
478           ConvertRGBToHWB(q->red,q->green,q->blue,&hue,&whiteness,&blackness);
479           q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
480           q->green=RoundToQuantum((MagickRealType) QuantumRange*whiteness);
481           q->blue=RoundToQuantum((MagickRealType) QuantumRange*blackness);
482           q++;
483         }
484         sync=SyncCacheViewAuthenticPixels(image_view,exception);
485         if (sync == MagickFalse)
486           status=MagickFalse;
487       }
488       image_view=DestroyCacheView(image_view);
489       return(status);
490     }
491     case LabColorspace:
492     {
493       /*
494         Transform image from RGB to Lab.
495       */
496       if (image->storage_class == PseudoClass)
497         {
498           if (SyncImage(image) == MagickFalse)
499             return(MagickFalse);
500           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
501             return(MagickFalse);
502         }
503       image_view=AcquireCacheView(image);
504 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
505   #pragma omp parallel for shared(status)
506 #endif
507       for (y=0; y < (long) image->rows; y++)
508       {
509         double
510           a,
511           b,
512           L,
513           X,
514           Y,
515           Z;
516
517         register long
518           x;
519
520         register PixelPacket
521           *__restrict q;
522
523         if (status == MagickFalse)
524           continue;
525         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
526           exception);
527         if (q == (PixelPacket *) NULL)
528           {
529             status=MagickFalse;
530             continue;
531           }
532         L=0.0;
533         a=0.0;
534         b=0.0;
535         X=0.0;
536         Y=0.0;
537         Z=0.0;
538         for (x=0; x < (long) image->columns; x++)
539         {
540           ConvertRGBToXYZ(q->red,q->green,q->blue,&X,&Y,&Z);
541           ConvertXYZToLab(X,Y,Z,&L,&a,&b);
542           q->red=RoundToQuantum((MagickRealType) QuantumRange*L);
543           q->green=RoundToQuantum((MagickRealType) QuantumRange*a);
544           q->blue=RoundToQuantum((MagickRealType) QuantumRange*b);
545           q++;
546         }
547         sync=SyncCacheViewAuthenticPixels(image_view,exception);
548         if (sync == MagickFalse)
549           status=MagickFalse;
550       }
551       image_view=DestroyCacheView(image_view);
552       return(status);
553     }
554     case LogColorspace:
555     {
556 #define ReferenceBlack  95.0
557 #define ReferenceWhite  685.0
558 #define DisplayGamma  (1.0/1.7)
559
560       const char
561         *value;
562
563       double
564         black,
565         density,
566         gamma,
567         reference_black,
568         reference_white;
569
570       Quantum
571         *logmap;
572
573       /*
574         Transform RGB to Log colorspace.
575       */
576       density=2.03728;
577       gamma=DisplayGamma;
578       value=GetImageProperty(image,"gamma");
579       if (value != (const char *) NULL)
580         gamma=1.0/atof(value) != 0.0 ? atof(value) : 1.0;
581       reference_black=ReferenceBlack;
582       value=GetImageProperty(image,"reference-black");
583       if (value != (const char *) NULL)
584         reference_black=atof(value);
585       reference_white=ReferenceWhite;
586       value=GetImageProperty(image,"reference-white");
587       if (value != (const char *) NULL)
588         reference_white=atof(value);
589       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
590         sizeof(*logmap));
591       if (logmap == (Quantum *) NULL)
592         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
593           image->filename);
594       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
595         0.002/0.6);
596 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
597   #pragma omp parallel for
598 #endif
599       for (i=0; i <= (long) MaxMap; i++)
600         logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+
601           log10(black+((MagickRealType) i/MaxMap)*(1.0-black))/((gamma/density)*
602           0.002/0.6))/1024.0+0.5));
603       image_view=AcquireCacheView(image);
604 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
605   #pragma omp parallel for shared(status)
606 #endif
607       for (y=0; y < (long) image->rows; y++)
608       {
609         register long
610           x;
611
612         register PixelPacket
613           *__restrict q;
614
615         if (status == MagickFalse)
616           continue;
617         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
618           exception);
619         if (q == (PixelPacket *) NULL)
620           {
621             status=MagickFalse;
622             continue;
623           }
624         for (x=(long) image->columns; x != 0; x--)
625         {
626           q->red=logmap[ScaleQuantumToMap(q->red)];
627           q->green=logmap[ScaleQuantumToMap(q->green)];
628           q->blue=logmap[ScaleQuantumToMap(q->blue)];
629           q++;
630         }
631         sync=SyncCacheViewAuthenticPixels(image_view,exception);
632         if (sync == MagickFalse)
633           status=MagickFalse;
634       }
635       image_view=DestroyCacheView(image_view);
636       logmap=(Quantum *) RelinquishMagickMemory(logmap);
637       return(status);
638     }
639     default:
640       break;
641   }
642   /*
643     Allocate the tables.
644   */
645   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
646     sizeof(*x_map));
647   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
648     sizeof(*y_map));
649   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
650     sizeof(*z_map));
651   if ((x_map == (TransformPacket *) NULL) ||
652       (y_map == (TransformPacket *) NULL) ||
653       (z_map == (TransformPacket *) NULL))
654     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
655       image->filename);
656   (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
657   switch (colorspace)
658   {
659     case OHTAColorspace:
660     {
661       /*
662         Initialize OHTA tables:
663
664           I1 = 0.33333*R+0.33334*G+0.33333*B
665           I2 = 0.50000*R+0.00000*G-0.50000*B
666           I3 =-0.25000*R+0.50000*G-0.25000*B
667
668         I and Q, normally -0.5 through 0.5, are normalized to the range 0
669         through QuantumRange.
670       */
671       primary_info.y=(double) (MaxMap+1.0)/2.0;
672       primary_info.z=(double) (MaxMap+1.0)/2.0;
673 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
674   #pragma omp parallel for
675 #endif
676       for (i=0; i <= (long) MaxMap; i++)
677       {
678         x_map[i].x=0.33333f*(MagickRealType) i;
679         y_map[i].x=0.33334f*(MagickRealType) i;
680         z_map[i].x=0.33333f*(MagickRealType) i;
681         x_map[i].y=0.50000f*(MagickRealType) i;
682         y_map[i].y=0.00000f*(MagickRealType) i;
683         z_map[i].y=(-0.50000f)*(MagickRealType) i;
684         x_map[i].z=(-0.25000f)*(MagickRealType) i;
685         y_map[i].z=0.50000f*(MagickRealType) i;
686         z_map[i].z=(-0.25000f)*(MagickRealType) i;
687       }
688       break;
689     }
690     case Rec601LumaColorspace:
691     case GRAYColorspace:
692     {
693       /*
694         Initialize Rec601 luma tables:
695
696           G = 0.29900*R+0.58700*G+0.11400*B
697       */
698 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
699   #pragma omp parallel for
700 #endif
701       for (i=0; i <= (long) MaxMap; i++)
702       {
703         x_map[i].x=0.29900f*(MagickRealType) i;
704         y_map[i].x=0.58700f*(MagickRealType) i;
705         z_map[i].x=0.11400f*(MagickRealType) i;
706         x_map[i].y=0.29900f*(MagickRealType) i;
707         y_map[i].y=0.58700f*(MagickRealType) i;
708         z_map[i].y=0.11400f*(MagickRealType) i;
709         x_map[i].z=0.29900f*(MagickRealType) i;
710         y_map[i].z=0.58700f*(MagickRealType) i;
711         z_map[i].z=0.11400f*(MagickRealType) i;
712       }
713       image->type=GrayscaleType;
714       break;
715     }
716     case Rec601YCbCrColorspace:
717     case YCbCrColorspace:
718     {
719       /*
720         Initialize YCbCr tables (ITU-R BT.601):
721
722           Y =  0.299000*R+0.587000*G+0.114000*B
723           Cb= -0.168736*R-0.331264*G+0.500000*B
724           Cr=  0.500000*R-0.418688*G-0.081312*B
725
726         Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
727         through QuantumRange.
728       */
729       primary_info.y=(double) (MaxMap+1.0)/2.0;
730       primary_info.z=(double) (MaxMap+1.0)/2.0;
731 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
732   #pragma omp parallel for
733 #endif
734       for (i=0; i <= (long) MaxMap; i++)
735       {
736         x_map[i].x=0.299000f*(MagickRealType) i;
737         y_map[i].x=0.587000f*(MagickRealType) i;
738         z_map[i].x=0.114000f*(MagickRealType) i;
739         x_map[i].y=(-0.168730f)*(MagickRealType) i;
740         y_map[i].y=(-0.331264f)*(MagickRealType) i;
741         z_map[i].y=0.500000f*(MagickRealType) i;
742         x_map[i].z=0.500000f*(MagickRealType) i;
743         y_map[i].z=(-0.418688f)*(MagickRealType) i;
744         z_map[i].z=(-0.081312f)*(MagickRealType) i;
745       }
746       break;
747     }
748     case Rec709LumaColorspace:
749     {
750       /*
751         Initialize Rec709 luma tables:
752
753           G = 0.21260*R+0.71520*G+0.07220*B
754       */
755 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
756   #pragma omp parallel for
757 #endif
758       for (i=0; i <= (long) MaxMap; i++)
759       {
760         x_map[i].x=0.21260f*(MagickRealType) i;
761         y_map[i].x=0.71520f*(MagickRealType) i;
762         z_map[i].x=0.07220f*(MagickRealType) i;
763         x_map[i].y=0.21260f*(MagickRealType) i;
764         y_map[i].y=0.71520f*(MagickRealType) i;
765         z_map[i].y=0.07220f*(MagickRealType) i;
766         x_map[i].z=0.21260f*(MagickRealType) i;
767         y_map[i].z=0.71520f*(MagickRealType) i;
768         z_map[i].z=0.07220f*(MagickRealType) i;
769       }
770       break;
771     }
772     case Rec709YCbCrColorspace:
773     {
774       /*
775         Initialize YCbCr tables (ITU-R BT.709):
776
777           Y =  0.212600*R+0.715200*G+0.072200*B
778           Cb= -0.114572*R-0.385428*G+0.500000*B
779           Cr=  0.500000*R-0.454153*G-0.045847*B
780
781         Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
782         through QuantumRange.
783       */
784       primary_info.y=(double) (MaxMap+1.0)/2.0;
785       primary_info.z=(double) (MaxMap+1.0)/2.0;
786 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
787   #pragma omp parallel for
788 #endif
789       for (i=0; i <= (long) MaxMap; i++)
790       {
791         x_map[i].x=0.212600f*(MagickRealType) i;
792         y_map[i].x=0.715200f*(MagickRealType) i;
793         z_map[i].x=0.072200f*(MagickRealType) i;
794         x_map[i].y=(-0.114572f)*(MagickRealType) i;
795         y_map[i].y=(-0.385428f)*(MagickRealType) i;
796         z_map[i].y=0.500000f*(MagickRealType) i;
797         x_map[i].z=0.500000f*(MagickRealType) i;
798         y_map[i].z=(-0.454153f)*(MagickRealType) i;
799         z_map[i].z=(-0.045847f)*(MagickRealType) i;
800       }
801       break;
802     }
803     case sRGBColorspace:
804     {
805       /*
806         Linear RGB to nonlinear sRGB (http://www.w3.org/Graphics/Color/sRGB):
807
808           R = 1.0*R+0.0*G+0.0*B
809           G = 0.0*R+0.1*G+0.0*B
810           B = 0.0*R+0.0*G+1.0*B
811       */
812 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
813   #pragma omp parallel for
814 #endif
815       for (i=0; i <= (long) MaxMap; i++)
816       {
817         MagickRealType
818           v;
819
820         v=(MagickRealType) i/(MagickRealType) MaxMap;
821         if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.03928f)
822           v/=12.92f;
823         else
824           v=(MagickRealType) MaxMap*pow((((double) i/MaxMap)+0.055)/1.055,2.4);
825         x_map[i].x=1.0f*v;
826         y_map[i].x=0.0f*v;
827         z_map[i].x=0.0f*v;
828         x_map[i].y=0.0f*v;
829         y_map[i].y=1.0f*v;
830         z_map[i].y=0.0f*v;
831         x_map[i].z=0.0f*v;
832         y_map[i].z=0.0f*v;
833         z_map[i].z=1.0f*v;
834       }
835       break;
836     }
837     case XYZColorspace:
838     {
839       /*
840         Initialize CIE XYZ tables (ITU-R 709 RGB):
841
842           X = 0.4124564*R+0.3575761*G+0.1804375*B
843           Y = 0.2126729*R+0.7151522*G+0.0721750*B
844           Z = 0.0193339*R+0.1191920*G+0.9503041*B
845       */
846 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
847   #pragma omp parallel for
848 #endif
849       for (i=0; i <= (long) MaxMap; i++)
850       {
851         x_map[i].x=0.4124564f*(MagickRealType) i;
852         y_map[i].x=0.3575761f*(MagickRealType) i;
853         z_map[i].x=0.1804375f*(MagickRealType) i;
854         x_map[i].y=0.2126729f*(MagickRealType) i;
855         y_map[i].y=0.7151522f*(MagickRealType) i;
856         z_map[i].y=0.0721750f*(MagickRealType) i;
857         x_map[i].z=0.0193339f*(MagickRealType) i;
858         y_map[i].z=0.1191920f*(MagickRealType) i;
859         z_map[i].z=0.9503041f*(MagickRealType) i;
860       }
861       break;
862     }
863     case YCCColorspace:
864     {
865       /*
866         Initialize YCC tables:
867
868           Y =  0.29900*R+0.58700*G+0.11400*B
869           C1= -0.29900*R-0.58700*G+0.88600*B
870           C2=  0.70100*R-0.58700*G-0.11400*B
871
872         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
873       */
874       primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
875       primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
876       for (i=0; i <= (long) (0.018*MaxMap); i++)
877       {
878         x_map[i].x=0.003962014134275617f*(MagickRealType) i;
879         y_map[i].x=0.007778268551236748f*(MagickRealType) i;
880         z_map[i].x=0.001510600706713781f*(MagickRealType) i;
881         x_map[i].y=(-0.002426619775463276f)*(MagickRealType) i;
882         y_map[i].y=(-0.004763965913702149f)*(MagickRealType) i;
883         z_map[i].y=0.007190585689165425f*(MagickRealType) i;
884         x_map[i].z=0.006927257754597858f*(MagickRealType) i;
885         y_map[i].z=(-0.005800713697502058f)*(MagickRealType) i;
886         z_map[i].z=(-0.0011265440570958f)*(MagickRealType) i;
887       }
888       for ( ; i <= (long) MaxMap; i++)
889       {
890         x_map[i].x=0.2201118963486454*(1.099f*(MagickRealType) i-0.099f);
891         y_map[i].x=0.4321260306242638*(1.099f*(MagickRealType) i-0.099f);
892         z_map[i].x=0.08392226148409894*(1.099f*(MagickRealType) i-0.099f);
893         x_map[i].y=(-0.1348122097479598)*(1.099f*(MagickRealType) i-0.099f);
894         y_map[i].y=(-0.2646647729834528)*(1.099f*(MagickRealType) i-0.099f);
895         z_map[i].y=0.3994769827314126*(1.099f*(MagickRealType) i-0.099f);
896         x_map[i].z=0.3848476530332144*(1.099f*(MagickRealType) i-0.099f);
897         y_map[i].z=(-0.3222618720834477)*(1.099f*(MagickRealType) i-0.099f);
898         z_map[i].z=(-0.06258578094976668)*(1.099f*(MagickRealType) i-0.099f);
899       }
900       break;
901     }
902     case YIQColorspace:
903     {
904       /*
905         Initialize YIQ tables:
906
907           Y = 0.29900*R+0.58700*G+0.11400*B
908           I = 0.59600*R-0.27400*G-0.32200*B
909           Q = 0.21100*R-0.52300*G+0.31200*B
910
911         I and Q, normally -0.5 through 0.5, are normalized to the range 0
912         through QuantumRange.
913       */
914       primary_info.y=(double) (MaxMap+1.0)/2.0;
915       primary_info.z=(double) (MaxMap+1.0)/2.0;
916 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
917   #pragma omp parallel for
918 #endif
919       for (i=0; i <= (long) MaxMap; i++)
920       {
921         x_map[i].x=0.29900f*(MagickRealType) i;
922         y_map[i].x=0.58700f*(MagickRealType) i;
923         z_map[i].x=0.11400f*(MagickRealType) i;
924         x_map[i].y=0.59600f*(MagickRealType) i;
925         y_map[i].y=(-0.27400f)*(MagickRealType) i;
926         z_map[i].y=(-0.32200f)*(MagickRealType) i;
927         x_map[i].z=0.21100f*(MagickRealType) i;
928         y_map[i].z=(-0.52300f)*(MagickRealType) i;
929         z_map[i].z=0.31200f*(MagickRealType) i;
930       }
931       break;
932     }
933     case YPbPrColorspace:
934     {
935       /*
936         Initialize YPbPr tables (ITU-R BT.601):
937
938           Y =  0.299000*R+0.587000*G+0.114000*B
939           Pb= -0.168736*R-0.331264*G+0.500000*B
940           Pr=  0.500000*R-0.418688*G-0.081312*B
941
942         Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0
943         through QuantumRange.
944       */
945       primary_info.y=(double) (MaxMap+1.0)/2.0;
946       primary_info.z=(double) (MaxMap+1.0)/2.0;
947 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
948   #pragma omp parallel for
949 #endif
950       for (i=0; i <= (long) MaxMap; i++)
951       {
952         x_map[i].x=0.299000f*(MagickRealType) i;
953         y_map[i].x=0.587000f*(MagickRealType) i;
954         z_map[i].x=0.114000f*(MagickRealType) i;
955         x_map[i].y=(-0.168736f)*(MagickRealType) i;
956         y_map[i].y=(-0.331264f)*(MagickRealType) i;
957         z_map[i].y=0.500000f*(MagickRealType) i;
958         x_map[i].z=0.500000f*(MagickRealType) i;
959         y_map[i].z=(-0.418688f)*(MagickRealType) i;
960         z_map[i].z=(-0.081312f)*(MagickRealType) i;
961       }
962       break;
963     }
964     case YUVColorspace:
965     default:
966     {
967       /*
968         Initialize YUV tables:
969
970           Y =  0.29900*R+0.58700*G+0.11400*B
971           U = -0.14740*R-0.28950*G+0.43690*B
972           V =  0.61500*R-0.51500*G-0.10000*B
973
974         U and V, normally -0.5 through 0.5, are normalized to the range 0
975         through QuantumRange.  Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
976       */
977       primary_info.y=(double) (MaxMap+1.0)/2.0;
978       primary_info.z=(double) (MaxMap+1.0)/2.0;
979 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
980   #pragma omp parallel for
981 #endif
982       for (i=0; i <= (long) MaxMap; i++)
983       {
984         x_map[i].x=0.29900f*(MagickRealType) i;
985         y_map[i].x=0.58700f*(MagickRealType) i;
986         z_map[i].x=0.11400f*(MagickRealType) i;
987         x_map[i].y=(-0.14740f)*(MagickRealType) i;
988         y_map[i].y=(-0.28950f)*(MagickRealType) i;
989         z_map[i].y=0.43690f*(MagickRealType) i;
990         x_map[i].z=0.61500f*(MagickRealType) i;
991         y_map[i].z=(-0.51500f)*(MagickRealType) i;
992         z_map[i].z=(-0.10000f)*(MagickRealType) i;
993       }
994       break;
995     }
996   }
997   /*
998     Convert from RGB.
999   */
1000   switch (image->storage_class)
1001   {
1002     case DirectClass:
1003     default:
1004     {
1005       /*
1006         Convert DirectClass image.
1007       */
1008       image_view=AcquireCacheView(image);
1009 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1010   #pragma omp parallel for shared(status)
1011 #endif
1012       for (y=0; y < (long) image->rows; y++)
1013       {
1014         MagickPixelPacket
1015           pixel;
1016
1017         register long
1018           x;
1019
1020         register PixelPacket
1021           *__restrict q;
1022
1023         register unsigned long
1024           blue,
1025           green,
1026           red;
1027
1028         if (status == MagickFalse)
1029           continue;
1030         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1031           exception);
1032         if (q == (PixelPacket *) NULL)
1033           {
1034             status=MagickFalse;
1035             continue;
1036           }
1037         for (x=0; x < (long) image->columns; x++)
1038         {
1039           red=ScaleQuantumToMap(q->red);
1040           green=ScaleQuantumToMap(q->green);
1041           blue=ScaleQuantumToMap(q->blue);
1042           pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
1043             (MagickRealType) primary_info.x;
1044           pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
1045             (MagickRealType) primary_info.y;
1046           pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
1047             (MagickRealType) primary_info.z;
1048           q->red=ScaleMapToQuantum(pixel.red);
1049           q->green=ScaleMapToQuantum(pixel.green);
1050           q->blue=ScaleMapToQuantum(pixel.blue);
1051           q++;
1052         }
1053         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1054         if (sync == MagickFalse)
1055           status=MagickFalse;
1056         if (image->progress_monitor != (MagickProgressMonitor) NULL)
1057           {
1058             MagickBooleanType
1059               proceed;
1060
1061 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1062   #pragma omp critical (MagickCore_RGBTransformImage)
1063 #endif
1064             proceed=SetImageProgress(image,RGBTransformImageTag,progress++,
1065               image->rows);
1066             if (proceed == MagickFalse)
1067               status=MagickFalse;
1068           }
1069       }
1070       image_view=DestroyCacheView(image_view);
1071       break;
1072     }
1073     case PseudoClass:
1074     {
1075       register unsigned long
1076         blue,
1077         green,
1078         red;
1079
1080       /*
1081         Convert PseudoClass image.
1082       */
1083       image_view=AcquireCacheView(image);
1084       for (i=0; i < (long) image->colors; i++)
1085       {
1086         MagickPixelPacket
1087           pixel;
1088
1089         red=ScaleQuantumToMap(image->colormap[i].red);
1090         green=ScaleQuantumToMap(image->colormap[i].green);
1091         blue=ScaleQuantumToMap(image->colormap[i].blue);
1092         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
1093         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
1094         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
1095         image->colormap[i].red=ScaleMapToQuantum(pixel.red);
1096         image->colormap[i].green=ScaleMapToQuantum(pixel.green);
1097         image->colormap[i].blue=ScaleMapToQuantum(pixel.blue);
1098       }
1099       image_view=DestroyCacheView(image_view);
1100       (void) SyncImage(image);
1101       break;
1102     }
1103   }
1104   /*
1105     Relinquish resources.
1106   */
1107   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1108   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1109   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1110   if (SetImageColorspace(image,colorspace) == MagickFalse)
1111     return(MagickFalse);
1112   return(status);
1113 }
1114 \f
1115 /*
1116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117 %                                                                             %
1118 %                                                                             %
1119 %                                                                             %
1120 %   S e t I m a g e C o l o r s p a c e                                       %
1121 %                                                                             %
1122 %                                                                             %
1123 %                                                                             %
1124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1125 %
1126 %  SetImageColorspace() sets the colorspace member of the Image structure.
1127 %
1128 %  The format of the SetImageColorspace method is:
1129 %
1130 %      MagickBooleanType SetImageColorspace(Image *image,
1131 %        const ColorspaceType colorspace)
1132 %
1133 %  A description of each parameter follows:
1134 %
1135 %    o image: the image.
1136 %
1137 %    o colorspace: the colorspace.
1138 %
1139 */
1140 MagickExport MagickBooleanType SetImageColorspace(Image *image,
1141   const ColorspaceType colorspace)
1142 {
1143   Cache
1144     cache;
1145
1146   if (image->colorspace == colorspace)
1147     return(MagickTrue);
1148   image->colorspace=colorspace;
1149   cache=GetImagePixelCache(image,MagickTrue,&image->exception);
1150   image->colorspace=colorspace;  /* GRAY colorspace might get reset to RGB */
1151   return(cache == (Cache) NULL ? MagickFalse: MagickTrue);
1152 }
1153 \f
1154 /*
1155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1156 %                                                                             %
1157 %                                                                             %
1158 %                                                                             %
1159 %   T r a n s f o r m I m a g e C o l o r s p a c e                           %
1160 %                                                                             %
1161 %                                                                             %
1162 %                                                                             %
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164 %
1165 %  TransformImageColorspace() transforms an image colorspace.
1166 %
1167 %  The format of the TransformImageColorspace method is:
1168 %
1169 %      MagickBooleanType TransformImageColorspace(Image *image,
1170 %        const ColorspaceType colorspace)
1171 %
1172 %  A description of each parameter follows:
1173 %
1174 %    o image: the image.
1175 %
1176 %    o colorspace: the colorspace.
1177 %
1178 */
1179 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
1180   const ColorspaceType colorspace)
1181 {
1182   MagickBooleanType
1183     status;
1184
1185   assert(image != (Image *) NULL);
1186   assert(image->signature == MagickSignature);
1187   if (image->debug != MagickFalse)
1188     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1189   if (colorspace == UndefinedColorspace)
1190     {
1191       if (SetImageColorspace(image,colorspace) == MagickFalse)
1192         return(MagickFalse);
1193       return(MagickTrue);
1194     }
1195   if (image->colorspace == colorspace)
1196     return(MagickTrue);
1197   if ((colorspace == RGBColorspace) || (colorspace == TransparentColorspace))
1198     return(TransformRGBImage(image,image->colorspace));
1199   status=MagickTrue;
1200   if ((image->colorspace != RGBColorspace) &&
1201       (image->colorspace != TransparentColorspace) &&
1202       (image->colorspace != GRAYColorspace))
1203     status=TransformRGBImage(image,image->colorspace);
1204   if (RGBTransformImage(image,colorspace) == MagickFalse)
1205     status=MagickFalse;
1206   return(status);
1207 }
1208 \f
1209 /*
1210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1211 %                                                                             %
1212 %                                                                             %
1213 %                                                                             %
1214 +     T r a n s f o r m R G B I m a g e                                       %
1215 %                                                                             %
1216 %                                                                             %
1217 %                                                                             %
1218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1219 %
1220 %  TransformRGBImage() converts the reference image from an alternate
1221 %  colorspace to RGB.  The transformation matrices are not the standard ones:
1222 %  the weights are rescaled to normalize the range of the transformed values to
1223 %  be [0..QuantumRange].
1224 %
1225 %  The format of the TransformRGBImage method is:
1226 %
1227 %      MagickBooleanType TransformRGBImage(Image *image,
1228 %        const ColorspaceType colorspace)
1229 %
1230 %  A description of each parameter follows:
1231 %
1232 %    o image: the image.
1233 %
1234 %    o colorspace: the colorspace to transform the image to.
1235 %
1236 */
1237
1238 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
1239   double *X,double *Y,double *Z)
1240 {
1241   double
1242     cube,
1243     x,
1244     y,
1245     z;
1246
1247   assert(X != (double *) NULL);
1248   assert(Y != (double *) NULL);
1249   assert(Z != (double *) NULL);
1250   y=(100.0*L+16.0)/116.0;
1251   x=255.0*(a > 0.5 ? a-1.0 : a)/500.0+y;
1252   z=y-255.0*(b > 0.5 ? b-1.0 : b)/200.0;
1253   cube=y*y*y;
1254   if (cube > 0.008856)
1255     y=cube;
1256   else
1257     y=(y-16.0/116.0)/7.787;
1258   cube=x*x*x;
1259   if (cube > 0.008856)
1260     x=cube;
1261   else
1262     x=(x-16.0/116.0)/7.787;
1263   cube=z*z*z;
1264   if (cube > 0.008856)
1265     z=cube;
1266   else
1267     z=(z-16.0/116.0)/7.787;
1268   *X=0.9504559271*x;
1269   *Y=1.0000000000*y;
1270   *Z=1.0890577508*z;
1271 }
1272
1273 static inline unsigned short RoundToYCC(const MagickRealType value)
1274 {
1275   if (value <= 0.0)
1276     return(0UL);
1277   if (value >= 350.0)
1278     return(350);
1279   return((unsigned short) (value+0.5));
1280 }
1281
1282 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
1283   Quantum *red,Quantum *green,Quantum *blue)
1284 {
1285   double
1286     b,
1287     g,
1288     r;
1289
1290   /*
1291     Convert XYZ to RGB colorspace.
1292   */
1293   assert(red != (Quantum *) NULL);
1294   assert(green != (Quantum *) NULL);
1295   assert(blue != (Quantum *) NULL);
1296   r=3.2404542*x-1.5371385*y-0.4985314*z;
1297   g=(-0.9692660*x+1.8760108*y+0.0415560*z);
1298   b=0.0556434*x-0.2040259*y+1.0572252*z;
1299   if (r > 0.0031308)
1300     r=1.055*pow(r,1.0/2.4)-0.055;
1301   else
1302     r*=12.92;
1303   if (g > 0.0031308)
1304     g=1.055*pow(g,1.0/2.4)-0.055;
1305   else
1306     g*=12.92;
1307   if (b > 0.0031308)
1308     b=1.055*pow(b,1.0/2.4)-0.055;
1309   else
1310     b*=12.92;
1311   *red=RoundToQuantum((MagickRealType) QuantumRange*r);
1312   *green=RoundToQuantum((MagickRealType) QuantumRange*g);
1313   *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
1314 }
1315
1316 static inline void ConvertCMYKToRGB(MagickPixelPacket *pixel)
1317 {
1318   pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red*
1319     (QuantumRange-pixel->index)+pixel->index);
1320   pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green*
1321     (QuantumRange-pixel->index)+pixel->index);
1322   pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue*
1323     (QuantumRange-pixel->index)+pixel->index);
1324 }
1325
1326 MagickExport MagickBooleanType TransformRGBImage(Image *image,
1327   const ColorspaceType colorspace)
1328 {
1329 #define D50X  (0.9642)
1330 #define D50Y  (1.0)
1331 #define D50Z  (0.8249)
1332 #define TransformRGBImageTag  "Transform/Image"
1333
1334 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1335   static const unsigned char
1336     YCCMap[351] =  /* Photo CD information beyond 100% white, Gamma 2.2 */
1337     {
1338         0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,
1339        14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
1340        28,  29,  30,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
1341        43,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  56,  57,  58,
1342        59,  60,  61,  62,  63,  64,  66,  67,  68,  69,  70,  71,  72,  73,
1343        74,  76,  77,  78,  79,  80,  81,  82,  83,  84,  86,  87,  88,  89,
1344        90,  91,  92,  93,  94,  95,  97,  98,  99, 100, 101, 102, 103, 104,
1345       105, 106, 107, 108, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
1346       120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134,
1347       135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
1348       149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
1349       163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
1350       176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
1351       190, 191, 192, 193, 193, 194, 195, 196, 197, 198, 199, 200, 201, 201,
1352       202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 211, 212, 213,
1353       214, 215, 215, 216, 217, 218, 218, 219, 220, 221, 221, 222, 223, 224,
1354       224, 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232, 233,
1355       234, 234, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240, 241, 241,
1356       242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 247,
1357       248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 251, 251, 251,
1358       251, 251, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253,
1359       253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254,
1360       254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255,
1361       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1362       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1363       255
1364     };
1365 #endif
1366
1367   ExceptionInfo
1368     *exception;
1369
1370   long
1371     progress,
1372     y;
1373
1374   MagickBooleanType
1375     status;
1376
1377   register long
1378     i;
1379
1380   TransformPacket
1381     *y_map,
1382     *x_map,
1383     *z_map;
1384
1385   CacheView
1386     *image_view;
1387
1388   assert(image != (Image *) NULL);
1389   assert(image->signature == MagickSignature);
1390   if (image->debug != MagickFalse)
1391     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1392   switch (colorspace)
1393   {
1394     case GRAYColorspace:
1395     case Rec601LumaColorspace:
1396     case Rec709LumaColorspace:
1397     case RGBColorspace:
1398     case TransparentColorspace:
1399     case UndefinedColorspace:
1400       return(MagickTrue);
1401     default:
1402       break;
1403   }
1404   status=MagickTrue;
1405   progress=0;
1406   exception=(&image->exception);
1407   switch (colorspace)
1408   {
1409     case CMYColorspace:
1410     {
1411       /*
1412         Transform image from CMY to RGB.
1413       */
1414       if (image->storage_class == PseudoClass)
1415         {
1416           if (SyncImage(image) == MagickFalse)
1417             return(MagickFalse);
1418           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1419             return(MagickFalse);
1420         }
1421       image_view=AcquireCacheView(image);
1422 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1423   #pragma omp parallel for shared(status)
1424 #endif
1425       for (y=0; y < (long) image->rows; y++)
1426       {
1427         MagickBooleanType
1428           sync;
1429
1430         register long
1431           x;
1432
1433         register PixelPacket
1434           *__restrict q;
1435
1436         if (status == MagickFalse)
1437           continue;
1438         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1439           exception);
1440         if (q == (PixelPacket *) NULL)
1441           {
1442             status=MagickFalse;
1443             continue;
1444           }
1445         for (x=0; x < (long) image->columns; x++)
1446         {
1447           q->red=RoundToQuantum((MagickRealType) (QuantumRange-q->red));
1448           q->green=RoundToQuantum((MagickRealType) (QuantumRange-q->green));
1449           q->blue=RoundToQuantum((MagickRealType) (QuantumRange-q->blue));
1450           q++;
1451         }
1452         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1453         if (sync == MagickFalse)
1454           status=MagickFalse;
1455       }
1456       image_view=DestroyCacheView(image_view);
1457       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1458         return(MagickFalse);
1459       return(status);
1460     }
1461     case CMYKColorspace:
1462     {
1463       MagickPixelPacket
1464         zero;
1465
1466       /*
1467         Transform image from CMYK to RGB.
1468       */
1469       if (image->storage_class == PseudoClass)
1470         {
1471           if (SyncImage(image) == MagickFalse)
1472             return(MagickFalse);
1473           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1474             return(MagickFalse);
1475         }
1476       GetMagickPixelPacket(image,&zero);
1477       image_view=AcquireCacheView(image);
1478 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1479   #pragma omp parallel for shared(status)
1480 #endif
1481       for (y=0; y < (long) image->rows; y++)
1482       {
1483         MagickBooleanType
1484           sync;
1485
1486         MagickPixelPacket
1487           pixel;
1488
1489         register IndexPacket
1490           *__restrict indexes;
1491
1492         register long
1493           x;
1494
1495         register PixelPacket
1496           *__restrict q;
1497
1498         if (status == MagickFalse)
1499           continue;
1500         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1501           exception);
1502         if (q == (PixelPacket *) NULL)
1503           {
1504             status=MagickFalse;
1505             continue;
1506           }
1507         indexes=GetCacheViewAuthenticIndexQueue(image_view);
1508         pixel=zero;
1509         for (x=0; x < (long) image->columns; x++)
1510         {
1511           SetMagickPixelPacket(image,q,indexes+x,&pixel);
1512           ConvertCMYKToRGB(&pixel);
1513           SetPixelPacket(image,&pixel,q,indexes+x);
1514           q++;
1515         }
1516         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1517         if (sync == MagickFalse)
1518           status=MagickFalse;
1519       }
1520       image_view=DestroyCacheView(image_view);
1521       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1522         return(MagickFalse);
1523       return(status);
1524     }
1525     case HSBColorspace:
1526     {
1527       /*
1528         Transform image from HSB to RGB.
1529       */
1530       if (image->storage_class == PseudoClass)
1531         {
1532           if (SyncImage(image) == MagickFalse)
1533             return(MagickFalse);
1534           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1535             return(MagickFalse);
1536         }
1537       image_view=AcquireCacheView(image);
1538 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1539   #pragma omp parallel for shared(status)
1540 #endif
1541       for (y=0; y < (long) image->rows; y++)
1542       {
1543         double
1544           brightness,
1545           hue,
1546           saturation;
1547
1548         MagickBooleanType
1549           sync;
1550
1551         register long
1552           x;
1553
1554         register PixelPacket
1555           *__restrict q;
1556
1557         if (status == MagickFalse)
1558           continue;
1559         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1560           exception);
1561         if (q == (PixelPacket *) NULL)
1562           {
1563             status=MagickFalse;
1564             continue;
1565           }
1566         for (x=0; x < (long) image->columns; x++)
1567         {
1568           hue=(double) (QuantumScale*q->red);
1569           saturation=(double) (QuantumScale*q->green);
1570           brightness=(double) (QuantumScale*q->blue);
1571           ConvertHSBToRGB(hue,saturation,brightness,&q->red,&q->green,&q->blue);
1572           q++;
1573         }
1574         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1575         if (sync == MagickFalse)
1576           status=MagickFalse;
1577       }
1578       image_view=DestroyCacheView(image_view);
1579       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1580         return(MagickFalse);
1581       return(status);
1582     }
1583     case HSLColorspace:
1584     {
1585       /*
1586         Transform image from HSL to RGB.
1587       */
1588       if (image->storage_class == PseudoClass)
1589         {
1590           if (SyncImage(image) == MagickFalse)
1591             return(MagickFalse);
1592           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1593             return(MagickFalse);
1594         }
1595       image_view=AcquireCacheView(image);
1596 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1597   #pragma omp parallel for shared(status)
1598 #endif
1599       for (y=0; y < (long) image->rows; y++)
1600       {
1601         double
1602           hue,
1603           lightness,
1604           saturation;
1605
1606         MagickBooleanType
1607           sync;
1608
1609         register long
1610           x;
1611
1612         register PixelPacket
1613           *__restrict q;
1614
1615         if (status == MagickFalse)
1616           continue;
1617         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1618           exception);
1619         if (q == (PixelPacket *) NULL)
1620           {
1621             status=MagickFalse;
1622             continue;
1623           }
1624         for (x=0; x < (long) image->columns; x++)
1625         {
1626           hue=(double) (QuantumScale*q->red);
1627           saturation=(double) (QuantumScale*q->green);
1628           lightness=(double) (QuantumScale*q->blue);
1629           ConvertHSLToRGB(hue,saturation,lightness,&q->red,&q->green,&q->blue);
1630           q++;
1631         }
1632         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1633         if (sync == MagickFalse)
1634           status=MagickFalse;
1635       }
1636       image_view=DestroyCacheView(image_view);
1637       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1638         return(MagickFalse);
1639       return(status);
1640     }
1641     case HWBColorspace:
1642     {
1643       /*
1644         Transform image from HWB to RGB.
1645       */
1646       if (image->storage_class == PseudoClass)
1647         {
1648           if (SyncImage(image) == MagickFalse)
1649             return(MagickFalse);
1650           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1651             return(MagickFalse);
1652         }
1653       image_view=AcquireCacheView(image);
1654 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1655   #pragma omp parallel for shared(status)
1656 #endif
1657       for (y=0; y < (long) image->rows; y++)
1658       {
1659         double
1660           blackness,
1661           hue,
1662           whiteness;
1663
1664         MagickBooleanType
1665           sync;
1666
1667         register long
1668           x;
1669
1670         register PixelPacket
1671           *__restrict q;
1672
1673         if (status == MagickFalse)
1674           continue;
1675         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1676           exception);
1677         if (q == (PixelPacket *) NULL)
1678           {
1679             status=MagickFalse;
1680             continue;
1681           }
1682         for (x=0; x < (long) image->columns; x++)
1683         {
1684           hue=(double) (QuantumScale*q->red);
1685           whiteness=(double) (QuantumScale*q->green);
1686           blackness=(double) (QuantumScale*q->blue);
1687           ConvertHWBToRGB(hue,whiteness,blackness,&q->red,&q->green,&q->blue);
1688           q++;
1689         }
1690         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1691         if (sync == MagickFalse)
1692           status=MagickFalse;
1693       }
1694       image_view=DestroyCacheView(image_view);
1695       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1696         return(MagickFalse);
1697       return(status);
1698     }
1699     case LabColorspace:
1700     {
1701       /*
1702         Transform image from Lab to RGB.
1703       */
1704       if (image->storage_class == PseudoClass)
1705         {
1706           if (SyncImage(image) == MagickFalse)
1707             return(MagickFalse);
1708           if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1709             return(MagickFalse);
1710         }
1711       image_view=AcquireCacheView(image);
1712 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1713   #pragma omp parallel for shared(status)
1714 #endif
1715       for (y=0; y < (long) image->rows; y++)
1716       {
1717         double
1718           a,
1719           b,
1720           L,
1721           X,
1722           Y,
1723           Z;
1724
1725         MagickBooleanType
1726           sync;
1727
1728         register long
1729           x;
1730
1731         register PixelPacket
1732           *__restrict q;
1733
1734         if (status == MagickFalse)
1735           continue;
1736         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1737           exception);
1738         if (q == (PixelPacket *) NULL)
1739           {
1740             status=MagickFalse;
1741             continue;
1742           }
1743         X=0.0;
1744         Y=0.0;
1745         Z=0.0;
1746         for (x=0; x < (long) image->columns; x++)
1747         {
1748           L=QuantumScale*q->red;
1749           a=QuantumScale*q->green;
1750           b=QuantumScale*q->blue;
1751           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
1752           ConvertXYZToRGB(X,Y,Z,&q->red,&q->green,&q->blue);
1753           q++;
1754         }
1755         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1756         if (sync == MagickFalse)
1757           status=MagickFalse;
1758       }
1759       image_view=DestroyCacheView(image_view);
1760       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1761         return(MagickFalse);
1762       return(status);
1763     }
1764     case LogColorspace:
1765     {
1766       const char
1767         *value;
1768
1769       double
1770         black,
1771         density,
1772         gamma,
1773         reference_black,
1774         reference_white;
1775
1776       Quantum
1777         *logmap;
1778
1779       /*
1780         Transform Log to RGB colorspace.
1781       */
1782       density=2.03728;
1783       gamma=DisplayGamma;
1784       value=GetImageProperty(image,"gamma");
1785       if (value != (const char *) NULL)
1786         gamma=1.0/atof(value) != 0.0 ? atof(value) : 1.0;
1787       reference_black=ReferenceBlack;
1788       value=GetImageProperty(image,"reference-black");
1789       if (value != (const char *) NULL)
1790         reference_black=atof(value);
1791       reference_white=ReferenceWhite;
1792       value=GetImageProperty(image,"reference-white");
1793       if (value != (const char *) NULL)
1794         reference_white=atof(value);
1795       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1796         sizeof(*logmap));
1797       if (logmap == (Quantum *) NULL)
1798         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1799           image->filename);
1800       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
1801         0.002/0.6);
1802       for (i=0; i <= (long) (reference_black*MaxMap/1024.0); i++)
1803         logmap[i]=(Quantum) 0;
1804       for ( ; i < (long) (reference_white*MaxMap/1024.0); i++)
1805         logmap[i]=RoundToQuantum((MagickRealType) QuantumRange/(1.0-black)*
1806           (pow(10.0,(1024.0*i/MaxMap-reference_white)*
1807           (gamma/density)*0.002/0.6)-black));
1808       for ( ; i <= (long) MaxMap; i++)
1809         logmap[i]=(Quantum) QuantumRange;
1810       if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1811         return(MagickFalse);
1812       image_view=AcquireCacheView(image);
1813 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1814   #pragma omp parallel for shared(status)
1815 #endif
1816       for (y=0; y < (long) image->rows; y++)
1817       {
1818         MagickBooleanType
1819           sync;
1820
1821         register long
1822           x;
1823
1824         register PixelPacket
1825           *__restrict q;
1826
1827         if (status == MagickFalse)
1828           continue;
1829         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1830           exception);
1831         if (q == (PixelPacket *) NULL)
1832           {
1833             status=MagickFalse;
1834             continue;
1835           }
1836         for (x=(long) image->columns; x != 0; x--)
1837         {
1838           q->red=logmap[ScaleQuantumToMap(q->red)];
1839           q->green=logmap[ScaleQuantumToMap(q->green)];
1840           q->blue=logmap[ScaleQuantumToMap(q->blue)];
1841           q++;
1842         }
1843         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1844         if (sync == MagickFalse)
1845           status=MagickFalse;
1846       }
1847       image_view=DestroyCacheView(image_view);
1848       logmap=(Quantum *) RelinquishMagickMemory(logmap);
1849       if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1850         return(MagickFalse);
1851       return(status);
1852     }
1853     default:
1854       break;
1855   }
1856   /*
1857     Allocate the tables.
1858   */
1859   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1860     sizeof(*x_map));
1861   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1862     sizeof(*y_map));
1863   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1864     sizeof(*z_map));
1865   if ((x_map == (TransformPacket *) NULL) ||
1866       (y_map == (TransformPacket *) NULL) ||
1867       (z_map == (TransformPacket *) NULL))
1868     {
1869       if (z_map != (TransformPacket *) NULL)
1870         z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1871       if (y_map != (TransformPacket *) NULL)
1872         y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1873       if (x_map != (TransformPacket *) NULL)
1874         x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1875       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1876         image->filename);
1877     }
1878   switch (colorspace)
1879   {
1880     case OHTAColorspace:
1881     {
1882       /*
1883         Initialize OHTA tables:
1884
1885           R = I1+1.00000*I2-0.66668*I3
1886           G = I1+0.00000*I2+1.33333*I3
1887           B = I1-1.00000*I2-0.66668*I3
1888
1889         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
1890         through QuantumRange.
1891       */
1892 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1893   #pragma omp parallel for
1894 #endif
1895       for (i=0; i <= (long) MaxMap; i++)
1896       {
1897         x_map[i].x=(MagickRealType) i;
1898         y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType)
1899           MaxMap);
1900         z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1901           MaxMap);
1902         x_map[i].y=(MagickRealType) i;
1903         y_map[i].y=0.000000f;
1904         z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType)
1905           MaxMap);
1906         x_map[i].z=(MagickRealType) i;
1907         y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1908           MaxMap);
1909         z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1910           MaxMap);
1911       }
1912       break;
1913     }
1914     case Rec601YCbCrColorspace:
1915     case YCbCrColorspace:
1916     {
1917       /*
1918         Initialize YCbCr tables:
1919
1920           R = Y            +1.402000*Cr
1921           G = Y-0.344136*Cb-0.714136*Cr
1922           B = Y+1.772000*Cb
1923
1924         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
1925         through QuantumRange.
1926       */
1927 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1928   #pragma omp parallel for
1929 #endif
1930       for (i=0; i <= (long) MaxMap; i++)
1931       {
1932         x_map[i].x=(MagickRealType) i;
1933         y_map[i].x=0.000000f;
1934         z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i-
1935           (MagickRealType) MaxMap);
1936         x_map[i].y=(MagickRealType) i;
1937         y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i-
1938           (MagickRealType) MaxMap);
1939         z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i-
1940           (MagickRealType) MaxMap);
1941         x_map[i].z=(MagickRealType) i;
1942         y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i-
1943           (MagickRealType) MaxMap);
1944         z_map[i].z=0.000000f;
1945       }
1946       break;
1947     }
1948     case Rec709YCbCrColorspace:
1949     {
1950       /*
1951         Initialize YCbCr tables:
1952
1953           R = Y            +1.574800*Cr
1954           G = Y-0.187324*Cb-0.468124*Cr
1955           B = Y+1.855600*Cb
1956
1957         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
1958         through QuantumRange.
1959       */
1960 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1961   #pragma omp parallel for
1962 #endif
1963       for (i=0; i <= (long) MaxMap; i++)
1964       {
1965         x_map[i].x=(MagickRealType) i;
1966         y_map[i].x=0.000000f;
1967         z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i-
1968           (MagickRealType) MaxMap);
1969         x_map[i].y=(MagickRealType) i;
1970         y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i-
1971           (MagickRealType) MaxMap);
1972         z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i-
1973           (MagickRealType) MaxMap);
1974         x_map[i].z=(MagickRealType) i;
1975         y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i-
1976           (MagickRealType) MaxMap);
1977         z_map[i].z=0.00000f;
1978       }
1979       break;
1980     }
1981     case sRGBColorspace:
1982     {
1983       /*
1984         Nonlinear sRGB to linear RGB.
1985
1986           R = 1.0*R+0.0*G+0.0*B
1987           G = 0.0*R+1.0*G+0.0*B
1988           B = 0.0*R+0.0*G+1.0*B
1989       */
1990 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1991   #pragma omp parallel for
1992 #endif
1993       for (i=0; i <= (long) MaxMap; i++)
1994       {
1995         x_map[i].x=1.0f*(MagickRealType) i;
1996         y_map[i].x=0.0f*(MagickRealType) i;
1997         z_map[i].x=0.0f*(MagickRealType) i;
1998         x_map[i].y=0.0f*(MagickRealType) i;
1999         y_map[i].y=1.0f*(MagickRealType) i;
2000         z_map[i].y=0.0f*(MagickRealType) i;
2001         x_map[i].z=0.0f*(MagickRealType) i;
2002         y_map[i].z=0.0f*(MagickRealType) i;
2003         z_map[i].z=1.0f*(MagickRealType) i;
2004       }
2005       break;
2006     }
2007     case XYZColorspace:
2008     {
2009       /*
2010         Initialize CIE XYZ tables (ITU R-709 RGB):
2011
2012           R =  3.2404542*X-1.5371385*Y-0.4985314*Z
2013           G = -0.9692660*X+1.8760108*Y+0.0415560*Z
2014           B =  0.0556434*X-0.2040259*Y+1.057225*Z
2015       */
2016 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2017   #pragma omp parallel for
2018 #endif
2019       for (i=0; i <= (long) MaxMap; i++)
2020       {
2021         x_map[i].x=3.2404542f*(MagickRealType) i;
2022         x_map[i].y=(-0.9692660f)*(MagickRealType) i;
2023         x_map[i].z=0.0556434f*(MagickRealType) i;
2024         y_map[i].x=(-1.5371385f)*(MagickRealType) i;
2025         y_map[i].y=1.8760108f*(MagickRealType) i;
2026         y_map[i].z=(-0.2040259f)*(MagickRealType) i;
2027         z_map[i].x=(-0.4985314f)*(MagickRealType) i;
2028         z_map[i].y=0.0415560f*(MagickRealType) i;
2029         z_map[i].z=1.0572252f*(MagickRealType) i;
2030       }
2031       break;
2032     }
2033     case YCCColorspace:
2034     {
2035       /*
2036         Initialize YCC tables:
2037
2038           R = Y            +1.340762*C2
2039           G = Y-0.317038*C1-0.682243*C2
2040           B = Y+1.632639*C1
2041
2042         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
2043       */
2044 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2045   #pragma omp parallel for
2046 #endif
2047       for (i=0; i <= (long) MaxMap; i++)
2048       {
2049         x_map[i].x=1.3584000f*(MagickRealType) i;
2050         y_map[i].x=0.0000000f;
2051         z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType)
2052           ScaleQuantumToMap(ScaleCharToQuantum(137)));
2053         x_map[i].y=1.3584000f*(MagickRealType) i;
2054         y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType)
2055           ScaleQuantumToMap(ScaleCharToQuantum(156)));
2056         z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType)
2057           ScaleQuantumToMap(ScaleCharToQuantum(137)));
2058         x_map[i].z=1.3584000f*(MagickRealType) i;
2059         y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType)
2060           ScaleQuantumToMap(ScaleCharToQuantum(156)));
2061         z_map[i].z=0.0000000f;
2062       }
2063       break;
2064     }
2065     case YIQColorspace:
2066     {
2067       /*
2068         Initialize YIQ tables:
2069
2070           R = Y+0.95620*I+0.62140*Q
2071           G = Y-0.27270*I-0.64680*Q
2072           B = Y-1.10370*I+1.70060*Q
2073
2074         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2075         through QuantumRange.
2076       */
2077 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2078   #pragma omp parallel for
2079 #endif
2080       for (i=0; i <= (long) MaxMap; i++)
2081       {
2082         x_map[i].x=(MagickRealType) i;
2083         y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType)
2084           MaxMap);
2085         z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType)
2086           MaxMap);
2087         x_map[i].y=(MagickRealType) i;
2088         y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2089           MaxMap);
2090         z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2091           MaxMap);
2092         x_map[i].z=(MagickRealType) i;
2093         y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2094           MaxMap);
2095         z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType)
2096           MaxMap);
2097       }
2098       break;
2099     }
2100     case YPbPrColorspace:
2101     {
2102       /*
2103         Initialize YPbPr tables:
2104
2105           R = Y            +1.402000*C2
2106           G = Y-0.344136*C1+0.714136*C2
2107           B = Y+1.772000*C1
2108
2109         Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
2110         through QuantumRange.
2111       */
2112 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2113   #pragma omp parallel for
2114 #endif
2115       for (i=0; i <= (long) MaxMap; i++)
2116       {
2117         x_map[i].x=(MagickRealType) i;
2118         y_map[i].x=0.000000f;
2119         z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType)
2120           MaxMap);
2121         x_map[i].y=(MagickRealType) i;
2122         y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2123           MaxMap);
2124         z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType)
2125           MaxMap);
2126         x_map[i].z=(MagickRealType) i;
2127         y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType)
2128           MaxMap);
2129         z_map[i].z=0.00000f;
2130       }
2131       break;
2132     }
2133     case YUVColorspace:
2134     default:
2135     {
2136       /*
2137         Initialize YUV tables:
2138
2139           R = Y          +1.13980*V
2140           G = Y-0.39380*U-0.58050*V
2141           B = Y+2.02790*U
2142
2143         U and V, normally -0.5 through 0.5, must be normalized to the range 0
2144         through QuantumRange.
2145       */
2146 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2147   #pragma omp parallel for
2148 #endif
2149       for (i=0; i <= (long) MaxMap; i++)
2150       {
2151         x_map[i].x=(MagickRealType) i;
2152         y_map[i].x=0.00000f;
2153         z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType)
2154           MaxMap);
2155         x_map[i].y=(MagickRealType) i;
2156         y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2157           MaxMap);
2158         z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2159           MaxMap);
2160         x_map[i].z=(MagickRealType) i;
2161         y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType)
2162           MaxMap);
2163         z_map[i].z=0.00000f;
2164       }
2165       break;
2166     }
2167   }
2168   /*
2169     Convert to RGB.
2170   */
2171   switch (image->storage_class)
2172   {
2173     case DirectClass:
2174     default:
2175     {
2176       /*
2177         Convert DirectClass image.
2178       */
2179       image_view=AcquireCacheView(image);
2180 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2181   #pragma omp parallel for shared(status)
2182 #endif
2183       for (y=0; y < (long) image->rows; y++)
2184       {
2185         MagickBooleanType
2186           sync;
2187
2188         MagickPixelPacket
2189           pixel;
2190
2191         register long
2192           x;
2193
2194         register PixelPacket
2195           *__restrict q;
2196
2197         if (status == MagickFalse)
2198           continue;
2199         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2200           exception);
2201         if (q == (PixelPacket *) NULL)
2202           {
2203             status=MagickFalse;
2204             continue;
2205           }
2206         for (x=0; x < (long) image->columns; x++)
2207         {
2208           register unsigned long
2209             blue,
2210             green,
2211             red;
2212
2213           red=ScaleQuantumToMap(q->red);
2214           green=ScaleQuantumToMap(q->green);
2215           blue=ScaleQuantumToMap(q->blue);
2216           pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2217           pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2218           pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2219           switch (colorspace)
2220           {
2221             case YCCColorspace:
2222             {
2223 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2224               pixel.red=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2225                 255.0*QuantumScale*pixel.red)]);
2226               pixel.green=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2227                 255.0*QuantumScale*pixel.green)]);
2228               pixel.blue=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2229                 255.0*QuantumScale*pixel.blue)]);
2230 #endif
2231               break;
2232             }
2233             case sRGBColorspace:
2234             {
2235               if ((QuantumScale*pixel.red) <= 0.0031308)
2236                 pixel.red*=12.92f;
2237               else
2238                 pixel.red=(MagickRealType) QuantumRange*(1.055*
2239                   pow(QuantumScale*pixel.red,(1.0/2.4))-0.055);
2240               if ((QuantumScale*pixel.green) <= 0.0031308)
2241                 pixel.green*=12.92f;
2242               else
2243                 pixel.green=(MagickRealType) QuantumRange*(1.055*
2244                   pow(QuantumScale*pixel.green,(1.0/2.4))-0.055);
2245               if ((QuantumScale*pixel.blue) <= 0.0031308)
2246                 pixel.blue*=12.92f;
2247               else
2248                 pixel.blue=(MagickRealType) QuantumRange*(1.055*
2249                   pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055);
2250               break;
2251             }
2252             default:
2253               break;
2254           }
2255           q->red=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2256             pixel.red);
2257           q->green=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2258             pixel.green);
2259           q->blue=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2260             pixel.blue);
2261           q++;
2262         }
2263         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2264         if (sync == MagickFalse)
2265           status=MagickFalse;
2266         if (image->progress_monitor != (MagickProgressMonitor) NULL)
2267           {
2268             MagickBooleanType
2269               proceed;
2270
2271 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2272   #pragma omp critical (MagickCore_TransformRGBImage)
2273 #endif
2274             proceed=SetImageProgress(image,TransformRGBImageTag,progress++,
2275               image->rows);
2276             if (proceed == MagickFalse)
2277               status=MagickFalse;
2278           }
2279       }
2280       image_view=DestroyCacheView(image_view);
2281       break;
2282     }
2283     case PseudoClass:
2284     {
2285       /*
2286         Convert PseudoClass image.
2287       */
2288       image_view=AcquireCacheView(image);
2289 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2290   #pragma omp parallel for shared(status)
2291 #endif
2292       for (i=0; i < (long) image->colors; i++)
2293       {
2294         MagickPixelPacket
2295           pixel;
2296
2297         register unsigned long
2298           blue,
2299           green,
2300           red;
2301
2302         red=ScaleQuantumToMap(image->colormap[i].red);
2303         green=ScaleQuantumToMap(image->colormap[i].green);
2304         blue=ScaleQuantumToMap(image->colormap[i].blue);
2305         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2306         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2307         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2308         switch (colorspace)
2309         {
2310           case YCCColorspace:
2311           {
2312 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2313             image->colormap[i].red=ScaleCharToQuantum(YCCMap[RoundToYCC(
2314               255.0*QuantumScale*pixel.red)]);
2315             image->colormap[i].green=ScaleCharToQuantum(YCCMap[RoundToYCC(
2316               255.0*QuantumScale*pixel.green)]);
2317             image->colormap[i].blue=ScaleCharToQuantum(YCCMap[RoundToYCC(
2318               255.0*QuantumScale*pixel.blue)]);
2319 #endif
2320             break;
2321           }
2322           case sRGBColorspace:
2323           {
2324             if ((QuantumScale*pixel.red) <= 0.0031308)
2325               pixel.red*=12.92f;
2326             else
2327               pixel.red=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2328                 pixel.red,(1.0/2.4))-0.055);
2329             if ((QuantumScale*pixel.green) <= 0.0031308)
2330               pixel.green*=12.92f;
2331             else
2332               pixel.green=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2333                 pixel.green,(1.0/2.4))-0.055);
2334             if ((QuantumScale*pixel.blue) <= 0.0031308)
2335               pixel.blue*=12.92f;
2336             else
2337               pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2338                 pixel.blue,(1.0/2.4))-0.055);
2339           }
2340           default:
2341           {
2342             image->colormap[i].red=ScaleMapToQuantum((MagickRealType) MaxMap*
2343               QuantumScale*pixel.red);
2344             image->colormap[i].green=ScaleMapToQuantum((MagickRealType) MaxMap*
2345               QuantumScale*pixel.green);
2346             image->colormap[i].blue=ScaleMapToQuantum((MagickRealType) MaxMap*
2347               QuantumScale*pixel.blue);
2348             break;
2349           }
2350         }
2351       }
2352       image_view=DestroyCacheView(image_view);
2353       (void) SyncImage(image);
2354       break;
2355     }
2356   }
2357   /*
2358     Relinquish resources.
2359   */
2360   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2361   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2362   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2363   if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
2364     return(MagickFalse);
2365   return(MagickTrue);
2366 }