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