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