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