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