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