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