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