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