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