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