]> 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.04045)
129     r=pow((r+0.055)/1.055,2.4);
130   else
131     r/=12.92;
132   g=QuantumScale*green;
133   if (g > 0.04045)
134     g=pow((g+0.055)/1.055,2.4);
135   else
136     g/=12.92;
137   b=QuantumScale*blue;
138   if (b > 0.04045)
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=AcquireCacheView(image);
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=AcquireCacheView(image);
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=AcquireCacheView(image);
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=AcquireCacheView(image);
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=AcquireCacheView(image);
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=AcquireCacheView(image);
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=AcquireCacheView(image);
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.04045f)
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=AcquireCacheView(image);
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.
1248 %
1249 %  The format of the TransformImageColorspace method is:
1250 %
1251 %      MagickBooleanType TransformImageColorspace(Image *image,
1252 %        const ColorspaceType colorspace,ExceptionInfo *exception)
1253 %
1254 %  A description of each parameter follows:
1255 %
1256 %    o image: the image.
1257 %
1258 %    o colorspace: the colorspace.
1259 %
1260 %   o exception: return any errors or warnings in this structure.
1261 %
1262 */
1263 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
1264   const ColorspaceType colorspace,ExceptionInfo *exception)
1265 {
1266   MagickBooleanType
1267     status;
1268
1269   assert(image != (Image *) NULL);
1270   assert(image->signature == MagickSignature);
1271   if (image->debug != MagickFalse)
1272     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1273   if (colorspace == UndefinedColorspace)
1274     return(SetImageColorspace(image,colorspace,exception));
1275   if (image->colorspace == colorspace)
1276     return(MagickTrue);  /* same colorspace: no op */
1277   /*
1278     Convert the reference image from an alternate colorspace to RGB.
1279   */
1280   if ((colorspace == sRGBColorspace) || (colorspace == TransparentColorspace))
1281     return(TransformsRGBImage(image,colorspace,exception));
1282   status=MagickTrue;
1283   if (IssRGBColorspace(image->colorspace) == MagickFalse)
1284     status=TransformsRGBImage(image,image->colorspace,exception);
1285   /*
1286     Convert the reference image from RGB to an alternate colorspace.
1287   */
1288   if (sRGBTransformImage(image,colorspace,exception) == MagickFalse)
1289     status=MagickFalse;
1290   return(status);
1291 }
1292 \f
1293 /*
1294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1295 %                                                                             %
1296 %                                                                             %
1297 %                                                                             %
1298 +     T r a n s f o r m s R G B I m a g e                                     %
1299 %                                                                             %
1300 %                                                                             %
1301 %                                                                             %
1302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1303 %
1304 %  TransformsRGBImage() converts the reference image from an alternate
1305 %  colorspace to sRGB.  The transformation matrices are not the standard ones:
1306 %  the weights are rescaled to normalize the range of the transformed values to
1307 %  be [0..QuantumRange].
1308 %
1309 %  The format of the TransformsRGBImage method is:
1310 %
1311 %      MagickBooleanType TransformsRGBImage(Image *image,
1312 %        const ColorspaceType colorspace,ExceptionInfo *exception)
1313 %
1314 %  A description of each parameter follows:
1315 %
1316 %    o image: the image.
1317 %
1318 %    o colorspace: the colorspace to transform the image to.
1319 %
1320 %   o exception: return any errors or warnings in this structure.
1321 %
1322 */
1323
1324 static double LabF2(double alpha)
1325 {
1326   double
1327     beta;
1328
1329   if (alpha > (24.0/116.0))
1330     return(alpha*alpha*alpha);
1331   beta=(108.0/841.0)*(alpha-(16.0/116.0));
1332   if (beta > 0.0)
1333     return(beta);
1334   return(0.0);
1335 }
1336
1337 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
1338   double *X,double *Y,double *Z)
1339 {
1340
1341   double
1342     x,
1343     y,
1344     z;
1345
1346   assert(X != (double *) NULL);
1347   assert(Y != (double *) NULL);
1348   assert(Z != (double *) NULL);
1349   *X=0.0;
1350   *Y=0.0;
1351   *Z=0.0;
1352   if (L <= 0.0)
1353     return;
1354   y=(100.0*L+16.0)/116.0;
1355   x=y+255.0*0.002*(a > 0.5 ? a-1.0 : a);
1356   z=y-255.0*0.005*(b > 0.5 ? b-1.0 : b);
1357   *X=D50X*LabF2(x);
1358   *Y=D50Y*LabF2(y);
1359   *Z=D50Z*LabF2(z);
1360 }
1361
1362 static inline ssize_t RoundToYCC(const MagickRealType value)
1363 {
1364   if (value <= 0.0)
1365     return(0);
1366   if (value >= 1388.0)
1367     return(1388);
1368   return((ssize_t) (value+0.5));
1369 }
1370
1371 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
1372   Quantum *red,Quantum *green,Quantum *blue)
1373 {
1374   double
1375     b,
1376     g,
1377     r;
1378
1379   /*
1380     Convert XYZ to RGB colorspace.
1381   */
1382   assert(red != (Quantum *) NULL);
1383   assert(green != (Quantum *) NULL);
1384   assert(blue != (Quantum *) NULL);
1385   r=3.2404542*x-1.5371385*y-0.4985314*z;
1386   g=(-0.9692660*x+1.8760108*y+0.0415560*z);
1387   b=0.0556434*x-0.2040259*y+1.0572252*z;
1388   if (r > 0.0031308)
1389     r=1.055*pow(r,1.0/2.4)-0.055;
1390   else
1391     r*=12.92;
1392   if (g > 0.0031308)
1393     g=1.055*pow(g,1.0/2.4)-0.055;
1394   else
1395     g*=12.92;
1396   if (b > 0.0031308)
1397     b=1.055*pow(b,1.0/2.4)-0.055;
1398   else
1399     b*=12.92;
1400   *red=RoundToQuantum((MagickRealType) QuantumRange*r);
1401   *green=RoundToQuantum((MagickRealType) QuantumRange*g);
1402   *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
1403 }
1404
1405 static inline void ConvertCMYKToRGB(PixelInfo *pixel)
1406 {
1407   pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red*
1408     (QuantumRange-pixel->black)+pixel->black);
1409   pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green*
1410     (QuantumRange-pixel->black)+pixel->black);
1411   pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue*
1412     (QuantumRange-pixel->black)+pixel->black);
1413 }
1414
1415 static MagickBooleanType TransformsRGBImage(Image *image,
1416   const ColorspaceType colorspace,ExceptionInfo *exception)
1417 {
1418 #define D50X  (0.9642)
1419 #define D50Y  (1.0)
1420 #define D50Z  (0.8249)
1421 #define TransformsRGBImageTag  "Transform/Image"
1422
1423 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1424   static const float
1425     YCCMap[1389] =
1426     {
1427       0.000000f, 0.000720f, 0.001441f, 0.002161f, 0.002882f, 0.003602f,
1428       0.004323f, 0.005043f, 0.005764f, 0.006484f, 0.007205f, 0.007925f,
1429       0.008646f, 0.009366f, 0.010086f, 0.010807f, 0.011527f, 0.012248f,
1430       0.012968f, 0.013689f, 0.014409f, 0.015130f, 0.015850f, 0.016571f,
1431       0.017291f, 0.018012f, 0.018732f, 0.019452f, 0.020173f, 0.020893f,
1432       0.021614f, 0.022334f, 0.023055f, 0.023775f, 0.024496f, 0.025216f,
1433       0.025937f, 0.026657f, 0.027378f, 0.028098f, 0.028818f, 0.029539f,
1434       0.030259f, 0.030980f, 0.031700f, 0.032421f, 0.033141f, 0.033862f,
1435       0.034582f, 0.035303f, 0.036023f, 0.036744f, 0.037464f, 0.038184f,
1436       0.038905f, 0.039625f, 0.040346f, 0.041066f, 0.041787f, 0.042507f,
1437       0.043228f, 0.043948f, 0.044669f, 0.045389f, 0.046110f, 0.046830f,
1438       0.047550f, 0.048271f, 0.048991f, 0.049712f, 0.050432f, 0.051153f,
1439       0.051873f, 0.052594f, 0.053314f, 0.054035f, 0.054755f, 0.055476f,
1440       0.056196f, 0.056916f, 0.057637f, 0.058357f, 0.059078f, 0.059798f,
1441       0.060519f, 0.061239f, 0.061960f, 0.062680f, 0.063401f, 0.064121f,
1442       0.064842f, 0.065562f, 0.066282f, 0.067003f, 0.067723f, 0.068444f,
1443       0.069164f, 0.069885f, 0.070605f, 0.071326f, 0.072046f, 0.072767f,
1444       0.073487f, 0.074207f, 0.074928f, 0.075648f, 0.076369f, 0.077089f,
1445       0.077810f, 0.078530f, 0.079251f, 0.079971f, 0.080692f, 0.081412f,
1446       0.082133f, 0.082853f, 0.083573f, 0.084294f, 0.085014f, 0.085735f,
1447       0.086455f, 0.087176f, 0.087896f, 0.088617f, 0.089337f, 0.090058f,
1448       0.090778f, 0.091499f, 0.092219f, 0.092939f, 0.093660f, 0.094380f,
1449       0.095101f, 0.095821f, 0.096542f, 0.097262f, 0.097983f, 0.098703f,
1450       0.099424f, 0.100144f, 0.100865f, 0.101585f, 0.102305f, 0.103026f,
1451       0.103746f, 0.104467f, 0.105187f, 0.105908f, 0.106628f, 0.107349f,
1452       0.108069f, 0.108790f, 0.109510f, 0.110231f, 0.110951f, 0.111671f,
1453       0.112392f, 0.113112f, 0.113833f, 0.114553f, 0.115274f, 0.115994f,
1454       0.116715f, 0.117435f, 0.118156f, 0.118876f, 0.119597f, 0.120317f,
1455       0.121037f, 0.121758f, 0.122478f, 0.123199f, 0.123919f, 0.124640f,
1456       0.125360f, 0.126081f, 0.126801f, 0.127522f, 0.128242f, 0.128963f,
1457       0.129683f, 0.130403f, 0.131124f, 0.131844f, 0.132565f, 0.133285f,
1458       0.134006f, 0.134726f, 0.135447f, 0.136167f, 0.136888f, 0.137608f,
1459       0.138329f, 0.139049f, 0.139769f, 0.140490f, 0.141210f, 0.141931f,
1460       0.142651f, 0.143372f, 0.144092f, 0.144813f, 0.145533f, 0.146254f,
1461       0.146974f, 0.147695f, 0.148415f, 0.149135f, 0.149856f, 0.150576f,
1462       0.151297f, 0.152017f, 0.152738f, 0.153458f, 0.154179f, 0.154899f,
1463       0.155620f, 0.156340f, 0.157061f, 0.157781f, 0.158501f, 0.159222f,
1464       0.159942f, 0.160663f, 0.161383f, 0.162104f, 0.162824f, 0.163545f,
1465       0.164265f, 0.164986f, 0.165706f, 0.166427f, 0.167147f, 0.167867f,
1466       0.168588f, 0.169308f, 0.170029f, 0.170749f, 0.171470f, 0.172190f,
1467       0.172911f, 0.173631f, 0.174352f, 0.175072f, 0.175793f, 0.176513f,
1468       0.177233f, 0.177954f, 0.178674f, 0.179395f, 0.180115f, 0.180836f,
1469       0.181556f, 0.182277f, 0.182997f, 0.183718f, 0.184438f, 0.185159f,
1470       0.185879f, 0.186599f, 0.187320f, 0.188040f, 0.188761f, 0.189481f,
1471       0.190202f, 0.190922f, 0.191643f, 0.192363f, 0.193084f, 0.193804f,
1472       0.194524f, 0.195245f, 0.195965f, 0.196686f, 0.197406f, 0.198127f,
1473       0.198847f, 0.199568f, 0.200288f, 0.201009f, 0.201729f, 0.202450f,
1474       0.203170f, 0.203890f, 0.204611f, 0.205331f, 0.206052f, 0.206772f,
1475       0.207493f, 0.208213f, 0.208934f, 0.209654f, 0.210375f, 0.211095f,
1476       0.211816f, 0.212536f, 0.213256f, 0.213977f, 0.214697f, 0.215418f,
1477       0.216138f, 0.216859f, 0.217579f, 0.218300f, 0.219020f, 0.219741f,
1478       0.220461f, 0.221182f, 0.221902f, 0.222622f, 0.223343f, 0.224063f,
1479       0.224784f, 0.225504f, 0.226225f, 0.226945f, 0.227666f, 0.228386f,
1480       0.229107f, 0.229827f, 0.230548f, 0.231268f, 0.231988f, 0.232709f,
1481       0.233429f, 0.234150f, 0.234870f, 0.235591f, 0.236311f, 0.237032f,
1482       0.237752f, 0.238473f, 0.239193f, 0.239914f, 0.240634f, 0.241354f,
1483       0.242075f, 0.242795f, 0.243516f, 0.244236f, 0.244957f, 0.245677f,
1484       0.246398f, 0.247118f, 0.247839f, 0.248559f, 0.249280f, 0.250000f,
1485       0.250720f, 0.251441f, 0.252161f, 0.252882f, 0.253602f, 0.254323f,
1486       0.255043f, 0.255764f, 0.256484f, 0.257205f, 0.257925f, 0.258646f,
1487       0.259366f, 0.260086f, 0.260807f, 0.261527f, 0.262248f, 0.262968f,
1488       0.263689f, 0.264409f, 0.265130f, 0.265850f, 0.266571f, 0.267291f,
1489       0.268012f, 0.268732f, 0.269452f, 0.270173f, 0.270893f, 0.271614f,
1490       0.272334f, 0.273055f, 0.273775f, 0.274496f, 0.275216f, 0.275937f,
1491       0.276657f, 0.277378f, 0.278098f, 0.278818f, 0.279539f, 0.280259f,
1492       0.280980f, 0.281700f, 0.282421f, 0.283141f, 0.283862f, 0.284582f,
1493       0.285303f, 0.286023f, 0.286744f, 0.287464f, 0.288184f, 0.288905f,
1494       0.289625f, 0.290346f, 0.291066f, 0.291787f, 0.292507f, 0.293228f,
1495       0.293948f, 0.294669f, 0.295389f, 0.296109f, 0.296830f, 0.297550f,
1496       0.298271f, 0.298991f, 0.299712f, 0.300432f, 0.301153f, 0.301873f,
1497       0.302594f, 0.303314f, 0.304035f, 0.304755f, 0.305476f, 0.306196f,
1498       0.306916f, 0.307637f, 0.308357f, 0.309078f, 0.309798f, 0.310519f,
1499       0.311239f, 0.311960f, 0.312680f, 0.313401f, 0.314121f, 0.314842f,
1500       0.315562f, 0.316282f, 0.317003f, 0.317723f, 0.318444f, 0.319164f,
1501       0.319885f, 0.320605f, 0.321326f, 0.322046f, 0.322767f, 0.323487f,
1502       0.324207f, 0.324928f, 0.325648f, 0.326369f, 0.327089f, 0.327810f,
1503       0.328530f, 0.329251f, 0.329971f, 0.330692f, 0.331412f, 0.332133f,
1504       0.332853f, 0.333573f, 0.334294f, 0.335014f, 0.335735f, 0.336455f,
1505       0.337176f, 0.337896f, 0.338617f, 0.339337f, 0.340058f, 0.340778f,
1506       0.341499f, 0.342219f, 0.342939f, 0.343660f, 0.344380f, 0.345101f,
1507       0.345821f, 0.346542f, 0.347262f, 0.347983f, 0.348703f, 0.349424f,
1508       0.350144f, 0.350865f, 0.351585f, 0.352305f, 0.353026f, 0.353746f,
1509       0.354467f, 0.355187f, 0.355908f, 0.356628f, 0.357349f, 0.358069f,
1510       0.358790f, 0.359510f, 0.360231f, 0.360951f, 0.361671f, 0.362392f,
1511       0.363112f, 0.363833f, 0.364553f, 0.365274f, 0.365994f, 0.366715f,
1512       0.367435f, 0.368156f, 0.368876f, 0.369597f, 0.370317f, 0.371037f,
1513       0.371758f, 0.372478f, 0.373199f, 0.373919f, 0.374640f, 0.375360f,
1514       0.376081f, 0.376801f, 0.377522f, 0.378242f, 0.378963f, 0.379683f,
1515       0.380403f, 0.381124f, 0.381844f, 0.382565f, 0.383285f, 0.384006f,
1516       0.384726f, 0.385447f, 0.386167f, 0.386888f, 0.387608f, 0.388329f,
1517       0.389049f, 0.389769f, 0.390490f, 0.391210f, 0.391931f, 0.392651f,
1518       0.393372f, 0.394092f, 0.394813f, 0.395533f, 0.396254f, 0.396974f,
1519       0.397695f, 0.398415f, 0.399135f, 0.399856f, 0.400576f, 0.401297f,
1520       0.402017f, 0.402738f, 0.403458f, 0.404179f, 0.404899f, 0.405620f,
1521       0.406340f, 0.407061f, 0.407781f, 0.408501f, 0.409222f, 0.409942f,
1522       0.410663f, 0.411383f, 0.412104f, 0.412824f, 0.413545f, 0.414265f,
1523       0.414986f, 0.415706f, 0.416427f, 0.417147f, 0.417867f, 0.418588f,
1524       0.419308f, 0.420029f, 0.420749f, 0.421470f, 0.422190f, 0.422911f,
1525       0.423631f, 0.424352f, 0.425072f, 0.425793f, 0.426513f, 0.427233f,
1526       0.427954f, 0.428674f, 0.429395f, 0.430115f, 0.430836f, 0.431556f,
1527       0.432277f, 0.432997f, 0.433718f, 0.434438f, 0.435158f, 0.435879f,
1528       0.436599f, 0.437320f, 0.438040f, 0.438761f, 0.439481f, 0.440202f,
1529       0.440922f, 0.441643f, 0.442363f, 0.443084f, 0.443804f, 0.444524f,
1530       0.445245f, 0.445965f, 0.446686f, 0.447406f, 0.448127f, 0.448847f,
1531       0.449568f, 0.450288f, 0.451009f, 0.451729f, 0.452450f, 0.453170f,
1532       0.453891f, 0.454611f, 0.455331f, 0.456052f, 0.456772f, 0.457493f,
1533       0.458213f, 0.458934f, 0.459654f, 0.460375f, 0.461095f, 0.461816f,
1534       0.462536f, 0.463256f, 0.463977f, 0.464697f, 0.465418f, 0.466138f,
1535       0.466859f, 0.467579f, 0.468300f, 0.469020f, 0.469741f, 0.470461f,
1536       0.471182f, 0.471902f, 0.472622f, 0.473343f, 0.474063f, 0.474784f,
1537       0.475504f, 0.476225f, 0.476945f, 0.477666f, 0.478386f, 0.479107f,
1538       0.479827f, 0.480548f, 0.481268f, 0.481988f, 0.482709f, 0.483429f,
1539       0.484150f, 0.484870f, 0.485591f, 0.486311f, 0.487032f, 0.487752f,
1540       0.488473f, 0.489193f, 0.489914f, 0.490634f, 0.491354f, 0.492075f,
1541       0.492795f, 0.493516f, 0.494236f, 0.494957f, 0.495677f, 0.496398f,
1542       0.497118f, 0.497839f, 0.498559f, 0.499280f, 0.500000f, 0.500720f,
1543       0.501441f, 0.502161f, 0.502882f, 0.503602f, 0.504323f, 0.505043f,
1544       0.505764f, 0.506484f, 0.507205f, 0.507925f, 0.508646f, 0.509366f,
1545       0.510086f, 0.510807f, 0.511527f, 0.512248f, 0.512968f, 0.513689f,
1546       0.514409f, 0.515130f, 0.515850f, 0.516571f, 0.517291f, 0.518012f,
1547       0.518732f, 0.519452f, 0.520173f, 0.520893f, 0.521614f, 0.522334f,
1548       0.523055f, 0.523775f, 0.524496f, 0.525216f, 0.525937f, 0.526657f,
1549       0.527378f, 0.528098f, 0.528818f, 0.529539f, 0.530259f, 0.530980f,
1550       0.531700f, 0.532421f, 0.533141f, 0.533862f, 0.534582f, 0.535303f,
1551       0.536023f, 0.536744f, 0.537464f, 0.538184f, 0.538905f, 0.539625f,
1552       0.540346f, 0.541066f, 0.541787f, 0.542507f, 0.543228f, 0.543948f,
1553       0.544669f, 0.545389f, 0.546109f, 0.546830f, 0.547550f, 0.548271f,
1554       0.548991f, 0.549712f, 0.550432f, 0.551153f, 0.551873f, 0.552594f,
1555       0.553314f, 0.554035f, 0.554755f, 0.555476f, 0.556196f, 0.556916f,
1556       0.557637f, 0.558357f, 0.559078f, 0.559798f, 0.560519f, 0.561239f,
1557       0.561960f, 0.562680f, 0.563401f, 0.564121f, 0.564842f, 0.565562f,
1558       0.566282f, 0.567003f, 0.567723f, 0.568444f, 0.569164f, 0.569885f,
1559       0.570605f, 0.571326f, 0.572046f, 0.572767f, 0.573487f, 0.574207f,
1560       0.574928f, 0.575648f, 0.576369f, 0.577089f, 0.577810f, 0.578530f,
1561       0.579251f, 0.579971f, 0.580692f, 0.581412f, 0.582133f, 0.582853f,
1562       0.583573f, 0.584294f, 0.585014f, 0.585735f, 0.586455f, 0.587176f,
1563       0.587896f, 0.588617f, 0.589337f, 0.590058f, 0.590778f, 0.591499f,
1564       0.592219f, 0.592939f, 0.593660f, 0.594380f, 0.595101f, 0.595821f,
1565       0.596542f, 0.597262f, 0.597983f, 0.598703f, 0.599424f, 0.600144f,
1566       0.600865f, 0.601585f, 0.602305f, 0.603026f, 0.603746f, 0.604467f,
1567       0.605187f, 0.605908f, 0.606628f, 0.607349f, 0.608069f, 0.608790f,
1568       0.609510f, 0.610231f, 0.610951f, 0.611671f, 0.612392f, 0.613112f,
1569       0.613833f, 0.614553f, 0.615274f, 0.615994f, 0.616715f, 0.617435f,
1570       0.618156f, 0.618876f, 0.619597f, 0.620317f, 0.621037f, 0.621758f,
1571       0.622478f, 0.623199f, 0.623919f, 0.624640f, 0.625360f, 0.626081f,
1572       0.626801f, 0.627522f, 0.628242f, 0.628963f, 0.629683f, 0.630403f,
1573       0.631124f, 0.631844f, 0.632565f, 0.633285f, 0.634006f, 0.634726f,
1574       0.635447f, 0.636167f, 0.636888f, 0.637608f, 0.638329f, 0.639049f,
1575       0.639769f, 0.640490f, 0.641210f, 0.641931f, 0.642651f, 0.643372f,
1576       0.644092f, 0.644813f, 0.645533f, 0.646254f, 0.646974f, 0.647695f,
1577       0.648415f, 0.649135f, 0.649856f, 0.650576f, 0.651297f, 0.652017f,
1578       0.652738f, 0.653458f, 0.654179f, 0.654899f, 0.655620f, 0.656340f,
1579       0.657061f, 0.657781f, 0.658501f, 0.659222f, 0.659942f, 0.660663f,
1580       0.661383f, 0.662104f, 0.662824f, 0.663545f, 0.664265f, 0.664986f,
1581       0.665706f, 0.666427f, 0.667147f, 0.667867f, 0.668588f, 0.669308f,
1582       0.670029f, 0.670749f, 0.671470f, 0.672190f, 0.672911f, 0.673631f,
1583       0.674352f, 0.675072f, 0.675793f, 0.676513f, 0.677233f, 0.677954f,
1584       0.678674f, 0.679395f, 0.680115f, 0.680836f, 0.681556f, 0.682277f,
1585       0.682997f, 0.683718f, 0.684438f, 0.685158f, 0.685879f, 0.686599f,
1586       0.687320f, 0.688040f, 0.688761f, 0.689481f, 0.690202f, 0.690922f,
1587       0.691643f, 0.692363f, 0.693084f, 0.693804f, 0.694524f, 0.695245f,
1588       0.695965f, 0.696686f, 0.697406f, 0.698127f, 0.698847f, 0.699568f,
1589       0.700288f, 0.701009f, 0.701729f, 0.702450f, 0.703170f, 0.703891f,
1590       0.704611f, 0.705331f, 0.706052f, 0.706772f, 0.707493f, 0.708213f,
1591       0.708934f, 0.709654f, 0.710375f, 0.711095f, 0.711816f, 0.712536f,
1592       0.713256f, 0.713977f, 0.714697f, 0.715418f, 0.716138f, 0.716859f,
1593       0.717579f, 0.718300f, 0.719020f, 0.719741f, 0.720461f, 0.721182f,
1594       0.721902f, 0.722622f, 0.723343f, 0.724063f, 0.724784f, 0.725504f,
1595       0.726225f, 0.726945f, 0.727666f, 0.728386f, 0.729107f, 0.729827f,
1596       0.730548f, 0.731268f, 0.731988f, 0.732709f, 0.733429f, 0.734150f,
1597       0.734870f, 0.735591f, 0.736311f, 0.737032f, 0.737752f, 0.738473f,
1598       0.739193f, 0.739914f, 0.740634f, 0.741354f, 0.742075f, 0.742795f,
1599       0.743516f, 0.744236f, 0.744957f, 0.745677f, 0.746398f, 0.747118f,
1600       0.747839f, 0.748559f, 0.749280f, 0.750000f, 0.750720f, 0.751441f,
1601       0.752161f, 0.752882f, 0.753602f, 0.754323f, 0.755043f, 0.755764f,
1602       0.756484f, 0.757205f, 0.757925f, 0.758646f, 0.759366f, 0.760086f,
1603       0.760807f, 0.761527f, 0.762248f, 0.762968f, 0.763689f, 0.764409f,
1604       0.765130f, 0.765850f, 0.766571f, 0.767291f, 0.768012f, 0.768732f,
1605       0.769452f, 0.770173f, 0.770893f, 0.771614f, 0.772334f, 0.773055f,
1606       0.773775f, 0.774496f, 0.775216f, 0.775937f, 0.776657f, 0.777378f,
1607       0.778098f, 0.778818f, 0.779539f, 0.780259f, 0.780980f, 0.781700f,
1608       0.782421f, 0.783141f, 0.783862f, 0.784582f, 0.785303f, 0.786023f,
1609       0.786744f, 0.787464f, 0.788184f, 0.788905f, 0.789625f, 0.790346f,
1610       0.791066f, 0.791787f, 0.792507f, 0.793228f, 0.793948f, 0.794669f,
1611       0.795389f, 0.796109f, 0.796830f, 0.797550f, 0.798271f, 0.798991f,
1612       0.799712f, 0.800432f, 0.801153f, 0.801873f, 0.802594f, 0.803314f,
1613       0.804035f, 0.804755f, 0.805476f, 0.806196f, 0.806916f, 0.807637f,
1614       0.808357f, 0.809078f, 0.809798f, 0.810519f, 0.811239f, 0.811960f,
1615       0.812680f, 0.813401f, 0.814121f, 0.814842f, 0.815562f, 0.816282f,
1616       0.817003f, 0.817723f, 0.818444f, 0.819164f, 0.819885f, 0.820605f,
1617       0.821326f, 0.822046f, 0.822767f, 0.823487f, 0.824207f, 0.824928f,
1618       0.825648f, 0.826369f, 0.827089f, 0.827810f, 0.828530f, 0.829251f,
1619       0.829971f, 0.830692f, 0.831412f, 0.832133f, 0.832853f, 0.833573f,
1620       0.834294f, 0.835014f, 0.835735f, 0.836455f, 0.837176f, 0.837896f,
1621       0.838617f, 0.839337f, 0.840058f, 0.840778f, 0.841499f, 0.842219f,
1622       0.842939f, 0.843660f, 0.844380f, 0.845101f, 0.845821f, 0.846542f,
1623       0.847262f, 0.847983f, 0.848703f, 0.849424f, 0.850144f, 0.850865f,
1624       0.851585f, 0.852305f, 0.853026f, 0.853746f, 0.854467f, 0.855187f,
1625       0.855908f, 0.856628f, 0.857349f, 0.858069f, 0.858790f, 0.859510f,
1626       0.860231f, 0.860951f, 0.861671f, 0.862392f, 0.863112f, 0.863833f,
1627       0.864553f, 0.865274f, 0.865994f, 0.866715f, 0.867435f, 0.868156f,
1628       0.868876f, 0.869597f, 0.870317f, 0.871037f, 0.871758f, 0.872478f,
1629       0.873199f, 0.873919f, 0.874640f, 0.875360f, 0.876081f, 0.876801f,
1630       0.877522f, 0.878242f, 0.878963f, 0.879683f, 0.880403f, 0.881124f,
1631       0.881844f, 0.882565f, 0.883285f, 0.884006f, 0.884726f, 0.885447f,
1632       0.886167f, 0.886888f, 0.887608f, 0.888329f, 0.889049f, 0.889769f,
1633       0.890490f, 0.891210f, 0.891931f, 0.892651f, 0.893372f, 0.894092f,
1634       0.894813f, 0.895533f, 0.896254f, 0.896974f, 0.897695f, 0.898415f,
1635       0.899135f, 0.899856f, 0.900576f, 0.901297f, 0.902017f, 0.902738f,
1636       0.903458f, 0.904179f, 0.904899f, 0.905620f, 0.906340f, 0.907061f,
1637       0.907781f, 0.908501f, 0.909222f, 0.909942f, 0.910663f, 0.911383f,
1638       0.912104f, 0.912824f, 0.913545f, 0.914265f, 0.914986f, 0.915706f,
1639       0.916427f, 0.917147f, 0.917867f, 0.918588f, 0.919308f, 0.920029f,
1640       0.920749f, 0.921470f, 0.922190f, 0.922911f, 0.923631f, 0.924352f,
1641       0.925072f, 0.925793f, 0.926513f, 0.927233f, 0.927954f, 0.928674f,
1642       0.929395f, 0.930115f, 0.930836f, 0.931556f, 0.932277f, 0.932997f,
1643       0.933718f, 0.934438f, 0.935158f, 0.935879f, 0.936599f, 0.937320f,
1644       0.938040f, 0.938761f, 0.939481f, 0.940202f, 0.940922f, 0.941643f,
1645       0.942363f, 0.943084f, 0.943804f, 0.944524f, 0.945245f, 0.945965f,
1646       0.946686f, 0.947406f, 0.948127f, 0.948847f, 0.949568f, 0.950288f,
1647       0.951009f, 0.951729f, 0.952450f, 0.953170f, 0.953891f, 0.954611f,
1648       0.955331f, 0.956052f, 0.956772f, 0.957493f, 0.958213f, 0.958934f,
1649       0.959654f, 0.960375f, 0.961095f, 0.961816f, 0.962536f, 0.963256f,
1650       0.963977f, 0.964697f, 0.965418f, 0.966138f, 0.966859f, 0.967579f,
1651       0.968300f, 0.969020f, 0.969741f, 0.970461f, 0.971182f, 0.971902f,
1652       0.972622f, 0.973343f, 0.974063f, 0.974784f, 0.975504f, 0.976225f,
1653       0.976945f, 0.977666f, 0.978386f, 0.979107f, 0.979827f, 0.980548f,
1654       0.981268f, 0.981988f, 0.982709f, 0.983429f, 0.984150f, 0.984870f,
1655       0.985591f, 0.986311f, 0.987032f, 0.987752f, 0.988473f, 0.989193f,
1656       0.989914f, 0.990634f, 0.991354f, 0.992075f, 0.992795f, 0.993516f,
1657       0.994236f, 0.994957f, 0.995677f, 0.996398f, 0.997118f, 0.997839f,
1658       0.998559f, 0.999280f, 1.000000f
1659     };
1660 #endif
1661
1662   CacheView
1663     *image_view;
1664
1665   MagickBooleanType
1666     status;
1667
1668   MagickOffsetType
1669     progress;
1670
1671   register ssize_t
1672     i;
1673
1674   ssize_t
1675     y;
1676
1677   TransformPacket
1678     *y_map,
1679     *x_map,
1680     *z_map;
1681
1682   assert(image != (Image *) NULL);
1683   assert(image->signature == MagickSignature);
1684   if (image->debug != MagickFalse)
1685     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1686   status=MagickTrue;
1687   progress=0;
1688   switch (image->colorspace)
1689   {
1690     case CMYColorspace:
1691     {
1692       /*
1693         Transform image from CMY to RGB.
1694       */
1695       if (image->storage_class == PseudoClass)
1696         {
1697           if (SyncImage(image,exception) == MagickFalse)
1698             return(MagickFalse);
1699           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1700             return(MagickFalse);
1701         }
1702       image_view=AcquireCacheView(image);
1703 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1704       #pragma omp parallel for schedule(static,4) shared(status)
1705 #endif
1706       for (y=0; y < (ssize_t) image->rows; y++)
1707       {
1708         MagickBooleanType
1709           sync;
1710
1711         register ssize_t
1712           x;
1713
1714         register Quantum
1715           *restrict q;
1716
1717         if (status == MagickFalse)
1718           continue;
1719         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1720           exception);
1721         if (q == (Quantum *) NULL)
1722           {
1723             status=MagickFalse;
1724             continue;
1725           }
1726         for (x=0; x < (ssize_t) image->columns; x++)
1727         {
1728           SetPixelRed(image,ClampToQuantum((MagickRealType) (QuantumRange-
1729             GetPixelRed(image,q))),q);
1730           SetPixelGreen(image,ClampToQuantum((MagickRealType) (QuantumRange-
1731             GetPixelGreen(image,q))),q);
1732           SetPixelBlue(image,ClampToQuantum((MagickRealType) (QuantumRange-
1733             GetPixelBlue(image,q))),q);
1734           q+=GetPixelChannels(image);
1735         }
1736         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1737         if (sync == MagickFalse)
1738           status=MagickFalse;
1739       }
1740       image_view=DestroyCacheView(image_view);
1741       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
1742         return(MagickFalse);
1743       return(status);
1744     }
1745     case CMYKColorspace:
1746     {
1747       PixelInfo
1748         zero;
1749
1750       /*
1751         Transform image from CMYK to RGB.
1752       */
1753       if (image->storage_class == PseudoClass)
1754         {
1755           if (SyncImage(image,exception) == MagickFalse)
1756             return(MagickFalse);
1757           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1758             return(MagickFalse);
1759         }
1760       GetPixelInfo(image,&zero);
1761       image_view=AcquireCacheView(image);
1762 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1763       #pragma omp parallel for schedule(static,4) shared(status)
1764 #endif
1765       for (y=0; y < (ssize_t) image->rows; y++)
1766       {
1767         MagickBooleanType
1768           sync;
1769
1770         PixelInfo
1771           pixel;
1772
1773         register ssize_t
1774           x;
1775
1776         register Quantum
1777           *restrict q;
1778
1779         if (status == MagickFalse)
1780           continue;
1781         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1782           exception);
1783         if (q == (Quantum *) NULL)
1784           {
1785             status=MagickFalse;
1786             continue;
1787           }
1788         pixel=zero;
1789         for (x=0; x < (ssize_t) image->columns; x++)
1790         {
1791           GetPixelInfoPixel(image,q,&pixel);
1792           ConvertCMYKToRGB(&pixel);
1793           SetPixelInfoPixel(image,&pixel,q);
1794           q+=GetPixelChannels(image);
1795         }
1796         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1797         if (sync == MagickFalse)
1798           status=MagickFalse;
1799       }
1800       image_view=DestroyCacheView(image_view);
1801       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
1802         return(MagickFalse);
1803       return(status);
1804     }
1805     case HSBColorspace:
1806     {
1807       /*
1808         Transform image from HSB to RGB.
1809       */
1810       if (image->storage_class == PseudoClass)
1811         {
1812           if (SyncImage(image,exception) == MagickFalse)
1813             return(MagickFalse);
1814           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1815             return(MagickFalse);
1816         }
1817       image_view=AcquireCacheView(image);
1818 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1819       #pragma omp parallel for schedule(static,4) shared(status)
1820 #endif
1821       for (y=0; y < (ssize_t) image->rows; y++)
1822       {
1823         double
1824           brightness,
1825           hue,
1826           saturation;
1827
1828         MagickBooleanType
1829           sync;
1830
1831         register ssize_t
1832           x;
1833
1834         register Quantum
1835           *restrict q;
1836
1837         if (status == MagickFalse)
1838           continue;
1839         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1840           exception);
1841         if (q == (Quantum *) NULL)
1842           {
1843             status=MagickFalse;
1844             continue;
1845           }
1846         for (x=0; x < (ssize_t) image->columns; x++)
1847         {
1848           double
1849             blue,
1850             green,
1851             red;
1852
1853           hue=(double) (QuantumScale*GetPixelRed(image,q));
1854           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
1855           brightness=(double) (QuantumScale*GetPixelBlue(image,q));
1856           ConvertHSBToRGB(hue,saturation,brightness,&red,&green,&blue);
1857           SetPixelRed(image,ClampToQuantum(red),q);
1858           SetPixelGreen(image,ClampToQuantum(green),q);
1859           SetPixelBlue(image,ClampToQuantum(blue),q);
1860           q+=GetPixelChannels(image);
1861         }
1862         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1863         if (sync == MagickFalse)
1864           status=MagickFalse;
1865       }
1866       image_view=DestroyCacheView(image_view);
1867       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
1868         return(MagickFalse);
1869       return(status);
1870     }
1871     case HSLColorspace:
1872     {
1873       /*
1874         Transform image from HSL to RGB.
1875       */
1876       if (image->storage_class == PseudoClass)
1877         {
1878           if (SyncImage(image,exception) == MagickFalse)
1879             return(MagickFalse);
1880           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1881             return(MagickFalse);
1882         }
1883       image_view=AcquireCacheView(image);
1884 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1885       #pragma omp parallel for schedule(static,4) shared(status)
1886 #endif
1887       for (y=0; y < (ssize_t) image->rows; y++)
1888       {
1889         double
1890           hue,
1891           lightness,
1892           saturation;
1893
1894         MagickBooleanType
1895           sync;
1896
1897         register ssize_t
1898           x;
1899
1900         register Quantum
1901           *restrict q;
1902
1903         if (status == MagickFalse)
1904           continue;
1905         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1906           exception);
1907         if (q == (Quantum *) NULL)
1908           {
1909             status=MagickFalse;
1910             continue;
1911           }
1912         for (x=0; x < (ssize_t) image->columns; x++)
1913         {
1914           double
1915             blue,
1916             green,
1917             red;
1918
1919           hue=(double) (QuantumScale*GetPixelRed(image,q));
1920           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
1921           lightness=(double) (QuantumScale*GetPixelBlue(image,q));
1922           ConvertHSLToRGB(hue,saturation,lightness,&red,&green,&blue);
1923           SetPixelRed(image,ClampToQuantum(red),q);
1924           SetPixelGreen(image,ClampToQuantum(green),q);
1925           SetPixelBlue(image,ClampToQuantum(blue),q);
1926           q+=GetPixelChannels(image);
1927         }
1928         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1929         if (sync == MagickFalse)
1930           status=MagickFalse;
1931       }
1932       image_view=DestroyCacheView(image_view);
1933       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
1934         return(MagickFalse);
1935       return(status);
1936     }
1937     case HWBColorspace:
1938     {
1939       /*
1940         Transform image from HWB to RGB.
1941       */
1942       if (image->storage_class == PseudoClass)
1943         {
1944           if (SyncImage(image,exception) == MagickFalse)
1945             return(MagickFalse);
1946           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1947             return(MagickFalse);
1948         }
1949       image_view=AcquireCacheView(image);
1950 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1951       #pragma omp parallel for schedule(static,4) shared(status)
1952 #endif
1953       for (y=0; y < (ssize_t) image->rows; y++)
1954       {
1955         double
1956           blackness,
1957           hue,
1958           whiteness;
1959
1960         MagickBooleanType
1961           sync;
1962
1963         register ssize_t
1964           x;
1965
1966         register Quantum
1967           *restrict q;
1968
1969         if (status == MagickFalse)
1970           continue;
1971         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1972           exception);
1973         if (q == (Quantum *) NULL)
1974           {
1975             status=MagickFalse;
1976             continue;
1977           }
1978         for (x=0; x < (ssize_t) image->columns; x++)
1979         {
1980           double
1981             blue,
1982             green,
1983             red;
1984
1985           hue=(double) (QuantumScale*GetPixelRed(image,q));
1986           whiteness=(double) (QuantumScale*GetPixelGreen(image,q));
1987           blackness=(double) (QuantumScale*GetPixelBlue(image,q));
1988           ConvertHWBToRGB(hue,whiteness,blackness,&red,&green,&blue);
1989           SetPixelRed(image,ClampToQuantum(red),q);
1990           SetPixelGreen(image,ClampToQuantum(green),q);
1991           SetPixelBlue(image,ClampToQuantum(blue),q);
1992           q+=GetPixelChannels(image);
1993         }
1994         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1995         if (sync == MagickFalse)
1996           status=MagickFalse;
1997       }
1998       image_view=DestroyCacheView(image_view);
1999       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2000         return(MagickFalse);
2001       return(status);
2002     }
2003     case LabColorspace:
2004     {
2005       /*
2006         Transform image from Lab to RGB.
2007       */
2008       if (image->storage_class == PseudoClass)
2009         {
2010           if (SyncImage(image,exception) == MagickFalse)
2011             return(MagickFalse);
2012           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2013             return(MagickFalse);
2014         }
2015       image_view=AcquireCacheView(image);
2016 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2017       #pragma omp parallel for schedule(static,4) shared(status)
2018 #endif
2019       for (y=0; y < (ssize_t) image->rows; y++)
2020       {
2021         double
2022           a,
2023           b,
2024           L,
2025           X,
2026           Y,
2027           Z;
2028
2029         MagickBooleanType
2030           sync;
2031
2032         register ssize_t
2033           x;
2034
2035         register Quantum
2036           *restrict q;
2037
2038         if (status == MagickFalse)
2039           continue;
2040         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2041           exception);
2042         if (q == (Quantum *) NULL)
2043           {
2044             status=MagickFalse;
2045             continue;
2046           }
2047         X=0.0;
2048         Y=0.0;
2049         Z=0.0;
2050         for (x=0; x < (ssize_t) image->columns; x++)
2051         {
2052           Quantum
2053             blue,
2054             green,
2055             red;
2056
2057           L=QuantumScale*GetPixelRed(image,q);
2058           a=QuantumScale*GetPixelGreen(image,q);
2059           b=QuantumScale*GetPixelBlue(image,q);
2060           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
2061           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2062           SetPixelRed(image,red,q);
2063           SetPixelGreen(image,green,q);
2064           SetPixelBlue(image,blue,q);
2065           q+=GetPixelChannels(image);
2066         }
2067         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2068         if (sync == MagickFalse)
2069           status=MagickFalse;
2070       }
2071       image_view=DestroyCacheView(image_view);
2072       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2073         return(MagickFalse);
2074       return(status);
2075     }
2076     case LogColorspace:
2077     {
2078       const char
2079         *value;
2080
2081       double
2082         black,
2083         density,
2084         film_gamma,
2085         gamma,
2086         reference_black,
2087         reference_white;
2088
2089       Quantum
2090         *logmap;
2091
2092       /*
2093         Transform Log to RGB colorspace.
2094       */
2095       density=DisplayGamma;
2096       gamma=DisplayGamma;
2097       value=GetImageProperty(image,"gamma",exception);
2098       if (value != (const char *) NULL)
2099         gamma=1.0/fabs(StringToDouble(value,(char **) NULL)) >=
2100           MagickEpsilon ? StringToDouble(value,(char **) NULL) : 1.0;
2101       film_gamma=FilmGamma;
2102       value=GetImageProperty(image,"film-gamma",exception);
2103       if (value != (const char *) NULL)
2104         film_gamma=StringToDouble(value,(char **) NULL);
2105       reference_black=ReferenceBlack;
2106       value=GetImageProperty(image,"reference-black",exception);
2107       if (value != (const char *) NULL)
2108         reference_black=StringToDouble(value,(char **) NULL);
2109       reference_white=ReferenceWhite;
2110       value=GetImageProperty(image,"reference-white",exception);
2111       if (value != (const char *) NULL)
2112         reference_white=StringToDouble(value,(char **) NULL);
2113       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2114         sizeof(*logmap));
2115       if (logmap == (Quantum *) NULL)
2116         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2117           image->filename);
2118       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
2119         0.002/film_gamma);
2120       for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
2121         logmap[i]=(Quantum) 0;
2122       for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0); i++)
2123         logmap[i]=ClampToQuantum((MagickRealType) QuantumRange/(1.0-black)*
2124           (pow(10.0,(1024.0*i/MaxMap-reference_white)*
2125           (gamma/density)*0.002/film_gamma)-black));
2126       for ( ; i <= (ssize_t) MaxMap; i++)
2127         logmap[i]=(Quantum) QuantumRange;
2128       if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2129         return(MagickFalse);
2130       image_view=AcquireCacheView(image);
2131 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2132       #pragma omp parallel for schedule(static,4) shared(status)
2133 #endif
2134       for (y=0; y < (ssize_t) image->rows; y++)
2135       {
2136         MagickBooleanType
2137           sync;
2138
2139         register ssize_t
2140           x;
2141
2142         register Quantum
2143           *restrict q;
2144
2145         if (status == MagickFalse)
2146           continue;
2147         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2148           exception);
2149         if (q == (Quantum *) NULL)
2150           {
2151             status=MagickFalse;
2152             continue;
2153           }
2154         for (x=(ssize_t) image->columns; x != 0; x--)
2155         {
2156           SetPixelRed(image,logmap[ScaleQuantumToMap(
2157             GetPixelRed(image,q))],q);
2158           SetPixelGreen(image,logmap[ScaleQuantumToMap(
2159             GetPixelGreen(image,q))],q);
2160           SetPixelBlue(image,logmap[ScaleQuantumToMap(
2161             GetPixelBlue(image,q))],q);
2162           q+=GetPixelChannels(image);
2163         }
2164         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2165         if (sync == MagickFalse)
2166           status=MagickFalse;
2167       }
2168       image_view=DestroyCacheView(image_view);
2169       logmap=(Quantum *) RelinquishMagickMemory(logmap);
2170       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2171         return(MagickFalse);
2172       return(status);
2173     }
2174     default:
2175       break;
2176   }
2177   /*
2178     Allocate the tables.
2179   */
2180   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2181     sizeof(*x_map));
2182   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2183     sizeof(*y_map));
2184   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2185     sizeof(*z_map));
2186   if ((x_map == (TransformPacket *) NULL) ||
2187       (y_map == (TransformPacket *) NULL) ||
2188       (z_map == (TransformPacket *) NULL))
2189     {
2190       if (z_map != (TransformPacket *) NULL)
2191         z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2192       if (y_map != (TransformPacket *) NULL)
2193         y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2194       if (x_map != (TransformPacket *) NULL)
2195         x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2196       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2197         image->filename);
2198     }
2199   switch (image->colorspace)
2200   {
2201     case OHTAColorspace:
2202     {
2203       /*
2204         Initialize OHTA tables:
2205
2206           R = I1+1.00000*I2-0.66668*I3
2207           G = I1+0.00000*I2+1.33333*I3
2208           B = I1-1.00000*I2-0.66668*I3
2209
2210         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2211         through QuantumRange.
2212       */
2213 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2214       #pragma omp parallel for schedule(static)
2215 #endif
2216       for (i=0; i <= (ssize_t) MaxMap; i++)
2217       {
2218         x_map[i].x=(MagickRealType) i;
2219         y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType)
2220           MaxMap);
2221         z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
2222           MaxMap);
2223         x_map[i].y=(MagickRealType) i;
2224         y_map[i].y=0.000000f;
2225         z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType)
2226           MaxMap);
2227         x_map[i].z=(MagickRealType) i;
2228         y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType)
2229           MaxMap);
2230         z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
2231           MaxMap);
2232       }
2233       break;
2234     }
2235     case Rec601YCbCrColorspace:
2236     case YCbCrColorspace:
2237     {
2238       /*
2239         Initialize YCbCr tables:
2240
2241           R = Y            +1.402000*Cr
2242           G = Y-0.344136*Cb-0.714136*Cr
2243           B = Y+1.772000*Cb
2244
2245         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
2246         through QuantumRange.
2247       */
2248 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2249       #pragma omp parallel for schedule(static)
2250 #endif
2251       for (i=0; i <= (ssize_t) MaxMap; i++)
2252       {
2253         x_map[i].x=(MagickRealType) i;
2254         y_map[i].x=0.000000f;
2255         z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i-
2256           (MagickRealType) MaxMap);
2257         x_map[i].y=(MagickRealType) i;
2258         y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i-
2259           (MagickRealType) MaxMap);
2260         z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i-
2261           (MagickRealType) MaxMap);
2262         x_map[i].z=(MagickRealType) i;
2263         y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i-
2264           (MagickRealType) MaxMap);
2265         z_map[i].z=0.000000f;
2266       }
2267       break;
2268     }
2269     case Rec709YCbCrColorspace:
2270     {
2271       /*
2272         Initialize YCbCr tables:
2273
2274           R = Y            +1.574800*Cr
2275           G = Y-0.187324*Cb-0.468124*Cr
2276           B = Y+1.855600*Cb
2277
2278         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
2279         through QuantumRange.
2280       */
2281 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2282       #pragma omp parallel for schedule(static)
2283 #endif
2284       for (i=0; i <= (ssize_t) MaxMap; i++)
2285       {
2286         x_map[i].x=(MagickRealType) i;
2287         y_map[i].x=0.000000f;
2288         z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i-
2289           (MagickRealType) MaxMap);
2290         x_map[i].y=(MagickRealType) i;
2291         y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i-
2292           (MagickRealType) MaxMap);
2293         z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i-
2294           (MagickRealType) MaxMap);
2295         x_map[i].z=(MagickRealType) i;
2296         y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i-
2297           (MagickRealType) MaxMap);
2298         z_map[i].z=0.00000f;
2299       }
2300       break;
2301     }
2302     case RGBColorspace:
2303     {
2304       /*
2305         Nonlinear sRGB to linear RGB (http://www.w3.org/Graphics/Color/sRGB):
2306
2307           R = 1.0*R+0.0*G+0.0*B
2308           G = 0.0*R+1.0*G+0.0*B
2309           B = 0.0*R+0.0*G+1.0*B
2310       */
2311 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2312       #pragma omp parallel for schedule(static)
2313 #endif
2314       for (i=0; i <= (ssize_t) MaxMap; i++)
2315       {
2316         MagickRealType
2317           v;
2318
2319         v=(MagickRealType) i/(MagickRealType) MaxMap;
2320         if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.0031308)
2321           v*=12.92f;
2322         else
2323           v=(MagickRealType) (1.055*pow((double) i/MaxMap,1.0/2.4)-0.055);
2324         x_map[i].x=1.0f*MaxMap*v;
2325         y_map[i].x=0.0f*MaxMap*v;
2326         z_map[i].x=0.0f*MaxMap*v;
2327         x_map[i].y=0.0f*MaxMap*v;
2328         y_map[i].y=1.0f*MaxMap*v;
2329         z_map[i].y=0.0f*MaxMap*v;
2330         x_map[i].z=0.0f*MaxMap*v;
2331         y_map[i].z=0.0f*MaxMap*v;
2332         z_map[i].z=1.0f*MaxMap*v;
2333       }
2334       break;
2335     }
2336     case XYZColorspace:
2337     {
2338       /*
2339         Initialize CIE XYZ tables (ITU R-709 RGB):
2340
2341           R =  3.2404542*X-1.5371385*Y-0.4985314*Z
2342           G = -0.9692660*X+1.8760108*Y+0.0415560*Z
2343           B =  0.0556434*X-0.2040259*Y+1.057225*Z
2344       */
2345 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2346       #pragma omp parallel for schedule(static)
2347 #endif
2348       for (i=0; i <= (ssize_t) MaxMap; i++)
2349       {
2350         x_map[i].x=3.2404542f*(MagickRealType) i;
2351         x_map[i].y=(-0.9692660f)*(MagickRealType) i;
2352         x_map[i].z=0.0556434f*(MagickRealType) i;
2353         y_map[i].x=(-1.5371385f)*(MagickRealType) i;
2354         y_map[i].y=1.8760108f*(MagickRealType) i;
2355         y_map[i].z=(-0.2040259f)*(MagickRealType) i;
2356         z_map[i].x=(-0.4985314f)*(MagickRealType) i;
2357         z_map[i].y=0.0415560f*(MagickRealType) i;
2358         z_map[i].z=1.0572252f*(MagickRealType) i;
2359       }
2360       break;
2361     }
2362     case YCCColorspace:
2363     {
2364       /*
2365         Initialize YCC tables:
2366
2367           R = Y            +1.340762*C2
2368           G = Y-0.317038*C1-0.682243*C2
2369           B = Y+1.632639*C1
2370
2371         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
2372       */
2373 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2374       #pragma omp parallel for schedule(static)
2375 #endif
2376       for (i=0; i <= (ssize_t) MaxMap; i++)
2377       {
2378         x_map[i].x=1.3584000f*(MagickRealType) i;
2379         y_map[i].x=0.0000000f;
2380         z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType)
2381           ScaleQuantumToMap(ScaleCharToQuantum(137)));
2382         x_map[i].y=1.3584000f*(MagickRealType) i;
2383         y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType)
2384           ScaleQuantumToMap(ScaleCharToQuantum(156)));
2385         z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType)
2386           ScaleQuantumToMap(ScaleCharToQuantum(137)));
2387         x_map[i].z=1.3584000f*(MagickRealType) i;
2388         y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType)
2389           ScaleQuantumToMap(ScaleCharToQuantum(156)));
2390         z_map[i].z=0.0000000f;
2391       }
2392       break;
2393     }
2394     case YIQColorspace:
2395     {
2396       /*
2397         Initialize YIQ tables:
2398
2399           R = Y+0.95620*I+0.62140*Q
2400           G = Y-0.27270*I-0.64680*Q
2401           B = Y-1.10370*I+1.70060*Q
2402
2403         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2404         through QuantumRange.
2405       */
2406 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2407       #pragma omp parallel for schedule(static)
2408 #endif
2409       for (i=0; i <= (ssize_t) MaxMap; i++)
2410       {
2411         x_map[i].x=(MagickRealType) i;
2412         y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType)
2413           MaxMap);
2414         z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType)
2415           MaxMap);
2416         x_map[i].y=(MagickRealType) i;
2417         y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2418           MaxMap);
2419         z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2420           MaxMap);
2421         x_map[i].z=(MagickRealType) i;
2422         y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2423           MaxMap);
2424         z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType)
2425           MaxMap);
2426       }
2427       break;
2428     }
2429     case YPbPrColorspace:
2430     {
2431       /*
2432         Initialize YPbPr tables:
2433
2434           R = Y            +1.402000*C2
2435           G = Y-0.344136*C1+0.714136*C2
2436           B = Y+1.772000*C1
2437
2438         Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
2439         through QuantumRange.
2440       */
2441 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2442       #pragma omp parallel for schedule(static)
2443 #endif
2444       for (i=0; i <= (ssize_t) MaxMap; i++)
2445       {
2446         x_map[i].x=(MagickRealType) i;
2447         y_map[i].x=0.000000f;
2448         z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType)
2449           MaxMap);
2450         x_map[i].y=(MagickRealType) i;
2451         y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2452           MaxMap);
2453         z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType)
2454           MaxMap);
2455         x_map[i].z=(MagickRealType) i;
2456         y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType)
2457           MaxMap);
2458         z_map[i].z=0.00000f;
2459       }
2460       break;
2461     }
2462     case YUVColorspace:
2463     {
2464       /*
2465         Initialize YUV tables:
2466
2467           R = Y          +1.13980*V
2468           G = Y-0.39380*U-0.58050*V
2469           B = Y+2.02790*U
2470
2471         U and V, normally -0.5 through 0.5, must be normalized to the range 0
2472         through QuantumRange.
2473       */
2474 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2475       #pragma omp parallel for schedule(static)
2476 #endif
2477       for (i=0; i <= (ssize_t) MaxMap; i++)
2478       {
2479         x_map[i].x=(MagickRealType) i;
2480         y_map[i].x=0.00000f;
2481         z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType)
2482           MaxMap);
2483         x_map[i].y=(MagickRealType) i;
2484         y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2485           MaxMap);
2486         z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2487           MaxMap);
2488         x_map[i].z=(MagickRealType) i;
2489         y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType)
2490           MaxMap);
2491         z_map[i].z=0.00000f;
2492       }
2493       break;
2494     }
2495     default:
2496     {
2497       /*
2498         Linear conversion tables.
2499       */
2500 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2501       #pragma omp parallel for schedule(static)
2502 #endif
2503       for (i=0; i <= (ssize_t) MaxMap; i++)
2504       {
2505         x_map[i].x=(MagickRealType) i;
2506         y_map[i].x=0.0f;
2507         z_map[i].x=0.0f;
2508         x_map[i].y=0.0f;
2509         y_map[i].y=(MagickRealType) i;
2510         z_map[i].y=0.0f;
2511         x_map[i].z=0.0f;
2512         y_map[i].z=0.0f;
2513         z_map[i].z=(MagickRealType) i;
2514       }
2515       break;
2516     }
2517   }
2518   /*
2519     Convert to RGB.
2520   */
2521   switch (image->storage_class)
2522   {
2523     case DirectClass:
2524     default:
2525     {
2526       /*
2527         Convert DirectClass image.
2528       */
2529       image_view=AcquireCacheView(image);
2530 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2531       #pragma omp parallel for schedule(static,4) shared(status)
2532 #endif
2533       for (y=0; y < (ssize_t) image->rows; y++)
2534       {
2535         MagickBooleanType
2536           sync;
2537
2538         PixelInfo
2539           pixel;
2540
2541         register ssize_t
2542           x;
2543
2544         register Quantum
2545           *restrict q;
2546
2547         if (status == MagickFalse)
2548           continue;
2549         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2550           exception);
2551         if (q == (Quantum *) NULL)
2552           {
2553             status=MagickFalse;
2554             continue;
2555           }
2556         for (x=0; x < (ssize_t) image->columns; x++)
2557         {
2558           register size_t
2559             blue,
2560             green,
2561             red;
2562
2563           red=ScaleQuantumToMap(GetPixelRed(image,q));
2564           green=ScaleQuantumToMap(GetPixelGreen(image,q));
2565           blue=ScaleQuantumToMap(GetPixelBlue(image,q));
2566           pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2567           pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2568           pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2569           switch (colorspace)
2570           {
2571             case YCCColorspace:
2572             {
2573 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2574               pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
2575                 pixel.red)];
2576               pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
2577                 pixel.green)];
2578               pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
2579                 pixel.blue)];
2580 #endif
2581               break;
2582             }
2583             case RGBColorspace:
2584             {
2585               if ((QuantumScale*pixel.red) <= 0.0031308)
2586                 pixel.red*=12.92f;
2587               else
2588                 pixel.red=(MagickRealType) QuantumRange*(1.055*pow(
2589                   QuantumScale*pixel.red,(1.0/2.4))-0.055);
2590               if ((QuantumScale*pixel.green) <= 0.0031308)
2591                 pixel.green*=12.92f;
2592               else
2593                 pixel.green=(MagickRealType) QuantumRange*(1.055*pow(
2594                   QuantumScale*pixel.green,(1.0/2.4))-0.055);
2595               if ((QuantumScale*pixel.blue) <= 0.0031308)
2596                 pixel.blue*=12.92f;
2597               else
2598                 pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(
2599                   QuantumScale*pixel.blue,(1.0/2.4))-0.055);
2600             }
2601             default:
2602               break;
2603           }
2604           SetPixelRed(image,ScaleMapToQuantum((MagickRealType) MaxMap*
2605             QuantumScale*pixel.red),q);
2606           SetPixelGreen(image,ScaleMapToQuantum((MagickRealType) MaxMap*
2607             QuantumScale*pixel.green),q);
2608           SetPixelBlue(image,ScaleMapToQuantum((MagickRealType) MaxMap*
2609             QuantumScale*pixel.blue),q);
2610           q+=GetPixelChannels(image);
2611         }
2612         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2613         if (sync == MagickFalse)
2614           status=MagickFalse;
2615         if (image->progress_monitor != (MagickProgressMonitor) NULL)
2616           {
2617             MagickBooleanType
2618               proceed;
2619
2620 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2621             #pragma omp critical (MagickCore_TransformsRGBImage)
2622 #endif
2623             proceed=SetImageProgress(image,TransformsRGBImageTag,progress++,
2624               image->rows);
2625             if (proceed == MagickFalse)
2626               status=MagickFalse;
2627           }
2628       }
2629       image_view=DestroyCacheView(image_view);
2630       break;
2631     }
2632     case PseudoClass:
2633     {
2634       /*
2635         Convert PseudoClass image.
2636       */
2637       image_view=AcquireCacheView(image);
2638 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2639       #pragma omp parallel for schedule(static,4) shared(status)
2640 #endif
2641       for (i=0; i < (ssize_t) image->colors; i++)
2642       {
2643         PixelInfo
2644           pixel;
2645
2646         register size_t
2647           blue,
2648           green,
2649           red;
2650
2651         red=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red));
2652         green=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green));
2653         blue=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue));
2654         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2655         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2656         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2657         switch (colorspace)
2658         {
2659           case YCCColorspace:
2660           {
2661 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2662             image->colormap[i].red=(double) (QuantumRange*YCCMap[
2663               RoundToYCC(1024.0*QuantumScale*pixel.red)]);
2664             image->colormap[i].green=(double) (QuantumRange*YCCMap[
2665               RoundToYCC(1024.0*QuantumScale*pixel.green)]);
2666             image->colormap[i].blue=(double) (QuantumRange*YCCMap[
2667               RoundToYCC(1024.0*QuantumScale*pixel.blue)]);
2668 #endif
2669             break;
2670           }
2671           case RGBColorspace:
2672           {
2673             if ((QuantumScale*pixel.red) <= 0.0031308)
2674               pixel.red*=12.92f;
2675             else
2676               pixel.red=(MagickRealType) QuantumRange*(1.055*
2677                 pow(QuantumScale*pixel.red,(1.0/2.4))-0.055);
2678             if ((QuantumScale*pixel.green) <= 0.0031308)
2679               pixel.green*=12.92f;
2680             else
2681               pixel.green=(MagickRealType) QuantumRange*(1.055*
2682                 pow(QuantumScale*pixel.green,(1.0/2.4))-0.055);
2683             if ((QuantumScale*pixel.blue) <= 0.0031308)
2684               pixel.blue*=12.92f;
2685             else
2686               pixel.blue=(MagickRealType) QuantumRange*(1.055*
2687                 pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055);
2688             break;
2689           }
2690           default:
2691           {
2692             image->colormap[i].red=(double) ScaleMapToQuantum((MagickRealType)
2693               MaxMap*QuantumScale*pixel.red);
2694             image->colormap[i].green=(double) ScaleMapToQuantum((MagickRealType)
2695               MaxMap*QuantumScale*pixel.green);
2696             image->colormap[i].blue=(double) ScaleMapToQuantum((MagickRealType)
2697               MaxMap*QuantumScale*pixel.blue);
2698             break;
2699           }
2700         }
2701       }
2702       image_view=DestroyCacheView(image_view);
2703       (void) SyncImage(image,exception);
2704       break;
2705     }
2706   }
2707   /*
2708     Relinquish resources.
2709   */
2710   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2711   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2712   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2713   if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2714     return(MagickFalse);
2715   return(MagickTrue);
2716 }