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