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