]> granicus.if.org Git - imagemagick/blob - MagickCore/colorspace.c
(no commit message)
[imagemagick] / MagickCore / colorspace.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %     CCCC   OOO   L       OOO   RRRR   SSSSS  PPPP    AAA    CCCC  EEEEE     %
7 %    C      O   O  L      O   O  R   R  SS     P   P  A   A  C      E         %
8 %    C      O   O  L      O   O  RRRR    SSS   PPPP   AAAAA  C      EEE       %
9 %    C      O   O  L      O   O  R R       SS  P      A   A  C      E         %
10 %     CCCC   OOO   LLLLL   OOO   R  R   SSSSS  P      A   A   CCCC  EEEEE     %
11 %                                                                             %
12 %                                                                             %
13 %                     MagickCore Image Colorspace Methods                     %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/property.h"
44 #include "MagickCore/cache.h"
45 #include "MagickCore/cache-private.h"
46 #include "MagickCore/cache-view.h"
47 #include "MagickCore/color.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/colorspace-private.h"
51 #include "MagickCore/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/image.h"
54 #include "MagickCore/image-private.h"
55 #include "MagickCore/gem.h"
56 #include "MagickCore/gem-private.h"
57 #include "MagickCore/memory_.h"
58 #include "MagickCore/monitor.h"
59 #include "MagickCore/monitor-private.h"
60 #include "MagickCore/pixel-accessor.h"
61 #include "MagickCore/pixel-private.h"
62 #include "MagickCore/quantize.h"
63 #include "MagickCore/quantum.h"
64 #include "MagickCore/quantum-private.h"
65 #include "MagickCore/resource_.h"
66 #include "MagickCore/string_.h"
67 #include "MagickCore/string-private.h"
68 #include "MagickCore/utility.h"
69 \f
70 /*
71   Typedef declarations.
72 */
73 typedef struct _TransformPacket
74 {
75   MagickRealType
76     x,
77     y,
78     z;
79 } TransformPacket;
80 \f
81 /*
82   Forward declarations.
83 */
84 static MagickBooleanType
85   TransformsRGBImage(Image *,const ColorspaceType,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 ConvertXYZToLMS(const double x,const double y,
119   const double z,double *L,double *M,double *S)
120 {
121   double
122     l,
123     m,
124     s;
125
126   /*
127     Convert XYZ to LMS colorspace.
128   */
129   assert(L != (double *) NULL);
130   assert(M != (double *) NULL);
131   assert(S != (double *) NULL);
132   l=0.7328f*x+0.4296f*y-0.1624f*z;
133   m=(-0.7036f*x+1.6975f*y+0.0415f*z);
134   s=0.0030f*x+0.0136f*y+0.9834f*z;
135   *L=QuantumRange*l;
136   *M=QuantumRange*m;
137   *S=QuantumRange*s;
138 }
139
140 static inline void ConvertRGBToXYZ(const double red,const double green,
141   const double blue,double *X,double *Y,double *Z)
142 {
143   double
144     b,
145     g,
146     r;
147
148   assert(X != (double *) NULL);
149   assert(Y != (double *) NULL);
150   assert(Z != (double *) NULL);
151   r=QuantumScale*red;
152   g=QuantumScale*green;
153   b=QuantumScale*blue;
154   *X=0.41239558896741421610*r+0.35758343076371481710*g+0.18049264738170157350*b;
155   *Y=0.21258623078559555160*r+0.71517030370341084990*g+0.07220049864333622685*b;
156   *Z=0.01929721549174694484*r+0.11918386458084853180*g+0.95049712513157976600*b;
157 }
158
159 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
160   double *L,double *a,double *b)
161 {
162 #define D65X  (0.950470f)
163 #define D65Y  (1.0f)
164 #define D65Z  (1.088830f)
165 #define CIEEpsilon  (216.0f/24389.0f)
166 #define CIEK  (24389.0f/27.0f)
167
168   double
169     x,
170     y,
171     z;
172
173   assert(L != (double *) NULL);
174   assert(a != (double *) NULL);
175   assert(b != (double *) NULL);
176   if ((X/D65X) > CIEEpsilon)
177     x=pow(X/D65X,1.0/3.0);
178   else
179     x=(CIEK*X/D65X+16.0f)/116.0f;
180   if ((Y/D65Y) > CIEEpsilon)
181     y=pow(Y/D65Y,1.0/3.0);
182   else
183     y=(CIEK*Y/D65Y+16.0f)/116.0f;
184   if ((Z/D65Z) > CIEEpsilon)
185     z=pow(Z/D65Z,1.0/3.0);
186   else
187     z=(CIEK*Z/D65Z+16.0f)/116.0f;
188   *L=((116.0f*y)-16.0f)/100.0f;
189   *a=(500.0f*(x-y))/255.0f+0.5f;
190   *b=(200.0f*(y-z))/255.0f+0.5f;
191 }
192
193 static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
194   double *L,double *u,double *v)
195 {
196   double
197     alpha;
198
199   assert(L != (double *) NULL);
200   assert(u != (double *) NULL);
201   assert(v != (double *) NULL);
202   if ((Y/D65Y) > CIEEpsilon)
203     *L=(double) (116.0f*pow(Y/D65Y,1.0/3.0)-16.0f);
204   else
205     *L=CIEK*(Y/D65Y);
206   alpha=PerceptibleReciprocal(X+15.0f*Y+3.0f*Z);
207   *u=13.0f*(*L)*((4.0f*alpha*X)-(4.0f*D65X/(D65X+15.0f*D65Y+3.0f*D65Z)));
208   *v=13.0f*(*L)*((9.0f*alpha*Y)-(9.0f*D65Y/(D65X+15.0f*D65Y+3.0f*D65Z)));
209   *L/=100.0f;
210   *u=(*u+134.0f)/354.0f;
211   *v=(*v+140.0f)/262.0f;
212 }
213
214 static MagickBooleanType sRGBTransformImage(Image *image,
215   const ColorspaceType colorspace,ExceptionInfo *exception)
216 {
217 #define sRGBTransformImageTag  "RGBTransform/Image"
218
219   CacheView
220     *image_view;
221
222   MagickBooleanType
223     status;
224
225   MagickOffsetType
226     progress;
227
228   PrimaryInfo
229     primary_info;
230
231   register ssize_t
232     i;
233
234   ssize_t
235     y;
236
237   TransformPacket
238     *x_map,
239     *y_map,
240     *z_map;
241
242   assert(image != (Image *) NULL);
243   assert(image->signature == MagickSignature);
244   if (image->debug != MagickFalse)
245     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
246   assert(colorspace != sRGBColorspace);
247   assert(colorspace != TransparentColorspace);
248   assert(colorspace != UndefinedColorspace);
249   status=MagickTrue;
250   progress=0;
251   switch (colorspace)
252   {
253     case CMYColorspace:
254     {
255       /*
256         Convert RGB to CMY colorspace.
257       */
258       if (image->storage_class == PseudoClass)
259         {
260           if (SyncImage(image,exception) == MagickFalse)
261             return(MagickFalse);
262           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
263             return(MagickFalse);
264         }
265       image_view=AcquireAuthenticCacheView(image,exception);
266 #if defined(MAGICKCORE_OPENMP_SUPPORT)
267       #pragma omp parallel for schedule(static,4) shared(status) \
268         dynamic_number_threads(image,image->columns,image->rows,1)
269 #endif
270       for (y=0; y < (ssize_t) image->rows; y++)
271       {
272         MagickBooleanType
273           sync;
274
275         register ssize_t
276           x;
277
278         register Quantum
279           *restrict q;
280
281         if (status == MagickFalse)
282           continue;
283         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
284           exception);
285         if (q == (Quantum *) NULL)
286           {
287             status=MagickFalse;
288             continue;
289           }
290         for (x=0; x < (ssize_t) image->columns; x++)
291         {
292           double
293             cyan,
294             magenta,
295             yellow;
296
297           cyan=DecodesRGBGamma((MagickRealType) GetPixelCyan(image,q));
298           magenta=DecodesRGBGamma((MagickRealType) GetPixelMagenta(image,q));
299           yellow=DecodesRGBGamma((MagickRealType) GetPixelYellow(image,q));
300           SetPixelCyan(image,ClampToQuantum(QuantumRange-cyan),q);
301           SetPixelMagenta(image,ClampToQuantum(QuantumRange-magenta),q);
302           SetPixelYellow(image,ClampToQuantum(QuantumRange-yellow),q);
303           q+=GetPixelChannels(image);
304         }
305         sync=SyncCacheViewAuthenticPixels(image_view,exception);
306         if (sync == MagickFalse)
307           status=MagickFalse;
308       }
309       image_view=DestroyCacheView(image_view);
310       image->type=image->alpha_trait != BlendPixelTrait ? ColorSeparationType :
311         ColorSeparationMatteType;
312       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
313         return(MagickFalse);
314       return(status);
315     }
316     case CMYKColorspace:
317     {
318       PixelInfo
319         zero;
320
321       /*
322         Convert RGB to CMYK colorspace.
323       */
324       if (image->storage_class == PseudoClass)
325         {
326           if (SyncImage(image,exception) == MagickFalse)
327             return(MagickFalse);
328           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
329             return(MagickFalse);
330         }
331       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
332         return(MagickFalse);
333       GetPixelInfo(image,&zero);
334       image_view=AcquireAuthenticCacheView(image,exception);
335 #if defined(MAGICKCORE_OPENMP_SUPPORT)
336       #pragma omp parallel for schedule(static,4) shared(status) \
337         dynamic_number_threads(image,image->columns,image->rows,1)
338 #endif
339       for (y=0; y < (ssize_t) image->rows; y++)
340       {
341         MagickBooleanType
342           sync;
343
344         PixelInfo
345           pixel;
346
347         register ssize_t
348           x;
349
350         register Quantum
351           *restrict q;
352
353         if (status == MagickFalse)
354           continue;
355         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
356           exception);
357         if (q == (Quantum *) NULL)
358           {
359             status=MagickFalse;
360             continue;
361           }
362         pixel=zero;
363         for (x=0; x < (ssize_t) image->columns; x++)
364         {
365           GetPixelInfoPixel(image,q,&pixel);
366           pixel.red=DecodesRGBGamma(pixel.red);
367           pixel.green=DecodesRGBGamma(pixel.green);
368           pixel.blue=DecodesRGBGamma(pixel.blue);
369           ConvertRGBToCMYK(&pixel);
370           SetPixelInfoPixel(image,&pixel,q);
371           q+=GetPixelChannels(image);
372         }
373         sync=SyncCacheViewAuthenticPixels(image_view,exception);
374         if (sync == MagickFalse)
375           status=MagickFalse;
376       }
377       image_view=DestroyCacheView(image_view);
378       image->type=image->alpha_trait != BlendPixelTrait ? ColorSeparationType :
379         ColorSeparationMatteType;
380       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
381         return(MagickFalse);
382       return(status);
383     }
384     case GRAYColorspace:
385     case Rec601LumaColorspace:
386     {
387       /*
388         Transform image from sRGB to GRAY.
389       */
390       if (image->storage_class == PseudoClass)
391         {
392           if (SyncImage(image,exception) == MagickFalse)
393             return(MagickFalse);
394           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
395             return(MagickFalse);
396         }
397       image_view=AcquireAuthenticCacheView(image,exception);
398 #if defined(MAGICKCORE_OPENMP_SUPPORT)
399       #pragma omp parallel for schedule(static,4) shared(status) \
400         dynamic_number_threads(image,image->columns,image->rows,1)
401 #endif
402       for (y=0; y < (ssize_t) image->rows; y++)
403       {
404         MagickBooleanType
405           sync;
406
407         register ssize_t
408           x;
409
410         register Quantum
411           *restrict q;
412
413         if (status == MagickFalse)
414           continue;
415         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
416           exception);
417         if (q == (Quantum *) NULL)
418           {
419             status=MagickFalse;
420             continue;
421           }
422         for (x=0; x < (ssize_t) image->columns; x++)
423         {
424           double
425             blue,
426             gray,
427             green,
428             red;
429
430           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
431           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
432           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
433           gray=0.298839f*red+0.586811f*green+0.114350f*blue;
434           SetPixelGray(image,ClampToQuantum(gray),q);
435           q+=GetPixelChannels(image);
436         }
437         sync=SyncCacheViewAuthenticPixels(image_view,exception);
438         if (sync == MagickFalse)
439           status=MagickFalse;
440       }
441       image_view=DestroyCacheView(image_view);
442       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
443         return(MagickFalse);
444       image->type=GrayscaleType;
445       return(status);
446     }
447     case HCLColorspace:
448     {
449       /*
450         Transform image from sRGB to HCL.
451       */
452       if (image->storage_class == PseudoClass)
453         {
454           if (SyncImage(image,exception) == MagickFalse)
455             return(MagickFalse);
456           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
457             return(MagickFalse);
458         }
459       image_view=AcquireAuthenticCacheView(image,exception);
460 #if defined(MAGICKCORE_OPENMP_SUPPORT)
461       #pragma omp parallel for schedule(static,4) shared(status) \
462         dynamic_number_threads(image,image->columns,image->rows,1)
463 #endif
464       for (y=0; y < (ssize_t) image->rows; y++)
465       {
466         MagickBooleanType
467           sync;
468
469         register ssize_t
470           x;
471
472         register Quantum
473           *restrict q;
474
475         if (status == MagickFalse)
476           continue;
477         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
478           exception);
479         if (q == (Quantum *) NULL)
480           {
481             status=MagickFalse;
482             continue;
483           }
484         for (x=0; x < (ssize_t) image->columns; x++)
485         {
486           double
487             blue,
488             chroma,
489             green,
490             hue,
491             luma,
492             red;
493
494           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
495           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
496           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
497           ConvertRGBToHCL(red,green,blue,&hue,&chroma,&luma);
498           SetPixelRed(image,ClampToQuantum(QuantumRange*hue),q);
499           SetPixelGreen(image,ClampToQuantum(QuantumRange*chroma),q);
500           SetPixelBlue(image,ClampToQuantum(QuantumRange*luma),q);
501           q+=GetPixelChannels(image);
502         }
503         sync=SyncCacheViewAuthenticPixels(image_view,exception);
504         if (sync == MagickFalse)
505           status=MagickFalse;
506       }
507       image_view=DestroyCacheView(image_view);
508       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
509         return(MagickFalse);
510       return(status);
511     }
512     case HSBColorspace:
513     {
514       /*
515         Transform image from sRGB to HSB.
516       */
517       if (image->storage_class == PseudoClass)
518         {
519           if (SyncImage(image,exception) == MagickFalse)
520             return(MagickFalse);
521           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
522             return(MagickFalse);
523         }
524       image_view=AcquireAuthenticCacheView(image,exception);
525 #if defined(MAGICKCORE_OPENMP_SUPPORT)
526       #pragma omp parallel for schedule(static,4) shared(status) \
527         dynamic_number_threads(image,image->columns,image->rows,1)
528 #endif
529       for (y=0; y < (ssize_t) image->rows; y++)
530       {
531         MagickBooleanType
532           sync;
533
534         register ssize_t
535           x;
536
537         register Quantum
538           *restrict q;
539
540         if (status == MagickFalse)
541           continue;
542         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
543           exception);
544         if (q == (Quantum *) NULL)
545           {
546             status=MagickFalse;
547             continue;
548           }
549         for (x=0; x < (ssize_t) image->columns; x++)
550         {
551           double
552             blue,
553             brightness,
554             green,
555             hue,
556             red,
557             saturation;
558
559           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
560           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
561           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
562           ConvertRGBToHSB(red,green,blue,&hue,&saturation,&brightness);
563           SetPixelRed(image,ClampToQuantum(QuantumRange*hue),q);
564           SetPixelGreen(image,ClampToQuantum(QuantumRange*saturation),q);
565           SetPixelBlue(image,ClampToQuantum(QuantumRange*brightness),q);
566           q+=GetPixelChannels(image);
567         }
568         sync=SyncCacheViewAuthenticPixels(image_view,exception);
569         if (sync == MagickFalse)
570           status=MagickFalse;
571       }
572       image_view=DestroyCacheView(image_view);
573       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
574         return(MagickFalse);
575       return(status);
576     }
577     case HSLColorspace:
578     {
579       /*
580         Transform image from sRGB to HSL.
581       */
582       if (image->storage_class == PseudoClass)
583         {
584           if (SyncImage(image,exception) == MagickFalse)
585             return(MagickFalse);
586           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
587             return(MagickFalse);
588         }
589       image_view=AcquireAuthenticCacheView(image,exception);
590 #if defined(MAGICKCORE_OPENMP_SUPPORT)
591       #pragma omp parallel for schedule(static,4) shared(status) \
592         dynamic_number_threads(image,image->columns,image->rows,1)
593 #endif
594       for (y=0; y < (ssize_t) image->rows; y++)
595       {
596         MagickBooleanType
597           sync;
598
599         register ssize_t
600           x;
601
602         register Quantum
603           *restrict q;
604
605         if (status == MagickFalse)
606           continue;
607         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
608           exception);
609         if (q == (Quantum *) NULL)
610           {
611             status=MagickFalse;
612             continue;
613           }
614         for (x=0; x < (ssize_t) image->columns; x++)
615         {
616           double
617             blue,
618             green,
619             hue,
620             lightness,
621             red,
622             saturation;
623
624           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
625           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
626           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
627           ConvertRGBToHSL(red,green,blue,&hue,&saturation,&lightness);
628           SetPixelRed(image,ClampToQuantum(QuantumRange*hue),q);
629           SetPixelGreen(image,ClampToQuantum(QuantumRange*saturation),q);
630           SetPixelBlue(image,ClampToQuantum(QuantumRange*lightness),q);
631           q+=GetPixelChannels(image);
632         }
633         sync=SyncCacheViewAuthenticPixels(image_view,exception);
634         if (sync == MagickFalse)
635           status=MagickFalse;
636       }
637       image_view=DestroyCacheView(image_view);
638       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
639         return(MagickFalse);
640       return(status);
641     }
642     case HWBColorspace:
643     {
644       /*
645         Transform image from sRGB to HWB.
646       */
647       if (image->storage_class == PseudoClass)
648         {
649           if (SyncImage(image,exception) == MagickFalse)
650             return(MagickFalse);
651           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
652             return(MagickFalse);
653         }
654       image_view=AcquireAuthenticCacheView(image,exception);
655 #if defined(MAGICKCORE_OPENMP_SUPPORT)
656       #pragma omp parallel for schedule(static,4) shared(status) \
657         dynamic_number_threads(image,image->columns,image->rows,1)
658 #endif
659       for (y=0; y < (ssize_t) image->rows; y++)
660       {
661         MagickBooleanType
662           sync;
663
664         register ssize_t
665           x;
666
667         register Quantum
668           *restrict q;
669
670         if (status == MagickFalse)
671           continue;
672         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
673           exception);
674         if (q == (Quantum *) NULL)
675           {
676             status=MagickFalse;
677             continue;
678           }
679         for (x=0; x < (ssize_t) image->columns; x++)
680         {
681           double
682             blackness,
683             blue,
684             green,
685             hue,
686             red,
687             whiteness;
688
689           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
690           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
691           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
692           ConvertRGBToHWB(red,green,blue,&hue,&whiteness,&blackness);
693           SetPixelRed(image,ClampToQuantum(QuantumRange*hue),q);
694           SetPixelGreen(image,ClampToQuantum(QuantumRange*whiteness),q);
695           SetPixelBlue(image,ClampToQuantum(QuantumRange*blackness),q);
696           q+=GetPixelChannels(image);
697         }
698         sync=SyncCacheViewAuthenticPixels(image_view,exception);
699         if (sync == MagickFalse)
700           status=MagickFalse;
701       }
702       image_view=DestroyCacheView(image_view);
703       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
704         return(MagickFalse);
705       return(status);
706     }
707     case LabColorspace:
708     {
709       /*
710         Transform image from sRGB to Lab.
711       */
712       if (image->storage_class == PseudoClass)
713         {
714           if (SyncImage(image,exception) == MagickFalse)
715             return(MagickFalse);
716           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
717             return(MagickFalse);
718         }
719       image_view=AcquireAuthenticCacheView(image,exception);
720 #if defined(MAGICKCORE_OPENMP_SUPPORT)
721       #pragma omp parallel for schedule(static,4) shared(status) \
722         dynamic_number_threads(image,image->columns,image->rows,1)
723 #endif
724       for (y=0; y < (ssize_t) image->rows; y++)
725       {
726         MagickBooleanType
727           sync;
728
729         register ssize_t
730           x;
731
732         register Quantum
733           *restrict q;
734
735         if (status == MagickFalse)
736           continue;
737         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
738           exception);
739         if (q == (Quantum *) NULL)
740           {
741             status=MagickFalse;
742             continue;
743           }
744         for (x=0; x < (ssize_t) image->columns; x++)
745         {
746           double
747             a,
748             b,
749             blue,
750             green,
751             L,
752             red,
753             X,
754             Y,
755             Z;
756
757           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
758           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
759           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
760           ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
761           ConvertXYZToLab(X,Y,Z,&L,&a,&b);
762           SetPixelRed(image,ClampToQuantum(QuantumRange*L),q);
763           SetPixelGreen(image,ClampToQuantum(QuantumRange*a),q);
764           SetPixelBlue(image,ClampToQuantum(QuantumRange*b),q);
765           q+=GetPixelChannels(image);
766         }
767         sync=SyncCacheViewAuthenticPixels(image_view,exception);
768         if (sync == MagickFalse)
769           status=MagickFalse;
770       }
771       image_view=DestroyCacheView(image_view);
772       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
773         return(MagickFalse);
774       return(status);
775     }
776     case LCHColorspace:
777     {
778       /*
779         Transform image from sRGB to LCH.
780       */
781       if (image->storage_class == PseudoClass)
782         {
783           if (SyncImage(image,exception) == MagickFalse)
784             return(MagickFalse);
785           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
786             return(MagickFalse);
787         }
788       image_view=AcquireAuthenticCacheView(image,exception);
789 #if defined(MAGICKCORE_OPENMP_SUPPORT)
790       #pragma omp parallel for schedule(static,4) shared(status) \
791         dynamic_number_threads(image,image->columns,image->rows,1)
792 #endif
793       for (y=0; y < (ssize_t) image->rows; y++)
794       {
795         MagickBooleanType
796           sync;
797
798         register ssize_t
799           x;
800
801         register Quantum
802           *restrict q;
803
804         if (status == MagickFalse)
805           continue;
806         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
807           exception);
808         if (q == (Quantum *) NULL)
809           {
810             status=MagickFalse;
811             continue;
812           }
813         for (x=0; x < (ssize_t) image->columns; x++)
814         {
815           double
816             a,
817             b,
818             blue,
819             C,
820             green,
821             H,
822             L,
823             red,
824             X,
825             Y,
826             Z;
827
828           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
829           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
830           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
831           ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
832           ConvertXYZToLab(X,Y,Z,&L,&a,&b);
833           C=sqrt(a*a+b*b);
834           H=atan2(b,a)*180.0f/MagickPI;
835           if (H < 0.0f)
836             H+=1.0f;
837           SetPixelRed(image,ClampToQuantum(QuantumRange*L),q);
838           SetPixelGreen(image,ClampToQuantum(QuantumRange*C),q);
839           SetPixelBlue(image,ClampToQuantum(QuantumRange*H),q);
840           q+=GetPixelChannels(image);
841         }
842         sync=SyncCacheViewAuthenticPixels(image_view,exception);
843         if (sync == MagickFalse)
844           status=MagickFalse;
845       }
846       image_view=DestroyCacheView(image_view);
847       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
848         return(MagickFalse);
849       return(status);
850     }
851     case LMSColorspace:
852     {
853       /*
854         Transform image from sRGB to LMS.
855       */
856       if (image->storage_class == PseudoClass)
857         {
858           if (SyncImage(image,exception) == MagickFalse)
859             return(MagickFalse);
860           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
861             return(MagickFalse);
862         }
863       image_view=AcquireAuthenticCacheView(image,exception);
864 #if defined(MAGICKCORE_OPENMP_SUPPORT)
865       #pragma omp parallel for schedule(static,4) shared(status) \
866         dynamic_number_threads(image,image->columns,image->rows,1)
867 #endif
868       for (y=0; y < (ssize_t) image->rows; y++)
869       {
870         MagickBooleanType
871           sync;
872
873         register ssize_t
874           x;
875
876         register Quantum
877           *restrict q;
878
879         if (status == MagickFalse)
880           continue;
881         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
882           exception);
883         if (q == (Quantum *) NULL)
884           {
885             status=MagickFalse;
886             continue;
887           }
888         for (x=0; x < (ssize_t) image->columns; x++)
889         {
890           double
891             blue,
892             green,
893             L,
894             M,
895             red,
896             S,
897             X,
898             Y,
899             Z;
900
901           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
902           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
903           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
904           ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
905           ConvertXYZToLMS(X,Y,Z,&L,&M,&S);
906           SetPixelRed(image,ClampToQuantum(QuantumRange*L),q);
907           SetPixelGreen(image,ClampToQuantum(QuantumRange*M),q);
908           SetPixelBlue(image,ClampToQuantum(QuantumRange*S),q);
909           q+=GetPixelChannels(image);
910         }
911         sync=SyncCacheViewAuthenticPixels(image_view,exception);
912         if (sync == MagickFalse)
913           status=MagickFalse;
914       }
915       image_view=DestroyCacheView(image_view);
916       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
917         return(MagickFalse);
918       return(status);
919     }
920     case LogColorspace:
921     {
922 #define DisplayGamma  (1.0f/1.7f)
923 #define FilmGamma  0.6f
924 #define ReferenceBlack  95.0f
925 #define ReferenceWhite  685.0f
926
927       const char
928         *value;
929
930       double
931         black,
932         density,
933         film_gamma,
934         gamma,
935         reference_black,
936         reference_white;
937
938       Quantum
939         *logmap;
940
941       /*
942         Transform RGB to Log colorspace.
943       */
944       density=DisplayGamma;
945       gamma=DisplayGamma;
946       value=GetImageProperty(image,"gamma",exception);
947       if (value != (const char *) NULL)
948         gamma=PerceptibleReciprocal(StringToDouble(value,(char **) NULL));
949       film_gamma=FilmGamma;
950       value=GetImageProperty(image,"film-gamma",exception);
951       if (value != (const char *) NULL)
952         film_gamma=StringToDouble(value,(char **) NULL);
953       reference_black=ReferenceBlack;
954       value=GetImageProperty(image,"reference-black",exception);
955       if (value != (const char *) NULL)
956         reference_black=StringToDouble(value,(char **) NULL);
957       reference_white=ReferenceWhite;
958       value=GetImageProperty(image,"reference-white",exception);
959       if (value != (const char *) NULL)
960         reference_white=StringToDouble(value,(char **) NULL);
961       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
962         sizeof(*logmap));
963       if (logmap == (Quantum *) NULL)
964         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
965           image->filename);
966       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*0.002f/
967         film_gamma);
968 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
969       #pragma omp parallel for schedule(static,4) \
970         dynamic_number_threads(image,image->columns,1,1)
971 #endif
972       for (i=0; i <= (ssize_t) MaxMap; i++)
973         logmap[i]=ScaleMapToQuantum((double) (MaxMap*(reference_white+
974           log10(black+(1.0*i/MaxMap)*(1.0-black))/((gamma/density)*0.002f/
975           film_gamma))/1024.0));
976       image_view=AcquireAuthenticCacheView(image,exception);
977 #if defined(MAGICKCORE_OPENMP_SUPPORT)
978       #pragma omp parallel for schedule(static,4) shared(status) \
979         dynamic_number_threads(image,image->columns,image->rows,1)
980 #endif
981       for (y=0; y < (ssize_t) image->rows; y++)
982       {
983         MagickBooleanType
984           sync;
985
986         register ssize_t
987           x;
988
989         register Quantum
990           *restrict q;
991
992         if (status == MagickFalse)
993           continue;
994         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
995           exception);
996         if (q == (Quantum *) NULL)
997           {
998             status=MagickFalse;
999             continue;
1000           }
1001         for (x=(ssize_t) image->columns; x != 0; x--)
1002         {
1003           double
1004             blue,
1005             green,
1006             red;
1007
1008           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
1009           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
1010           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
1011           SetPixelRed(image,logmap[ScaleQuantumToMap(
1012             ClampToQuantum(red))],q);
1013           SetPixelGreen(image,logmap[ScaleQuantumToMap(
1014             ClampToQuantum(green))],q);
1015           SetPixelBlue(image,logmap[ScaleQuantumToMap(
1016             ClampToQuantum(blue))],q);
1017           q+=GetPixelChannels(image);
1018         }
1019         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1020         if (sync == MagickFalse)
1021           status=MagickFalse;
1022       }
1023       image_view=DestroyCacheView(image_view);
1024       logmap=(Quantum *) RelinquishMagickMemory(logmap);
1025       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
1026         return(MagickFalse);
1027       return(status);
1028     }
1029     case LuvColorspace:
1030     {
1031       /*
1032         Transform image from sRGB to Luv.
1033       */
1034       if (image->storage_class == PseudoClass)
1035         {
1036           if (SyncImage(image,exception) == MagickFalse)
1037             return(MagickFalse);
1038           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1039             return(MagickFalse);
1040         }
1041       image_view=AcquireAuthenticCacheView(image,exception);
1042 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1043       #pragma omp parallel for schedule(static,4) shared(status) \
1044         dynamic_number_threads(image,image->columns,image->rows,1)
1045 #endif
1046       for (y=0; y < (ssize_t) image->rows; y++)
1047       {
1048         MagickBooleanType
1049           sync;
1050
1051         register ssize_t
1052           x;
1053
1054         register Quantum
1055           *restrict q;
1056
1057         if (status == MagickFalse)
1058           continue;
1059         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1060           exception);
1061         if (q == (Quantum *) NULL)
1062           {
1063             status=MagickFalse;
1064             continue;
1065           }
1066         for (x=0; x < (ssize_t) image->columns; x++)
1067         {
1068           double
1069             blue,
1070             green,
1071             L,
1072             red,
1073             u,
1074             v,
1075             X,
1076             Y,
1077             Z;
1078
1079           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
1080           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
1081           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
1082           ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1083           ConvertXYZToLuv(X,Y,Z,&L,&u,&v);
1084           SetPixelRed(image,ClampToQuantum(QuantumRange*L),q);
1085           SetPixelGreen(image,ClampToQuantum(QuantumRange*u),q);
1086           SetPixelBlue(image,ClampToQuantum(QuantumRange*v),q);
1087           q+=GetPixelChannels(image);
1088         }
1089         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1090         if (sync == MagickFalse)
1091           status=MagickFalse;
1092       }
1093       image_view=DestroyCacheView(image_view);
1094       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
1095         return(MagickFalse);
1096       return(status);
1097     }
1098     case Rec709LumaColorspace:
1099     {
1100       /*
1101         Transform image from sRGB to Rec709Luma.
1102       */
1103       if (image->storage_class == PseudoClass)
1104         {
1105           if (SyncImage(image,exception) == MagickFalse)
1106             return(MagickFalse);
1107           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1108             return(MagickFalse);
1109         }
1110       image_view=AcquireAuthenticCacheView(image,exception);
1111 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1112       #pragma omp parallel for schedule(static,4) shared(status) \
1113         dynamic_number_threads(image,image->columns,image->rows,1)
1114 #endif
1115       for (y=0; y < (ssize_t) image->rows; y++)
1116       {
1117         MagickBooleanType
1118           sync;
1119
1120         register ssize_t
1121           x;
1122
1123         register Quantum
1124           *restrict q;
1125
1126         if (status == MagickFalse)
1127           continue;
1128         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1129           exception);
1130         if (q == (Quantum *) NULL)
1131           {
1132             status=MagickFalse;
1133             continue;
1134           }
1135         for (x=0; x < (ssize_t) image->columns; x++)
1136         {
1137           double
1138             blue,
1139             gray,
1140             green,
1141             red;
1142
1143           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
1144           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
1145           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
1146           gray=0.212600f*red+0.715200f*green+0.072200f*blue;
1147           SetPixelGray(image,ClampToQuantum(gray),q);
1148           q+=GetPixelChannels(image);
1149         }
1150         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1151         if (sync == MagickFalse)
1152           status=MagickFalse;
1153       }
1154       image_view=DestroyCacheView(image_view);
1155       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
1156         return(MagickFalse);
1157       image->type=GrayscaleType;
1158       return(status);
1159     }
1160     case RGBColorspace:
1161     {
1162       /*
1163         Transform image from sRGB to linear RGB.
1164       */
1165       if (image->storage_class == PseudoClass)
1166         {
1167           if (SyncImage(image,exception) == MagickFalse)
1168             return(MagickFalse);
1169           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1170             return(MagickFalse);
1171         }
1172       image_view=AcquireAuthenticCacheView(image,exception);
1173 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1174       #pragma omp parallel for schedule(static,4) shared(status) \
1175         dynamic_number_threads(image,image->columns,image->rows,1)
1176 #endif
1177       for (y=0; y < (ssize_t) image->rows; y++)
1178       {
1179         MagickBooleanType
1180           sync;
1181
1182         register ssize_t
1183           x;
1184
1185         register Quantum
1186           *restrict q;
1187
1188         if (status == MagickFalse)
1189           continue;
1190         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1191           exception);
1192         if (q == (Quantum *) NULL)
1193           {
1194             status=MagickFalse;
1195             continue;
1196           }
1197         for (x=0; x < (ssize_t) image->columns; x++)
1198         {
1199           double
1200             blue,
1201             green,
1202             red;
1203
1204           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
1205           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
1206           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
1207           SetPixelRed(image,ClampToQuantum(red),q);
1208           SetPixelGreen(image,ClampToQuantum(green),q);
1209           SetPixelBlue(image,ClampToQuantum(blue),q);
1210           q+=GetPixelChannels(image);
1211         }
1212         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1213         if (sync == MagickFalse)
1214           status=MagickFalse;
1215       }
1216       image_view=DestroyCacheView(image_view);
1217       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
1218         return(MagickFalse);
1219       return(status);
1220     }
1221     case XYZColorspace:
1222     {
1223       /*
1224         Transform image from sRGB to XYZ.
1225       */
1226       if (image->storage_class == PseudoClass)
1227         {
1228           if (SyncImage(image,exception) == MagickFalse)
1229             return(MagickFalse);
1230           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1231             return(MagickFalse);
1232         }
1233       image_view=AcquireAuthenticCacheView(image,exception);
1234 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1235       #pragma omp parallel for schedule(static,4) shared(status) \
1236         dynamic_number_threads(image,image->columns,image->rows,1)
1237 #endif
1238       for (y=0; y < (ssize_t) image->rows; y++)
1239       {
1240         MagickBooleanType
1241           sync;
1242
1243         register ssize_t
1244           x;
1245
1246         register Quantum
1247           *restrict q;
1248
1249         if (status == MagickFalse)
1250           continue;
1251         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1252           exception);
1253         if (q == (Quantum *) NULL)
1254           {
1255             status=MagickFalse;
1256             continue;
1257           }
1258         for (x=0; x < (ssize_t) image->columns; x++)
1259         {
1260           double
1261             blue,
1262             green,
1263             red,
1264             X,
1265             Y,
1266             Z;
1267
1268           red=DecodesRGBGamma((MagickRealType) GetPixelRed(image,q));
1269           green=DecodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
1270           blue=DecodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
1271           ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1272           SetPixelRed(image,ClampToQuantum(QuantumRange*X),q);
1273           SetPixelGreen(image,ClampToQuantum(QuantumRange*Y),q);
1274           SetPixelBlue(image,ClampToQuantum(QuantumRange*Z),q);
1275           q+=GetPixelChannels(image);
1276         }
1277         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1278         if (sync == MagickFalse)
1279           status=MagickFalse;
1280       }
1281       image_view=DestroyCacheView(image_view);
1282       if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
1283         return(MagickFalse);
1284       return(status);
1285     }
1286     default:
1287       break;
1288   }
1289   /*
1290     Allocate the tables.
1291   */
1292   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1293     sizeof(*x_map));
1294   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1295     sizeof(*y_map));
1296   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1297     sizeof(*z_map));
1298   if ((x_map == (TransformPacket *) NULL) ||
1299       (y_map == (TransformPacket *) NULL) ||
1300       (z_map == (TransformPacket *) NULL))
1301     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1302       image->filename);
1303   (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
1304   switch (colorspace)
1305   {
1306     case OHTAColorspace:
1307     {
1308       /*
1309         Initialize OHTA tables:
1310
1311           I1 = 0.33333*R+0.33334*G+0.33333*B
1312           I2 = 0.50000*R+0.00000*G-0.50000*B
1313           I3 =-0.25000*R+0.50000*G-0.25000*B
1314
1315         I and Q, normally -0.5 through 0.5, are normalized to the range 0
1316         through QuantumRange.
1317       */
1318       primary_info.y=(double) (MaxMap+1.0f)/2.0f;
1319       primary_info.z=(double) (MaxMap+1.0f)/2.0f;
1320 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
1321       #pragma omp parallel for schedule(static,4) \
1322         dynamic_number_threads(image,image->columns,1,1)
1323 #endif
1324       for (i=0; i <= (ssize_t) MaxMap; i++)
1325       {
1326         x_map[i].x=(MagickRealType) (0.33333f*(float) i);
1327         y_map[i].x=(MagickRealType) (0.33334f*(float) i);
1328         z_map[i].x=(MagickRealType) (0.33333f*(float) i);
1329         x_map[i].y=(MagickRealType) (0.50000f*(float) i);
1330         y_map[i].y=(MagickRealType) (0.00000f*(float) i);
1331         z_map[i].y=(MagickRealType) (-0.50000f*(float) i);
1332         x_map[i].z=(MagickRealType) (-0.25000f*(float) i);
1333         y_map[i].z=(MagickRealType) (0.50000f*(float) i);
1334         z_map[i].z=(MagickRealType) (-0.25000f*(float) i);
1335       }
1336       break;
1337     }
1338     case Rec601YCbCrColorspace:
1339     case YCbCrColorspace:
1340     {
1341       /*
1342         Initialize YCbCr tables (ITU-R BT.601):
1343
1344           Y =  0.298839f0*R+0.586811f0*G+0.114350f0*B
1345           Cb= -0.1687367*R-0.3312640*G+0.5000000*B
1346           Cr=  0.5000000*R-0.4186880*G-0.0813120*B
1347
1348         Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
1349         through QuantumRange.
1350       */
1351       primary_info.y=(double) (MaxMap+1.0f)/2.0f;
1352       primary_info.z=(double) (MaxMap+1.0f)/2.0f;
1353 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
1354       #pragma omp parallel for schedule(static,4) \
1355         dynamic_number_threads(image,image->columns,1,1)
1356 #endif
1357       for (i=0; i <= (ssize_t) MaxMap; i++)
1358       {
1359         x_map[i].x=(MagickRealType) (0.298839f*(float) i);
1360         y_map[i].x=(MagickRealType) (0.586811f*(float) i);
1361         z_map[i].x=(MagickRealType) (0.114350f*(float) i);
1362         x_map[i].y=(MagickRealType) (-0.1687367f*(float) i);
1363         y_map[i].y=(MagickRealType) (-0.331264f*(float) i);
1364         z_map[i].y=(MagickRealType) (0.500000f*(float) i);
1365         x_map[i].z=(MagickRealType) (0.500000f*(float) i);
1366         y_map[i].z=(MagickRealType) (-0.418688f*(float) i);
1367         z_map[i].z=(MagickRealType) (-0.081312f*(float) i);
1368       }
1369       break;
1370     }
1371     case Rec709YCbCrColorspace:
1372     {
1373       /*
1374         Initialize YCbCr tables (ITU-R BT.709):
1375
1376           Y =  0.212600*R+0.715200*G+0.072200*B
1377           Cb= -0.114572*R-0.385428*G+0.500000*B
1378           Cr=  0.500000*R-0.454153*G-0.045847*B
1379
1380         Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
1381         through QuantumRange.
1382       */
1383       primary_info.y=(double) (MaxMap+1.0f)/2.0f;
1384       primary_info.z=(double) (MaxMap+1.0f)/2.0f;
1385 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
1386       #pragma omp parallel for schedule(static,4) \
1387         dynamic_number_threads(image,image->columns,1,1)
1388 #endif
1389       for (i=0; i <= (ssize_t) MaxMap; i++)
1390       {
1391         x_map[i].x=(MagickRealType) (0.212600f*(float) i);
1392         y_map[i].x=(MagickRealType) (0.715200f*(float) i);
1393         z_map[i].x=(MagickRealType) (0.072200f*(float) i);
1394         x_map[i].y=(MagickRealType) (-0.114572f*(float) i);
1395         y_map[i].y=(MagickRealType) (-0.385428f*(float) i);
1396         z_map[i].y=(MagickRealType) (0.500000f*(float) i);
1397         x_map[i].z=(MagickRealType) (0.500000f*(float) i);
1398         y_map[i].z=(MagickRealType) (-0.454153f*(float) i);
1399         z_map[i].z=(MagickRealType) (-0.045847f*(float) i);
1400       }
1401       break;
1402     }
1403     case YCCColorspace:
1404     {
1405       /*
1406         Initialize YCC tables:
1407
1408           Y =  0.298839f*R+0.586811f*G+0.114350f*B
1409           C1= -0.298839f*R-0.586811f*G+0.88600*B
1410           C2=  0.70100*R-0.586811f*G-0.114350f*B
1411
1412         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
1413       */
1414       primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
1415       primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
1416       for (i=0; i <= (ssize_t) (0.018f*MaxMap); i++)
1417       {
1418         x_map[i].x=0.003962014134275617*i;
1419         y_map[i].x=0.007778268551236748*i;
1420         z_map[i].x=0.001510600706713781*i;
1421         x_map[i].y=(-0.002426619775463276)*i;
1422         y_map[i].y=(-0.004763965913702149)*i;
1423         z_map[i].y=0.007190585689165425*i;
1424         x_map[i].z=0.006927257754597858*i;
1425         y_map[i].z=(-0.005800713697502058)*i;
1426         z_map[i].z=(-0.0011265440570958)*i;
1427       }
1428       for ( ; i <= (ssize_t) MaxMap; i++)
1429       {
1430         x_map[i].x=0.2201118963486454*(1.099*i-0.099);
1431         y_map[i].x=0.4321260306242638*(1.099*i-0.099);
1432         z_map[i].x=0.08392226148409894*(1.099*i-0.099);
1433         x_map[i].y=(-0.1348122097479598)*(1.099*i-0.099);
1434         y_map[i].y=(-0.2646647729834528)*(1.099*i-0.099);
1435         z_map[i].y=0.3994769827314126*(1.099*i-0.099);
1436         x_map[i].z=0.3848476530332144*(1.099*i-0.099);
1437         y_map[i].z=(-0.3222618720834477)*(1.099*i-0.099);
1438         z_map[i].z=(-0.06258578094976668)*(1.099*i-0.099);
1439       }
1440       break;
1441     }
1442     case YIQColorspace:
1443     {
1444       /*
1445         Initialize YIQ tables:
1446
1447           Y = 0.298839f*R+0.586811f*G+0.114350f*B
1448           I = 0.595716*R-0.274453*G-0.321263*B
1449           Q = 0.211456*R-0.522591*G+0.311135*B
1450
1451         I and Q, normally -0.5 through 0.5, are normalized to the range 0
1452         through QuantumRange.
1453       */
1454       primary_info.y=(double) (MaxMap+1.0f)/2.0f;
1455       primary_info.z=(double) (MaxMap+1.0f)/2.0f;
1456 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
1457       #pragma omp parallel for schedule(static,4) \
1458         dynamic_number_threads(image,image->columns,1,1)
1459 #endif
1460       for (i=0; i <= (ssize_t) MaxMap; i++)
1461       {
1462         x_map[i].x=(MagickRealType) (0.298839f*(float) i);
1463         y_map[i].x=(MagickRealType) (0.586811f*(float) i);
1464         z_map[i].x=(MagickRealType) (0.114350f*(float) i);
1465         x_map[i].y=(MagickRealType) (0.595716*(float) i);
1466         y_map[i].y=(MagickRealType) (-0.274453f*(float) i);
1467         z_map[i].y=(MagickRealType) (-0.321263f*(float) i);
1468         x_map[i].z=(MagickRealType) (0.211456f*(float) i);
1469         y_map[i].z=(MagickRealType) (-0.522591f*(float) i);
1470         z_map[i].z=(MagickRealType) (0.311135f*(float) i);
1471       }
1472       break;
1473     }
1474     case YPbPrColorspace:
1475     {
1476       /*
1477         Initialize YPbPr tables (ITU-R BT.601):
1478
1479           Y =  0.298839f0*R+0.586811f0*G+0.114350f0*B
1480           Pb= -0.1687367*R-0.3312640*G+0.5000000*B
1481           Pr=  0.5000000*R-0.4186880*G-0.0813120*B
1482
1483         Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0
1484         through QuantumRange.
1485       */
1486       primary_info.y=(double) (MaxMap+1.0f)/2.0f;
1487       primary_info.z=(double) (MaxMap+1.0f)/2.0f;
1488 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
1489       #pragma omp parallel for schedule(static,4) \
1490         dynamic_number_threads(image,image->columns,1,1)
1491 #endif
1492       for (i=0; i <= (ssize_t) MaxMap; i++)
1493       {
1494         x_map[i].x=(MagickRealType) (0.298839f*(float) i);
1495         y_map[i].x=(MagickRealType) (0.586811f*(float) i);
1496         z_map[i].x=(MagickRealType) (0.114350f*(float) i);
1497         x_map[i].y=(MagickRealType) (-0.1687367f*(float) i);
1498         y_map[i].y=(MagickRealType) (-0.331264*(float) i);
1499         z_map[i].y=(MagickRealType) (0.500000f*(float) i);
1500         x_map[i].z=(MagickRealType) (0.500000f*(float) i);
1501         y_map[i].z=(MagickRealType) (-0.418688f*(float) i);
1502         z_map[i].z=(MagickRealType) (-0.081312f*(float) i);
1503       }
1504       break;
1505     }
1506     case YUVColorspace:
1507     {
1508       /*
1509         Initialize YUV tables:
1510
1511           Y =  0.298839f*R+0.586811f*G+0.114350f*B
1512           U = -0.147130*R-0.288860*G+0.436000*B
1513           V =  0.615000*R-0.514990*G-0.100010*B
1514
1515         U and V, normally -0.5 through 0.5, are normalized to the range 0
1516         through QuantumRange.  Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
1517       */
1518       primary_info.y=(double) (MaxMap+1.0f)/2.0f;
1519       primary_info.z=(double) (MaxMap+1.0f)/2.0f;
1520 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
1521       #pragma omp parallel for schedule(static,4) \
1522         dynamic_number_threads(image,image->columns,1,1)
1523 #endif
1524       for (i=0; i <= (ssize_t) MaxMap; i++)
1525       {
1526         x_map[i].x=(MagickRealType) (0.298839f*(float) i);
1527         y_map[i].x=(MagickRealType) (0.586811f*(float) i);
1528         z_map[i].x=(MagickRealType) (0.114350f*(float) i);
1529         x_map[i].y=(MagickRealType) (-0.147130f*(float) i);
1530         y_map[i].y=(MagickRealType) (-0.288860f*(float) i);
1531         z_map[i].y=(MagickRealType) (0.436000f*(float) i);
1532         x_map[i].z=(MagickRealType) (0.615000f*(float) i);
1533         y_map[i].z=(MagickRealType) (-0.514990f*(float) i);
1534         z_map[i].z=(MagickRealType) (-0.100001f*(float) i);
1535       }
1536       break;
1537     }
1538     default:
1539     {
1540       /*
1541         Linear conversion tables.
1542       */
1543 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
1544       #pragma omp parallel for schedule(static,4) \
1545         dynamic_number_threads(image,image->columns,1,1)
1546 #endif
1547       for (i=0; i <= (ssize_t) MaxMap; i++)
1548       {
1549         x_map[i].x=(MagickRealType) (1.0*(float) i);
1550         y_map[i].x=(MagickRealType) 0.0f;
1551         z_map[i].x=(MagickRealType) 0.0f;
1552         x_map[i].y=(MagickRealType) 0.0f;
1553         y_map[i].y=(MagickRealType) (1.0*(float) i);
1554         z_map[i].y=(MagickRealType) 0.0f;
1555         x_map[i].z=(MagickRealType) 0.0f;
1556         y_map[i].z=(MagickRealType) 0.0f;
1557         z_map[i].z=(MagickRealType) (1.0*(float) i);
1558       }
1559       break;
1560     }
1561   }
1562   /*
1563     Convert from sRGB.
1564   */
1565   switch (image->storage_class)
1566   {
1567     case DirectClass:
1568     default:
1569     {
1570       /*
1571         Convert DirectClass image.
1572       */
1573       image_view=AcquireAuthenticCacheView(image,exception);
1574 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1575       #pragma omp parallel for schedule(static,4) shared(status) \
1576         dynamic_number_threads(image,image->columns,image->rows,1)
1577 #endif
1578       for (y=0; y < (ssize_t) image->rows; y++)
1579       {
1580         MagickBooleanType
1581           sync;
1582
1583         PixelInfo
1584           pixel;
1585
1586         register Quantum
1587           *restrict q;
1588
1589         register ssize_t
1590           x;
1591
1592         register unsigned int
1593           blue,
1594           green,
1595           red;
1596
1597         if (status == MagickFalse)
1598           continue;
1599         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1600           exception);
1601         if (q == (Quantum *) NULL)
1602           {
1603             status=MagickFalse;
1604             continue;
1605           }
1606         for (x=0; x < (ssize_t) image->columns; x++)
1607         {
1608           red=ScaleQuantumToMap(ClampToQuantum(DecodesRGBGamma(
1609             (MagickRealType) GetPixelRed(image,q))));
1610           green=ScaleQuantumToMap(ClampToQuantum(DecodesRGBGamma(
1611             (MagickRealType) GetPixelGreen(image,q))));
1612           blue=ScaleQuantumToMap(ClampToQuantum(DecodesRGBGamma(
1613             (MagickRealType) GetPixelBlue(image,q))));
1614           pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
1615             primary_info.x;
1616           pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
1617             primary_info.y;
1618           pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
1619             primary_info.z;
1620           SetPixelRed(image,ScaleMapToQuantum(pixel.red),q);
1621           SetPixelGreen(image,ScaleMapToQuantum(pixel.green),q);
1622           SetPixelBlue(image,ScaleMapToQuantum(pixel.blue),q);
1623           q+=GetPixelChannels(image);
1624         }
1625         sync=SyncCacheViewAuthenticPixels(image_view,exception);
1626         if (sync == MagickFalse)
1627           status=MagickFalse;
1628         if (image->progress_monitor != (MagickProgressMonitor) NULL)
1629           {
1630             MagickBooleanType
1631               proceed;
1632
1633 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1634             #pragma omp critical (MagickCore_sRGBTransformImage)
1635 #endif
1636             proceed=SetImageProgress(image,sRGBTransformImageTag,progress++,
1637               image->rows);
1638             if (proceed == MagickFalse)
1639               status=MagickFalse;
1640           }
1641       }
1642       image_view=DestroyCacheView(image_view);
1643       break;
1644     }
1645     case PseudoClass:
1646     {
1647       register unsigned int
1648         blue,
1649         green,
1650         red;
1651
1652       /*
1653         Convert PseudoClass image.
1654       */
1655       for (i=0; i < (ssize_t) image->colors; i++)
1656       {
1657         PixelInfo
1658           pixel;
1659
1660         red=ScaleQuantumToMap(ClampToQuantum(DecodesRGBGamma(
1661           image->colormap[i].red)));
1662         green=ScaleQuantumToMap(ClampToQuantum(DecodesRGBGamma(
1663           image->colormap[i].green)));
1664         blue=ScaleQuantumToMap(ClampToQuantum(DecodesRGBGamma(
1665           image->colormap[i].blue)));
1666         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
1667         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
1668         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
1669         image->colormap[i].red=(double) ScaleMapToQuantum(pixel.red);
1670         image->colormap[i].green=(double) ScaleMapToQuantum(pixel.green);
1671         image->colormap[i].blue=(double) ScaleMapToQuantum(pixel.blue);
1672       }
1673       (void) SyncImage(image,exception);
1674       break;
1675     }
1676   }
1677   /*
1678     Relinquish resources.
1679   */
1680   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1681   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1682   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1683   if (SetImageColorspace(image,colorspace,exception) == MagickFalse)
1684     return(MagickFalse);
1685   return(status);
1686 }
1687 \f
1688 /*
1689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1690 %                                                                             %
1691 %                                                                             %
1692 %                                                                             %
1693 %   S e t I m a g e C o l o r s p a c e                                       %
1694 %                                                                             %
1695 %                                                                             %
1696 %                                                                             %
1697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1698 %
1699 %  SetImageColorspace() sets the colorspace member of the Image structure.
1700 %
1701 %  The format of the SetImageColorspace method is:
1702 %
1703 %      MagickBooleanType SetImageColorspace(Image *image,
1704 %        const ColorspaceType colorspace,ExceptiionInfo *exception)
1705 %
1706 %  A description of each parameter follows:
1707 %
1708 %    o image: the image.
1709 %
1710 %    o colorspace: the colorspace.
1711 %
1712 %   o exception: return any errors or warnings in this structure.
1713 %
1714 */
1715 MagickExport MagickBooleanType SetImageColorspace(Image *image,
1716   const ColorspaceType colorspace,ExceptionInfo *exception)
1717 {
1718   if (image->colorspace == colorspace)
1719     return(MagickTrue);
1720   image->colorspace=colorspace;
1721   image->rendering_intent=UndefinedIntent;
1722   image->gamma=1.000f;
1723   (void) ResetMagickMemory(&image->chromaticity,0,sizeof(image->chromaticity));
1724   if (IssRGBColorspace(colorspace) != MagickFalse)
1725     {
1726       image->rendering_intent=PerceptualIntent;
1727       image->gamma=1.000f/2.200f;
1728       image->chromaticity.red_primary.x=0.6400f;
1729       image->chromaticity.red_primary.y=0.3300f;
1730       image->chromaticity.red_primary.z=0.0300f;
1731       image->chromaticity.green_primary.x=0.3000f;
1732       image->chromaticity.green_primary.y=0.6000f;
1733       image->chromaticity.green_primary.z=0.1000f;
1734       image->chromaticity.blue_primary.x=0.1500f;
1735       image->chromaticity.blue_primary.y=0.0600f;
1736       image->chromaticity.blue_primary.z=0.7900f;
1737       image->chromaticity.white_point.x=0.3127f;
1738       image->chromaticity.white_point.y=0.3290f;
1739       image->chromaticity.white_point.z=0.3583f;
1740     }
1741   if (IsGrayColorspace(colorspace) != MagickFalse)
1742     image->type=GrayscaleType;
1743   return(SyncImagePixelCache(image,exception));
1744 }
1745 \f
1746 /*
1747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1748 %                                                                             %
1749 %                                                                             %
1750 %                                                                             %
1751 %   T r a n s f o r m I m a g e C o l o r s p a c e                           %
1752 %                                                                             %
1753 %                                                                             %
1754 %                                                                             %
1755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1756 %
1757 %  TransformImageColorspace() transforms an image colorspace, changing the
1758 %  image data to reflect the new colorspace.
1759 %
1760 %  The format of the TransformImageColorspace method is:
1761 %
1762 %      MagickBooleanType TransformImageColorspace(Image *image,
1763 %        const ColorspaceType colorspace,ExceptionInfo *exception)
1764 %
1765 %  A description of each parameter follows:
1766 %
1767 %    o image: the image.
1768 %
1769 %    o colorspace: the colorspace.
1770 %
1771 %   o exception: return any errors or warnings in this structure.
1772 %
1773 */
1774 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
1775   const ColorspaceType colorspace,ExceptionInfo *exception)
1776 {
1777   MagickBooleanType
1778     status;
1779
1780   assert(image != (Image *) NULL);
1781   assert(image->signature == MagickSignature);
1782   if (image->debug != MagickFalse)
1783     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1784   if (colorspace == UndefinedColorspace)
1785     return(SetImageColorspace(image,colorspace,exception));
1786   if (image->colorspace == colorspace)
1787     return(MagickTrue);  /* same colorspace: no op */
1788   /*
1789     Convert the reference image from an alternate colorspace to sRGB.
1790   */
1791   (void) DeleteImageProfile(image,"icc");
1792   (void) DeleteImageProfile(image,"icm");
1793   if (IssRGBColorspace(colorspace) != MagickFalse)
1794     return(TransformsRGBImage(image,colorspace,exception));
1795   status=MagickTrue;
1796   if (IssRGBColorspace(image->colorspace) == MagickFalse)
1797     status=TransformsRGBImage(image,image->colorspace,exception);
1798   if (status == MagickFalse)
1799     return(status);
1800   /*
1801     Convert the reference image from sRGB to an alternate colorspace.
1802   */
1803   if (sRGBTransformImage(image,colorspace,exception) == MagickFalse)
1804     status=MagickFalse;
1805   return(status);
1806 }
1807 \f
1808 /*
1809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1810 %                                                                             %
1811 %                                                                             %
1812 %                                                                             %
1813 +     T r a n s f o r m s R G B I m a g e                                     %
1814 %                                                                             %
1815 %                                                                             %
1816 %                                                                             %
1817 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1818 %
1819 %  TransformsRGBImage() converts the reference image from an alternate
1820 %  colorspace to sRGB.  The transformation matrices are not the standard ones:
1821 %  the weights are rescaled to normalize the range of the transformed values
1822 %  to be [0..QuantumRange].
1823 %
1824 %  The format of the TransformsRGBImage method is:
1825 %
1826 %      MagickBooleanType TransformsRGBImage(Image *image,
1827 %        const ColorspaceType colorspace,ExceptionInfo *exception)
1828 %
1829 %  A description of each parameter follows:
1830 %
1831 %    o image: the image.
1832 %
1833 %    o colorspace: the colorspace to transform the image to.
1834 %
1835 %   o exception: return any errors or warnings in this structure.
1836 %
1837 */
1838
1839 static inline void ConvertLMSToXYZ(const double L,const double M,const double S,
1840   double *X,double *Y,double *Z)
1841 {
1842   double
1843     l,
1844     m,
1845     s;
1846
1847   assert(X != (double *) NULL);
1848   assert(Y != (double *) NULL);
1849   assert(Z != (double *) NULL);
1850   l=QuantumScale*L;
1851   m=QuantumScale*M;
1852   s=QuantumScale*S;
1853   *X=1.096123820835514*l-0.278869000218287*m+0.182745179382773*s;
1854   *Y=0.454369041975359*l+0.473533154307412*m+0.072097803717229*s;
1855   *Z=(-0.009627608738429)*l-0.005698031216113*m+1.015325639954543*s;
1856 }
1857
1858 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
1859   double *X,double *Y,double *Z)
1860 {
1861   double
1862     x,
1863     y,
1864     z;
1865
1866   assert(X != (double *) NULL);
1867   assert(Y != (double *) NULL);
1868   assert(Z != (double *) NULL);
1869   y=(100.0f*L+16.0f)/116.0f;
1870   x=y+255.0f*(a-0.5f)/500.0f;
1871   z=y-255.0f*(b-0.5f)/200.0f;
1872   if ((x*x*x) > CIEEpsilon)
1873     x=(x*x*x);
1874   else
1875     x=(116.0f*x-16.0f)/CIEK;
1876   if ((y*y*y) > CIEEpsilon)
1877     y=(y*y*y);
1878   else
1879     y=(100.0f*L)/CIEK;
1880   if ((z*z*z) > CIEEpsilon)
1881     z=(z*z*z);
1882   else
1883     z=(116.0f*z-16.0f)/CIEK;
1884   *X=D65X*x;
1885   *Y=D65Y*y;
1886   *Z=D65Z*z;
1887 }
1888
1889 static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
1890   double *X,double *Y,double *Z)
1891 {
1892   assert(X != (double *) NULL);
1893   assert(Y != (double *) NULL);
1894   assert(Z != (double *) NULL);
1895   if ((100.0f*L) > (CIEK*CIEEpsilon))
1896     *Y=(double) pow(((100.0*L)+16.0)/116.0,3.0);
1897   else
1898     *Y=(100.0f*L)/CIEK;
1899   *X=((*Y*((39.0f*(100.0f*L)/((262.0f*v-140.0f)+13.0f*(100.0f*L)*(9.0f*D65Y/
1900     (D65X+15.0f*D65Y+3.0f*D65Z))))-5.0f))+5.0f*(*Y))/((((52.0f*(100.0f*L)/
1901     ((354.0f*u-134.0f)+13.0f*(100.0f*L)*(4.0f*D65X/(D65X+15.0f*D65Y+3.0f*
1902     D65Z))))-1.0f)/3.0f)-(-1.0f/3.0f));
1903   *Z=(*X*(((52.0f*(100.0f*L)/((354.0f*u-134.0f)+13.0f*(100.0f*L)*(4.0f*D65X/
1904     (D65X+15.0f*D65Y+3.0f*D65Z))))-1.0f)/3.0f))-5.0f*(*Y);
1905 }
1906
1907 static inline ssize_t RoundToYCC(const double value)
1908 {
1909   if (value <= 0.0f)
1910     return(0);
1911   if (value >= 1388.0f)
1912     return(1388);
1913   return((ssize_t) (value+0.5f));
1914 }
1915
1916 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
1917   double *red,double *green,double *blue)
1918 {
1919   double
1920     b,
1921     g,
1922     r;
1923
1924   /*
1925     Convert XYZ to sRGB colorspace.
1926   */
1927   assert(red != (double *) NULL);
1928   assert(green != (double *) NULL);
1929   assert(blue != (double *) NULL);
1930   r=3.2406f*x-1.5372f*y-0.4986f*z;
1931   g=(-0.9689f*x+1.8758f*y+0.0415f*z);
1932   b=0.0557f*x-0.2040f*y+1.0570f*z;
1933   *red=QuantumRange*r;
1934   *green=QuantumRange*g;
1935   *blue=QuantumRange*b;
1936 }
1937
1938 static inline void ConvertCMYKToRGB(PixelInfo *pixel)
1939 {
1940   pixel->red=((QuantumRange-(QuantumScale*pixel->red*
1941     (QuantumRange-pixel->black)+pixel->black)));
1942   pixel->green=((QuantumRange-(QuantumScale*pixel->green*
1943     (QuantumRange-pixel->black)+pixel->black)));
1944   pixel->blue=((QuantumRange-(QuantumScale*pixel->blue*
1945     (QuantumRange-pixel->black)+pixel->black)));
1946 }
1947
1948 static MagickBooleanType TransformsRGBImage(Image *image,
1949   const ColorspaceType colorspace,ExceptionInfo *exception)
1950 {
1951 #define TransformsRGBImageTag  "Transform/Image"
1952
1953   static const float
1954     YCCMap[1389] =
1955     {
1956       0.000000f, 0.000720f, 0.001441f, 0.002161f, 0.002882f, 0.003602f,
1957       0.004323f, 0.005043f, 0.005764f, 0.006484f, 0.007205f, 0.007925f,
1958       0.008646f, 0.009366f, 0.010086f, 0.010807f, 0.011527f, 0.012248f,
1959       0.012968f, 0.013689f, 0.014409f, 0.015130f, 0.015850f, 0.016571f,
1960       0.017291f, 0.018012f, 0.018732f, 0.019452f, 0.020173f, 0.020893f,
1961       0.021614f, 0.022334f, 0.023055f, 0.023775f, 0.024496f, 0.025216f,
1962       0.025937f, 0.026657f, 0.027378f, 0.028098f, 0.028818f, 0.029539f,
1963       0.030259f, 0.030980f, 0.031700f, 0.032421f, 0.033141f, 0.033862f,
1964       0.034582f, 0.035303f, 0.036023f, 0.036744f, 0.037464f, 0.038184f,
1965       0.038905f, 0.039625f, 0.040346f, 0.041066f, 0.041787f, 0.042507f,
1966       0.043228f, 0.043948f, 0.044669f, 0.045389f, 0.046110f, 0.046830f,
1967       0.047550f, 0.048271f, 0.048991f, 0.049712f, 0.050432f, 0.051153f,
1968       0.051873f, 0.052594f, 0.053314f, 0.054035f, 0.054755f, 0.055476f,
1969       0.056196f, 0.056916f, 0.057637f, 0.058357f, 0.059078f, 0.059798f,
1970       0.060519f, 0.061239f, 0.061960f, 0.062680f, 0.063401f, 0.064121f,
1971       0.064842f, 0.065562f, 0.066282f, 0.067003f, 0.067723f, 0.068444f,
1972       0.069164f, 0.069885f, 0.070605f, 0.071326f, 0.072046f, 0.072767f,
1973       0.073487f, 0.074207f, 0.074928f, 0.075648f, 0.076369f, 0.077089f,
1974       0.077810f, 0.078530f, 0.079251f, 0.079971f, 0.080692f, 0.081412f,
1975       0.082133f, 0.082853f, 0.083573f, 0.084294f, 0.085014f, 0.085735f,
1976       0.086455f, 0.087176f, 0.087896f, 0.088617f, 0.089337f, 0.090058f,
1977       0.090778f, 0.091499f, 0.092219f, 0.092939f, 0.093660f, 0.094380f,
1978       0.095101f, 0.095821f, 0.096542f, 0.097262f, 0.097983f, 0.098703f,
1979       0.099424f, 0.100144f, 0.100865f, 0.101585f, 0.102305f, 0.103026f,
1980       0.103746f, 0.104467f, 0.105187f, 0.105908f, 0.106628f, 0.107349f,
1981       0.108069f, 0.108790f, 0.109510f, 0.110231f, 0.110951f, 0.111671f,
1982       0.112392f, 0.113112f, 0.113833f, 0.114553f, 0.115274f, 0.115994f,
1983       0.116715f, 0.117435f, 0.118156f, 0.118876f, 0.119597f, 0.120317f,
1984       0.121037f, 0.121758f, 0.122478f, 0.123199f, 0.123919f, 0.124640f,
1985       0.125360f, 0.126081f, 0.126801f, 0.127522f, 0.128242f, 0.128963f,
1986       0.129683f, 0.130403f, 0.131124f, 0.131844f, 0.132565f, 0.133285f,
1987       0.134006f, 0.134726f, 0.135447f, 0.136167f, 0.136888f, 0.137608f,
1988       0.138329f, 0.139049f, 0.139769f, 0.140490f, 0.141210f, 0.141931f,
1989       0.142651f, 0.143372f, 0.144092f, 0.144813f, 0.145533f, 0.146254f,
1990       0.146974f, 0.147695f, 0.148415f, 0.149135f, 0.149856f, 0.150576f,
1991       0.151297f, 0.152017f, 0.152738f, 0.153458f, 0.154179f, 0.154899f,
1992       0.155620f, 0.156340f, 0.157061f, 0.157781f, 0.158501f, 0.159222f,
1993       0.159942f, 0.160663f, 0.161383f, 0.162104f, 0.162824f, 0.163545f,
1994       0.164265f, 0.164986f, 0.165706f, 0.166427f, 0.167147f, 0.167867f,
1995       0.168588f, 0.169308f, 0.170029f, 0.170749f, 0.171470f, 0.172190f,
1996       0.172911f, 0.173631f, 0.174352f, 0.175072f, 0.175793f, 0.176513f,
1997       0.177233f, 0.177954f, 0.178674f, 0.179395f, 0.180115f, 0.180836f,
1998       0.181556f, 0.182277f, 0.182997f, 0.183718f, 0.184438f, 0.185159f,
1999       0.185879f, 0.186599f, 0.187320f, 0.188040f, 0.188761f, 0.189481f,
2000       0.190202f, 0.190922f, 0.191643f, 0.192363f, 0.193084f, 0.193804f,
2001       0.194524f, 0.195245f, 0.195965f, 0.196686f, 0.197406f, 0.198127f,
2002       0.198847f, 0.199568f, 0.200288f, 0.201009f, 0.201729f, 0.202450f,
2003       0.203170f, 0.203890f, 0.204611f, 0.205331f, 0.206052f, 0.206772f,
2004       0.207493f, 0.208213f, 0.208934f, 0.209654f, 0.210375f, 0.211095f,
2005       0.211816f, 0.212536f, 0.213256f, 0.213977f, 0.214697f, 0.215418f,
2006       0.216138f, 0.216859f, 0.217579f, 0.218300f, 0.219020f, 0.219741f,
2007       0.220461f, 0.221182f, 0.221902f, 0.222622f, 0.223343f, 0.224063f,
2008       0.224784f, 0.225504f, 0.226225f, 0.226945f, 0.227666f, 0.228386f,
2009       0.229107f, 0.229827f, 0.230548f, 0.231268f, 0.231988f, 0.232709f,
2010       0.233429f, 0.234150f, 0.234870f, 0.235591f, 0.236311f, 0.237032f,
2011       0.237752f, 0.238473f, 0.239193f, 0.239914f, 0.240634f, 0.241354f,
2012       0.242075f, 0.242795f, 0.243516f, 0.244236f, 0.244957f, 0.245677f,
2013       0.246398f, 0.247118f, 0.247839f, 0.248559f, 0.249280f, 0.250000f,
2014       0.250720f, 0.251441f, 0.252161f, 0.252882f, 0.253602f, 0.254323f,
2015       0.255043f, 0.255764f, 0.256484f, 0.257205f, 0.257925f, 0.258646f,
2016       0.259366f, 0.260086f, 0.260807f, 0.261527f, 0.262248f, 0.262968f,
2017       0.263689f, 0.264409f, 0.265130f, 0.265850f, 0.266571f, 0.267291f,
2018       0.268012f, 0.268732f, 0.269452f, 0.270173f, 0.270893f, 0.271614f,
2019       0.272334f, 0.273055f, 0.273775f, 0.274496f, 0.275216f, 0.275937f,
2020       0.276657f, 0.277378f, 0.278098f, 0.278818f, 0.279539f, 0.280259f,
2021       0.280980f, 0.281700f, 0.282421f, 0.283141f, 0.283862f, 0.284582f,
2022       0.285303f, 0.286023f, 0.286744f, 0.287464f, 0.288184f, 0.288905f,
2023       0.289625f, 0.290346f, 0.291066f, 0.291787f, 0.292507f, 0.293228f,
2024       0.293948f, 0.294669f, 0.295389f, 0.296109f, 0.296830f, 0.297550f,
2025       0.298271f, 0.298991f, 0.299712f, 0.300432f, 0.301153f, 0.301873f,
2026       0.302594f, 0.303314f, 0.304035f, 0.304755f, 0.305476f, 0.306196f,
2027       0.306916f, 0.307637f, 0.308357f, 0.309078f, 0.309798f, 0.310519f,
2028       0.311239f, 0.311960f, 0.312680f, 0.313401f, 0.314121f, 0.314842f,
2029       0.315562f, 0.316282f, 0.317003f, 0.317723f, 0.318444f, 0.319164f,
2030       0.319885f, 0.320605f, 0.321326f, 0.322046f, 0.322767f, 0.323487f,
2031       0.324207f, 0.324928f, 0.325648f, 0.326369f, 0.327089f, 0.327810f,
2032       0.328530f, 0.329251f, 0.329971f, 0.330692f, 0.331412f, 0.332133f,
2033       0.332853f, 0.333573f, 0.334294f, 0.335014f, 0.335735f, 0.336455f,
2034       0.337176f, 0.337896f, 0.338617f, 0.339337f, 0.340058f, 0.340778f,
2035       0.341499f, 0.342219f, 0.342939f, 0.343660f, 0.344380f, 0.345101f,
2036       0.345821f, 0.346542f, 0.347262f, 0.347983f, 0.348703f, 0.349424f,
2037       0.350144f, 0.350865f, 0.351585f, 0.352305f, 0.353026f, 0.353746f,
2038       0.354467f, 0.355187f, 0.355908f, 0.356628f, 0.357349f, 0.358069f,
2039       0.358790f, 0.359510f, 0.360231f, 0.360951f, 0.361671f, 0.362392f,
2040       0.363112f, 0.363833f, 0.364553f, 0.365274f, 0.365994f, 0.366715f,
2041       0.367435f, 0.368156f, 0.368876f, 0.369597f, 0.370317f, 0.371037f,
2042       0.371758f, 0.372478f, 0.373199f, 0.373919f, 0.374640f, 0.375360f,
2043       0.376081f, 0.376801f, 0.377522f, 0.378242f, 0.378963f, 0.379683f,
2044       0.380403f, 0.381124f, 0.381844f, 0.382565f, 0.383285f, 0.384006f,
2045       0.384726f, 0.385447f, 0.386167f, 0.386888f, 0.387608f, 0.388329f,
2046       0.389049f, 0.389769f, 0.390490f, 0.391210f, 0.391931f, 0.392651f,
2047       0.393372f, 0.394092f, 0.394813f, 0.395533f, 0.396254f, 0.396974f,
2048       0.397695f, 0.398415f, 0.399135f, 0.399856f, 0.400576f, 0.401297f,
2049       0.402017f, 0.402738f, 0.403458f, 0.404179f, 0.404899f, 0.405620f,
2050       0.406340f, 0.407061f, 0.407781f, 0.408501f, 0.409222f, 0.409942f,
2051       0.410663f, 0.411383f, 0.412104f, 0.412824f, 0.413545f, 0.414265f,
2052       0.414986f, 0.415706f, 0.416427f, 0.417147f, 0.417867f, 0.418588f,
2053       0.419308f, 0.420029f, 0.420749f, 0.421470f, 0.422190f, 0.422911f,
2054       0.423631f, 0.424352f, 0.425072f, 0.425793f, 0.426513f, 0.427233f,
2055       0.427954f, 0.428674f, 0.429395f, 0.430115f, 0.430836f, 0.431556f,
2056       0.432277f, 0.432997f, 0.433718f, 0.434438f, 0.435158f, 0.435879f,
2057       0.436599f, 0.437320f, 0.438040f, 0.438761f, 0.439481f, 0.440202f,
2058       0.440922f, 0.441643f, 0.442363f, 0.443084f, 0.443804f, 0.444524f,
2059       0.445245f, 0.445965f, 0.446686f, 0.447406f, 0.448127f, 0.448847f,
2060       0.449568f, 0.450288f, 0.451009f, 0.451729f, 0.452450f, 0.453170f,
2061       0.453891f, 0.454611f, 0.455331f, 0.456052f, 0.456772f, 0.457493f,
2062       0.458213f, 0.458934f, 0.459654f, 0.460375f, 0.461095f, 0.461816f,
2063       0.462536f, 0.463256f, 0.463977f, 0.464697f, 0.465418f, 0.466138f,
2064       0.466859f, 0.467579f, 0.468300f, 0.469020f, 0.469741f, 0.470461f,
2065       0.471182f, 0.471902f, 0.472622f, 0.473343f, 0.474063f, 0.474784f,
2066       0.475504f, 0.476225f, 0.476945f, 0.477666f, 0.478386f, 0.479107f,
2067       0.479827f, 0.480548f, 0.481268f, 0.481988f, 0.482709f, 0.483429f,
2068       0.484150f, 0.484870f, 0.485591f, 0.486311f, 0.487032f, 0.487752f,
2069       0.488473f, 0.489193f, 0.489914f, 0.490634f, 0.491354f, 0.492075f,
2070       0.492795f, 0.493516f, 0.494236f, 0.494957f, 0.495677f, 0.496398f,
2071       0.497118f, 0.497839f, 0.498559f, 0.499280f, 0.500000f, 0.500720f,
2072       0.501441f, 0.502161f, 0.502882f, 0.503602f, 0.504323f, 0.505043f,
2073       0.505764f, 0.506484f, 0.507205f, 0.507925f, 0.508646f, 0.509366f,
2074       0.510086f, 0.510807f, 0.511527f, 0.512248f, 0.512968f, 0.513689f,
2075       0.514409f, 0.515130f, 0.515850f, 0.516571f, 0.517291f, 0.518012f,
2076       0.518732f, 0.519452f, 0.520173f, 0.520893f, 0.521614f, 0.522334f,
2077       0.523055f, 0.523775f, 0.524496f, 0.525216f, 0.525937f, 0.526657f,
2078       0.527378f, 0.528098f, 0.528818f, 0.529539f, 0.530259f, 0.530980f,
2079       0.531700f, 0.532421f, 0.533141f, 0.533862f, 0.534582f, 0.535303f,
2080       0.536023f, 0.536744f, 0.537464f, 0.538184f, 0.538905f, 0.539625f,
2081       0.540346f, 0.541066f, 0.541787f, 0.542507f, 0.543228f, 0.543948f,
2082       0.544669f, 0.545389f, 0.546109f, 0.546830f, 0.547550f, 0.548271f,
2083       0.548991f, 0.549712f, 0.550432f, 0.551153f, 0.551873f, 0.552594f,
2084       0.553314f, 0.554035f, 0.554755f, 0.555476f, 0.556196f, 0.556916f,
2085       0.557637f, 0.558357f, 0.559078f, 0.559798f, 0.560519f, 0.561239f,
2086       0.561960f, 0.562680f, 0.563401f, 0.564121f, 0.564842f, 0.565562f,
2087       0.566282f, 0.567003f, 0.567723f, 0.568444f, 0.569164f, 0.569885f,
2088       0.570605f, 0.571326f, 0.572046f, 0.572767f, 0.573487f, 0.574207f,
2089       0.574928f, 0.575648f, 0.576369f, 0.577089f, 0.577810f, 0.578530f,
2090       0.579251f, 0.579971f, 0.580692f, 0.581412f, 0.582133f, 0.582853f,
2091       0.583573f, 0.584294f, 0.585014f, 0.585735f, 0.586455f, 0.587176f,
2092       0.587896f, 0.588617f, 0.589337f, 0.590058f, 0.590778f, 0.591499f,
2093       0.592219f, 0.592939f, 0.593660f, 0.594380f, 0.595101f, 0.595821f,
2094       0.596542f, 0.597262f, 0.597983f, 0.598703f, 0.599424f, 0.600144f,
2095       0.600865f, 0.601585f, 0.602305f, 0.603026f, 0.603746f, 0.604467f,
2096       0.605187f, 0.605908f, 0.606628f, 0.607349f, 0.608069f, 0.608790f,
2097       0.609510f, 0.610231f, 0.610951f, 0.611671f, 0.612392f, 0.613112f,
2098       0.613833f, 0.614553f, 0.615274f, 0.615994f, 0.616715f, 0.617435f,
2099       0.618156f, 0.618876f, 0.619597f, 0.620317f, 0.621037f, 0.621758f,
2100       0.622478f, 0.623199f, 0.623919f, 0.624640f, 0.625360f, 0.626081f,
2101       0.626801f, 0.627522f, 0.628242f, 0.628963f, 0.629683f, 0.630403f,
2102       0.631124f, 0.631844f, 0.632565f, 0.633285f, 0.634006f, 0.634726f,
2103       0.635447f, 0.636167f, 0.636888f, 0.637608f, 0.638329f, 0.639049f,
2104       0.639769f, 0.640490f, 0.641210f, 0.641931f, 0.642651f, 0.643372f,
2105       0.644092f, 0.644813f, 0.645533f, 0.646254f, 0.646974f, 0.647695f,
2106       0.648415f, 0.649135f, 0.649856f, 0.650576f, 0.651297f, 0.652017f,
2107       0.652738f, 0.653458f, 0.654179f, 0.654899f, 0.655620f, 0.656340f,
2108       0.657061f, 0.657781f, 0.658501f, 0.659222f, 0.659942f, 0.660663f,
2109       0.661383f, 0.662104f, 0.662824f, 0.663545f, 0.664265f, 0.664986f,
2110       0.665706f, 0.666427f, 0.667147f, 0.667867f, 0.668588f, 0.669308f,
2111       0.670029f, 0.670749f, 0.671470f, 0.672190f, 0.672911f, 0.673631f,
2112       0.674352f, 0.675072f, 0.675793f, 0.676513f, 0.677233f, 0.677954f,
2113       0.678674f, 0.679395f, 0.680115f, 0.680836f, 0.681556f, 0.682277f,
2114       0.682997f, 0.683718f, 0.684438f, 0.685158f, 0.685879f, 0.686599f,
2115       0.687320f, 0.688040f, 0.688761f, 0.689481f, 0.690202f, 0.690922f,
2116       0.691643f, 0.692363f, 0.693084f, 0.693804f, 0.694524f, 0.695245f,
2117       0.695965f, 0.696686f, 0.697406f, 0.698127f, 0.698847f, 0.699568f,
2118       0.700288f, 0.701009f, 0.701729f, 0.702450f, 0.703170f, 0.703891f,
2119       0.704611f, 0.705331f, 0.706052f, 0.706772f, 0.707493f, 0.708213f,
2120       0.708934f, 0.709654f, 0.710375f, 0.711095f, 0.711816f, 0.712536f,
2121       0.713256f, 0.713977f, 0.714697f, 0.715418f, 0.716138f, 0.716859f,
2122       0.717579f, 0.718300f, 0.719020f, 0.719741f, 0.720461f, 0.721182f,
2123       0.721902f, 0.722622f, 0.723343f, 0.724063f, 0.724784f, 0.725504f,
2124       0.726225f, 0.726945f, 0.727666f, 0.728386f, 0.729107f, 0.729827f,
2125       0.730548f, 0.731268f, 0.731988f, 0.732709f, 0.733429f, 0.734150f,
2126       0.734870f, 0.735591f, 0.736311f, 0.737032f, 0.737752f, 0.738473f,
2127       0.739193f, 0.739914f, 0.740634f, 0.741354f, 0.742075f, 0.742795f,
2128       0.743516f, 0.744236f, 0.744957f, 0.745677f, 0.746398f, 0.747118f,
2129       0.747839f, 0.748559f, 0.749280f, 0.750000f, 0.750720f, 0.751441f,
2130       0.752161f, 0.752882f, 0.753602f, 0.754323f, 0.755043f, 0.755764f,
2131       0.756484f, 0.757205f, 0.757925f, 0.758646f, 0.759366f, 0.760086f,
2132       0.760807f, 0.761527f, 0.762248f, 0.762968f, 0.763689f, 0.764409f,
2133       0.765130f, 0.765850f, 0.766571f, 0.767291f, 0.768012f, 0.768732f,
2134       0.769452f, 0.770173f, 0.770893f, 0.771614f, 0.772334f, 0.773055f,
2135       0.773775f, 0.774496f, 0.775216f, 0.775937f, 0.776657f, 0.777378f,
2136       0.778098f, 0.778818f, 0.779539f, 0.780259f, 0.780980f, 0.781700f,
2137       0.782421f, 0.783141f, 0.783862f, 0.784582f, 0.785303f, 0.786023f,
2138       0.786744f, 0.787464f, 0.788184f, 0.788905f, 0.789625f, 0.790346f,
2139       0.791066f, 0.791787f, 0.792507f, 0.793228f, 0.793948f, 0.794669f,
2140       0.795389f, 0.796109f, 0.796830f, 0.797550f, 0.798271f, 0.798991f,
2141       0.799712f, 0.800432f, 0.801153f, 0.801873f, 0.802594f, 0.803314f,
2142       0.804035f, 0.804755f, 0.805476f, 0.806196f, 0.806916f, 0.807637f,
2143       0.808357f, 0.809078f, 0.809798f, 0.810519f, 0.811239f, 0.811960f,
2144       0.812680f, 0.813401f, 0.814121f, 0.814842f, 0.815562f, 0.816282f,
2145       0.817003f, 0.817723f, 0.818444f, 0.819164f, 0.819885f, 0.820605f,
2146       0.821326f, 0.822046f, 0.822767f, 0.823487f, 0.824207f, 0.824928f,
2147       0.825648f, 0.826369f, 0.827089f, 0.827810f, 0.828530f, 0.829251f,
2148       0.829971f, 0.830692f, 0.831412f, 0.832133f, 0.832853f, 0.833573f,
2149       0.834294f, 0.835014f, 0.835735f, 0.836455f, 0.837176f, 0.837896f,
2150       0.838617f, 0.839337f, 0.840058f, 0.840778f, 0.841499f, 0.842219f,
2151       0.842939f, 0.843660f, 0.844380f, 0.845101f, 0.845821f, 0.846542f,
2152       0.847262f, 0.847983f, 0.848703f, 0.849424f, 0.850144f, 0.850865f,
2153       0.851585f, 0.852305f, 0.853026f, 0.853746f, 0.854467f, 0.855187f,
2154       0.855908f, 0.856628f, 0.857349f, 0.858069f, 0.858790f, 0.859510f,
2155       0.860231f, 0.860951f, 0.861671f, 0.862392f, 0.863112f, 0.863833f,
2156       0.864553f, 0.865274f, 0.865994f, 0.866715f, 0.867435f, 0.868156f,
2157       0.868876f, 0.869597f, 0.870317f, 0.871037f, 0.871758f, 0.872478f,
2158       0.873199f, 0.873919f, 0.874640f, 0.875360f, 0.876081f, 0.876801f,
2159       0.877522f, 0.878242f, 0.878963f, 0.879683f, 0.880403f, 0.881124f,
2160       0.881844f, 0.882565f, 0.883285f, 0.884006f, 0.884726f, 0.885447f,
2161       0.886167f, 0.886888f, 0.887608f, 0.888329f, 0.889049f, 0.889769f,
2162       0.890490f, 0.891210f, 0.891931f, 0.892651f, 0.893372f, 0.894092f,
2163       0.894813f, 0.895533f, 0.896254f, 0.896974f, 0.897695f, 0.898415f,
2164       0.899135f, 0.899856f, 0.900576f, 0.901297f, 0.902017f, 0.902738f,
2165       0.903458f, 0.904179f, 0.904899f, 0.905620f, 0.906340f, 0.907061f,
2166       0.907781f, 0.908501f, 0.909222f, 0.909942f, 0.910663f, 0.911383f,
2167       0.912104f, 0.912824f, 0.913545f, 0.914265f, 0.914986f, 0.915706f,
2168       0.916427f, 0.917147f, 0.917867f, 0.918588f, 0.919308f, 0.920029f,
2169       0.920749f, 0.921470f, 0.922190f, 0.922911f, 0.923631f, 0.924352f,
2170       0.925072f, 0.925793f, 0.926513f, 0.927233f, 0.927954f, 0.928674f,
2171       0.929395f, 0.930115f, 0.930836f, 0.931556f, 0.932277f, 0.932997f,
2172       0.933718f, 0.934438f, 0.935158f, 0.935879f, 0.936599f, 0.937320f,
2173       0.938040f, 0.938761f, 0.939481f, 0.940202f, 0.940922f, 0.941643f,
2174       0.942363f, 0.943084f, 0.943804f, 0.944524f, 0.945245f, 0.945965f,
2175       0.946686f, 0.947406f, 0.948127f, 0.948847f, 0.949568f, 0.950288f,
2176       0.951009f, 0.951729f, 0.952450f, 0.953170f, 0.953891f, 0.954611f,
2177       0.955331f, 0.956052f, 0.956772f, 0.957493f, 0.958213f, 0.958934f,
2178       0.959654f, 0.960375f, 0.961095f, 0.961816f, 0.962536f, 0.963256f,
2179       0.963977f, 0.964697f, 0.965418f, 0.966138f, 0.966859f, 0.967579f,
2180       0.968300f, 0.969020f, 0.969741f, 0.970461f, 0.971182f, 0.971902f,
2181       0.972622f, 0.973343f, 0.974063f, 0.974784f, 0.975504f, 0.976225f,
2182       0.976945f, 0.977666f, 0.978386f, 0.979107f, 0.979827f, 0.980548f,
2183       0.981268f, 0.981988f, 0.982709f, 0.983429f, 0.984150f, 0.984870f,
2184       0.985591f, 0.986311f, 0.987032f, 0.987752f, 0.988473f, 0.989193f,
2185       0.989914f, 0.990634f, 0.991354f, 0.992075f, 0.992795f, 0.993516f,
2186       0.994236f, 0.994957f, 0.995677f, 0.996398f, 0.997118f, 0.997839f,
2187       0.998559f, 0.999280f, 1.000000f
2188     };
2189
2190   CacheView
2191     *image_view;
2192
2193   MagickBooleanType
2194     status;
2195
2196   MagickOffsetType
2197     progress;
2198
2199   register ssize_t
2200     i;
2201
2202   ssize_t
2203     y;
2204
2205   TransformPacket
2206     *y_map,
2207     *x_map,
2208     *z_map;
2209
2210   assert(image != (Image *) NULL);
2211   assert(image->signature == MagickSignature);
2212   if (image->debug != MagickFalse)
2213     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2214   status=MagickTrue;
2215   progress=0;
2216   switch (image->colorspace)
2217   {
2218     case CMYColorspace:
2219     {
2220       /*
2221         Transform image from CMY to sRGB.
2222       */
2223       if (image->storage_class == PseudoClass)
2224         {
2225           if (SyncImage(image,exception) == MagickFalse)
2226             return(MagickFalse);
2227           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2228             return(MagickFalse);
2229         }
2230       image_view=AcquireAuthenticCacheView(image,exception);
2231 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2232       #pragma omp parallel for schedule(static,4) shared(status) \
2233         dynamic_number_threads(image,image->columns,image->rows,1)
2234 #endif
2235       for (y=0; y < (ssize_t) image->rows; y++)
2236       {
2237         MagickBooleanType
2238           sync;
2239
2240         register ssize_t
2241           x;
2242
2243         register Quantum
2244           *restrict q;
2245
2246         if (status == MagickFalse)
2247           continue;
2248         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2249           exception);
2250         if (q == (Quantum *) NULL)
2251           {
2252             status=MagickFalse;
2253             continue;
2254           }
2255         for (x=0; x < (ssize_t) image->columns; x++)
2256         {
2257           double
2258             cyan,
2259             magenta,
2260             yellow;
2261
2262           cyan=EncodesRGBGamma((MagickRealType) (QuantumRange-
2263             GetPixelCyan(image,q)));
2264           magenta=EncodesRGBGamma((MagickRealType) (QuantumRange-
2265             GetPixelMagenta(image,q)));
2266           yellow=EncodesRGBGamma((MagickRealType) (QuantumRange-
2267             GetPixelYellow(image,q)));
2268           SetPixelCyan(image,ClampToQuantum(cyan),q);
2269           SetPixelMagenta(image,ClampToQuantum(magenta),q);
2270           SetPixelYellow(image,ClampToQuantum(yellow),q);
2271           q+=GetPixelChannels(image);
2272         }
2273         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2274         if (sync == MagickFalse)
2275           status=MagickFalse;
2276       }
2277       image_view=DestroyCacheView(image_view);
2278       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2279         return(MagickFalse);
2280       return(status);
2281     }
2282     case CMYKColorspace:
2283     {
2284       PixelInfo
2285         zero;
2286
2287       /*
2288         Transform image from CMYK to sRGB.
2289       */
2290       if (image->storage_class == PseudoClass)
2291         {
2292           if (SyncImage(image,exception) == MagickFalse)
2293             return(MagickFalse);
2294           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2295             return(MagickFalse);
2296         }
2297       GetPixelInfo(image,&zero);
2298       image_view=AcquireAuthenticCacheView(image,exception);
2299 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2300       #pragma omp parallel for schedule(static,4) shared(status) \
2301         dynamic_number_threads(image,image->columns,image->rows,1)
2302 #endif
2303       for (y=0; y < (ssize_t) image->rows; y++)
2304       {
2305         MagickBooleanType
2306           sync;
2307
2308         PixelInfo
2309           pixel;
2310
2311         register ssize_t
2312           x;
2313
2314         register Quantum
2315           *restrict q;
2316
2317         if (status == MagickFalse)
2318           continue;
2319         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2320           exception);
2321         if (q == (Quantum *) NULL)
2322           {
2323             status=MagickFalse;
2324             continue;
2325           }
2326         pixel=zero;
2327         for (x=0; x < (ssize_t) image->columns; x++)
2328         {
2329           GetPixelInfoPixel(image,q,&pixel);
2330           ConvertCMYKToRGB(&pixel);
2331           pixel.red=EncodesRGBGamma(pixel.red);
2332           pixel.green=EncodesRGBGamma(pixel.green);
2333           pixel.blue=EncodesRGBGamma(pixel.blue);
2334           SetPixelInfoPixel(image,&pixel,q);
2335           q+=GetPixelChannels(image);
2336         }
2337         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2338         if (sync == MagickFalse)
2339           status=MagickFalse;
2340       }
2341       image_view=DestroyCacheView(image_view);
2342       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2343         return(MagickFalse);
2344       return(status);
2345     }
2346     case GRAYColorspace:
2347     case Rec601LumaColorspace:
2348     case Rec709LumaColorspace:
2349     {
2350       /*
2351         Transform linear GRAY to sRGB colorspace.
2352       */
2353       if (image->storage_class == PseudoClass)
2354         {
2355           if (SyncImage(image,exception) == MagickFalse)
2356             return(MagickFalse);
2357           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2358             return(MagickFalse);
2359         }
2360       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2361         return(MagickFalse);
2362       image_view=AcquireAuthenticCacheView(image,exception);
2363 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2364       #pragma omp parallel for schedule(static,4) shared(status) \
2365         dynamic_number_threads(image,image->columns,image->rows,1)
2366 #endif
2367       for (y=0; y < (ssize_t) image->rows; y++)
2368       {
2369         MagickBooleanType
2370           sync;
2371
2372         register ssize_t
2373           x;
2374
2375         register Quantum
2376           *restrict q;
2377
2378         if (status == MagickFalse)
2379           continue;
2380         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2381           exception);
2382         if (q == (Quantum *) NULL)
2383           {
2384             status=MagickFalse;
2385             continue;
2386           }
2387         for (x=(ssize_t) image->columns; x != 0; x--)
2388         {
2389           double
2390             gray;
2391
2392           gray=EncodesRGBGamma((MagickRealType) GetPixelGray(image,q));
2393           SetPixelRed(image,ClampToQuantum(gray),q);
2394           SetPixelGreen(image,ClampToQuantum(gray),q);
2395           SetPixelBlue(image,ClampToQuantum(gray),q);
2396           q+=GetPixelChannels(image);
2397         }
2398         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2399         if (sync == MagickFalse)
2400           status=MagickFalse;
2401       }
2402       image_view=DestroyCacheView(image_view);
2403       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2404         return(MagickFalse);
2405       return(status);
2406     }
2407     case HCLColorspace:
2408     {
2409       /*
2410         Transform image from HCL to sRGB.
2411       */
2412       if (image->storage_class == PseudoClass)
2413         {
2414           if (SyncImage(image,exception) == MagickFalse)
2415             return(MagickFalse);
2416           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2417             return(MagickFalse);
2418         }
2419       image_view=AcquireAuthenticCacheView(image,exception);
2420 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2421       #pragma omp parallel for schedule(static,4) shared(status) \
2422         dynamic_number_threads(image,image->columns,image->rows,1)
2423 #endif
2424       for (y=0; y < (ssize_t) image->rows; y++)
2425       {
2426         MagickBooleanType
2427           sync;
2428
2429         register ssize_t
2430           x;
2431
2432         register Quantum
2433           *restrict q;
2434
2435         if (status == MagickFalse)
2436           continue;
2437         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2438           exception);
2439         if (q == (Quantum *) NULL)
2440           {
2441             status=MagickFalse;
2442             continue;
2443           }
2444         for (x=0; x < (ssize_t) image->columns; x++)
2445         {
2446           double
2447             blue,
2448             chroma,
2449             green,
2450             hue,
2451             luma,
2452             red;
2453
2454           hue=(double) (QuantumScale*GetPixelRed(image,q));
2455           chroma=(double) (QuantumScale*GetPixelGreen(image,q));
2456           luma=(double) (QuantumScale*GetPixelBlue(image,q));
2457           ConvertHCLToRGB(hue,chroma,luma,&red,&green,&blue);
2458           SetPixelRed(image,ClampToQuantum(EncodesRGBGamma(red)),q);
2459           SetPixelGreen(image,ClampToQuantum(EncodesRGBGamma(green)),q);
2460           SetPixelBlue(image,ClampToQuantum(EncodesRGBGamma(blue)),q);
2461           q+=GetPixelChannels(image);
2462         }
2463         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2464         if (sync == MagickFalse)
2465           status=MagickFalse;
2466       }
2467       image_view=DestroyCacheView(image_view);
2468       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2469         return(MagickFalse);
2470       return(status);
2471     }
2472     case HSBColorspace:
2473     {
2474       /*
2475         Transform image from HSB to sRGB.
2476       */
2477       if (image->storage_class == PseudoClass)
2478         {
2479           if (SyncImage(image,exception) == MagickFalse)
2480             return(MagickFalse);
2481           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2482             return(MagickFalse);
2483         }
2484       image_view=AcquireAuthenticCacheView(image,exception);
2485 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2486       #pragma omp parallel for schedule(static,4) shared(status) \
2487         dynamic_number_threads(image,image->columns,image->rows,1)
2488 #endif
2489       for (y=0; y < (ssize_t) image->rows; y++)
2490       {
2491         MagickBooleanType
2492           sync;
2493
2494         register ssize_t
2495           x;
2496
2497         register Quantum
2498           *restrict q;
2499
2500         if (status == MagickFalse)
2501           continue;
2502         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2503           exception);
2504         if (q == (Quantum *) NULL)
2505           {
2506             status=MagickFalse;
2507             continue;
2508           }
2509         for (x=0; x < (ssize_t) image->columns; x++)
2510         {
2511           double
2512             blue,
2513             brightness,
2514             green,
2515             hue,
2516             red,
2517             saturation;
2518
2519           hue=(double) (QuantumScale*GetPixelRed(image,q));
2520           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
2521           brightness=(double) (QuantumScale*GetPixelBlue(image,q));
2522           ConvertHSBToRGB(hue,saturation,brightness,&red,&green,&blue);
2523           SetPixelRed(image,ClampToQuantum(EncodesRGBGamma(red)),q);
2524           SetPixelGreen(image,ClampToQuantum(EncodesRGBGamma(green)),q);
2525           SetPixelBlue(image,ClampToQuantum(EncodesRGBGamma(blue)),q);
2526           q+=GetPixelChannels(image);
2527         }
2528         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2529         if (sync == MagickFalse)
2530           status=MagickFalse;
2531       }
2532       image_view=DestroyCacheView(image_view);
2533       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2534         return(MagickFalse);
2535       return(status);
2536     }
2537     case HSLColorspace:
2538     {
2539       /*
2540         Transform image from HSL to sRGB.
2541       */
2542       if (image->storage_class == PseudoClass)
2543         {
2544           if (SyncImage(image,exception) == MagickFalse)
2545             return(MagickFalse);
2546           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2547             return(MagickFalse);
2548         }
2549       image_view=AcquireAuthenticCacheView(image,exception);
2550 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2551       #pragma omp parallel for schedule(static,4) shared(status) \
2552         dynamic_number_threads(image,image->columns,image->rows,1)
2553 #endif
2554       for (y=0; y < (ssize_t) image->rows; y++)
2555       {
2556         MagickBooleanType
2557           sync;
2558
2559         register ssize_t
2560           x;
2561
2562         register Quantum
2563           *restrict q;
2564
2565         if (status == MagickFalse)
2566           continue;
2567         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2568           exception);
2569         if (q == (Quantum *) NULL)
2570           {
2571             status=MagickFalse;
2572             continue;
2573           }
2574         for (x=0; x < (ssize_t) image->columns; x++)
2575         {
2576           double
2577             blue,
2578             green,
2579             hue,
2580             lightness,
2581             red,
2582             saturation;
2583
2584           hue=(double) (QuantumScale*GetPixelRed(image,q));
2585           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
2586           lightness=(double) (QuantumScale*GetPixelBlue(image,q));
2587           ConvertHSLToRGB(hue,saturation,lightness,&red,&green,&blue);
2588           SetPixelRed(image,ClampToQuantum(EncodesRGBGamma(red)),q);
2589           SetPixelGreen(image,ClampToQuantum(EncodesRGBGamma(green)),q);
2590           SetPixelBlue(image,ClampToQuantum(EncodesRGBGamma(blue)),q);
2591           q+=GetPixelChannels(image);
2592         }
2593         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2594         if (sync == MagickFalse)
2595           status=MagickFalse;
2596       }
2597       image_view=DestroyCacheView(image_view);
2598       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2599         return(MagickFalse);
2600       return(status);
2601     }
2602     case HWBColorspace:
2603     {
2604       /*
2605         Transform image from HWB to sRGB.
2606       */
2607       if (image->storage_class == PseudoClass)
2608         {
2609           if (SyncImage(image,exception) == MagickFalse)
2610             return(MagickFalse);
2611           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2612             return(MagickFalse);
2613         }
2614       image_view=AcquireAuthenticCacheView(image,exception);
2615 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2616       #pragma omp parallel for schedule(static,4) shared(status) \
2617         dynamic_number_threads(image,image->columns,image->rows,1)
2618 #endif
2619       for (y=0; y < (ssize_t) image->rows; y++)
2620       {
2621         MagickBooleanType
2622           sync;
2623
2624         register ssize_t
2625           x;
2626
2627         register Quantum
2628           *restrict q;
2629
2630         if (status == MagickFalse)
2631           continue;
2632         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2633           exception);
2634         if (q == (Quantum *) NULL)
2635           {
2636             status=MagickFalse;
2637             continue;
2638           }
2639         for (x=0; x < (ssize_t) image->columns; x++)
2640         {
2641           double
2642             blackness,
2643             blue,
2644             green,
2645             hue,
2646             red,
2647             whiteness;
2648
2649           hue=(double) (QuantumScale*GetPixelRed(image,q));
2650           whiteness=(double) (QuantumScale*GetPixelGreen(image,q));
2651           blackness=(double) (QuantumScale*GetPixelBlue(image,q));
2652           ConvertHWBToRGB(hue,whiteness,blackness,&red,&green,&blue);
2653           SetPixelRed(image,ClampToQuantum(EncodesRGBGamma(red)),q);
2654           SetPixelGreen(image,ClampToQuantum(EncodesRGBGamma(green)),q);
2655           SetPixelBlue(image,ClampToQuantum(EncodesRGBGamma(blue)),q);
2656           q+=GetPixelChannels(image);
2657         }
2658         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2659         if (sync == MagickFalse)
2660           status=MagickFalse;
2661       }
2662       image_view=DestroyCacheView(image_view);
2663       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2664         return(MagickFalse);
2665       return(status);
2666     }
2667     case LabColorspace:
2668     {
2669       /*
2670         Transform image from Lab to sRGB.
2671       */
2672       if (image->storage_class == PseudoClass)
2673         {
2674           if (SyncImage(image,exception) == MagickFalse)
2675             return(MagickFalse);
2676           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2677             return(MagickFalse);
2678         }
2679       image_view=AcquireAuthenticCacheView(image,exception);
2680 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2681       #pragma omp parallel for schedule(static,4) shared(status) \
2682         dynamic_number_threads(image,image->columns,image->rows,1)
2683 #endif
2684       for (y=0; y < (ssize_t) image->rows; y++)
2685       {
2686         MagickBooleanType
2687           sync;
2688
2689         register ssize_t
2690           x;
2691
2692         register Quantum
2693           *restrict q;
2694
2695         if (status == MagickFalse)
2696           continue;
2697         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2698           exception);
2699         if (q == (Quantum *) NULL)
2700           {
2701             status=MagickFalse;
2702             continue;
2703           }
2704         for (x=0; x < (ssize_t) image->columns; x++)
2705         {
2706           double
2707             a,
2708             b,
2709             blue,
2710             green,
2711             L,
2712             red,
2713             X,
2714             Y,
2715             Z;
2716
2717           L=QuantumScale*GetPixelRed(image,q);
2718           a=QuantumScale*GetPixelGreen(image,q);
2719           b=QuantumScale*GetPixelBlue(image,q);
2720           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
2721           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2722           SetPixelRed(image,ClampToQuantum(EncodesRGBGamma(red)),q);
2723           SetPixelGreen(image,ClampToQuantum(EncodesRGBGamma(green)),q);
2724           SetPixelBlue(image,ClampToQuantum(EncodesRGBGamma(blue)),q);
2725           q+=GetPixelChannels(image);
2726         }
2727         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2728         if (sync == MagickFalse)
2729           status=MagickFalse;
2730       }
2731       image_view=DestroyCacheView(image_view);
2732       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2733         return(MagickFalse);
2734       return(status);
2735     }
2736     case LCHColorspace:
2737     {
2738       /*
2739         Transform image from LCH to sRGB.
2740       */
2741       if (image->storage_class == PseudoClass)
2742         {
2743           if (SyncImage(image,exception) == MagickFalse)
2744             return(MagickFalse);
2745           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2746             return(MagickFalse);
2747         }
2748       image_view=AcquireAuthenticCacheView(image,exception);
2749 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2750       #pragma omp parallel for schedule(static,4) shared(status) \
2751         dynamic_number_threads(image,image->columns,image->rows,1)
2752 #endif
2753       for (y=0; y < (ssize_t) image->rows; y++)
2754       {
2755         MagickBooleanType
2756           sync;
2757
2758         register ssize_t
2759           x;
2760
2761         register Quantum
2762           *restrict q;
2763
2764         if (status == MagickFalse)
2765           continue;
2766         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2767           exception);
2768         if (q == (Quantum *) NULL)
2769           {
2770             status=MagickFalse;
2771             continue;
2772           }
2773         for (x=0; x < (ssize_t) image->columns; x++)
2774         {
2775           double
2776             a,
2777             b,
2778             blue,
2779             C,
2780             green,
2781             H,
2782             L,
2783             red,
2784             X,
2785             Y,
2786             Z;
2787
2788           L=QuantumScale*GetPixelRed(image,q);
2789           C=QuantumScale*GetPixelGreen(image,q);
2790           H=QuantumScale*GetPixelBlue(image,q);
2791           a=C*cos(H*(MagickPI/180.0f));
2792           b=C*sin(H*(MagickPI/180.0f));
2793           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
2794           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2795           SetPixelRed(image,ClampToQuantum(EncodesRGBGamma(red)),q);
2796           SetPixelGreen(image,ClampToQuantum(EncodesRGBGamma(green)),q);
2797           SetPixelBlue(image,ClampToQuantum(EncodesRGBGamma(blue)),q);
2798           q+=GetPixelChannels(image);
2799         }
2800         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2801         if (sync == MagickFalse)
2802           status=MagickFalse;
2803       }
2804       image_view=DestroyCacheView(image_view);
2805       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2806         return(MagickFalse);
2807       return(status);
2808     }
2809     case LMSColorspace:
2810     {
2811       /*
2812         Transform image from LMS to sRGB.
2813       */
2814       if (image->storage_class == PseudoClass)
2815         {
2816           if (SyncImage(image,exception) == MagickFalse)
2817             return(MagickFalse);
2818           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2819             return(MagickFalse);
2820         }
2821       image_view=AcquireAuthenticCacheView(image,exception);
2822 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2823       #pragma omp parallel for schedule(static,4) shared(status) \
2824         dynamic_number_threads(image,image->columns,image->rows,1)
2825 #endif
2826       for (y=0; y < (ssize_t) image->rows; y++)
2827       {
2828         MagickBooleanType
2829           sync;
2830
2831         register ssize_t
2832           x;
2833
2834         register Quantum
2835           *restrict q;
2836
2837         if (status == MagickFalse)
2838           continue;
2839         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2840           exception);
2841         if (q == (Quantum *) NULL)
2842           {
2843             status=MagickFalse;
2844             continue;
2845           }
2846         for (x=0; x < (ssize_t) image->columns; x++)
2847         {
2848           double
2849             blue,
2850             green,
2851             L,
2852             M,
2853             red,
2854             S,
2855             X,
2856             Y,
2857             Z;
2858
2859           L=QuantumScale*GetPixelRed(image,q);
2860           M=QuantumScale*GetPixelGreen(image,q);
2861           S=QuantumScale*GetPixelBlue(image,q);
2862           ConvertLMSToXYZ(L,M,S,&X,&Y,&Z);
2863           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2864           SetPixelRed(image,ClampToQuantum(EncodesRGBGamma(red)),q);
2865           SetPixelGreen(image,ClampToQuantum(EncodesRGBGamma(green)),q);
2866           SetPixelBlue(image,ClampToQuantum(EncodesRGBGamma(blue)),q);
2867           q+=GetPixelChannels(image);
2868         }
2869         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2870         if (sync == MagickFalse)
2871           status=MagickFalse;
2872       }
2873       image_view=DestroyCacheView(image_view);
2874       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2875         return(MagickFalse);
2876       return(status);
2877     }
2878     case LogColorspace:
2879     {
2880       const char
2881         *value;
2882
2883       double
2884         black,
2885         density,
2886         film_gamma,
2887         gamma,
2888         reference_black,
2889         reference_white;
2890
2891       Quantum
2892         *logmap;
2893
2894       /*
2895         Transform Log to sRGB colorspace.
2896       */
2897       density=DisplayGamma;
2898       gamma=DisplayGamma;
2899       value=GetImageProperty(image,"gamma",exception);
2900       if (value != (const char *) NULL)
2901         gamma=PerceptibleReciprocal(StringToDouble(value,(char **) NULL));
2902       film_gamma=FilmGamma;
2903       value=GetImageProperty(image,"film-gamma",exception);
2904       if (value != (const char *) NULL)
2905         film_gamma=StringToDouble(value,(char **) NULL);
2906       reference_black=ReferenceBlack;
2907       value=GetImageProperty(image,"reference-black",exception);
2908       if (value != (const char *) NULL)
2909         reference_black=StringToDouble(value,(char **) NULL);
2910       reference_white=ReferenceWhite;
2911       value=GetImageProperty(image,"reference-white",exception);
2912       if (value != (const char *) NULL)
2913         reference_white=StringToDouble(value,(char **) NULL);
2914       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2915         sizeof(*logmap));
2916       if (logmap == (Quantum *) NULL)
2917         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2918           image->filename);
2919       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*0.002f/
2920         film_gamma);
2921       for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0f); i++)
2922         logmap[i]=(Quantum) 0;
2923       for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0f); i++)
2924         logmap[i]=ClampToQuantum(QuantumRange/(1.0f-black)*
2925           (pow(10.0,(1024.0*i/MaxMap-reference_white)*(gamma/density)*0.002f/
2926           film_gamma)-black));
2927       for ( ; i <= (ssize_t) MaxMap; i++)
2928         logmap[i]=QuantumRange;
2929       if (image->storage_class == PseudoClass)
2930         {
2931           if (SyncImage(image,exception) == MagickFalse)
2932             return(MagickFalse);
2933           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2934             return(MagickFalse);
2935         }
2936       image_view=AcquireAuthenticCacheView(image,exception);
2937 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2938       #pragma omp parallel for schedule(static,4) shared(status) \
2939         dynamic_number_threads(image,image->columns,image->rows,1)
2940 #endif
2941       for (y=0; y < (ssize_t) image->rows; y++)
2942       {
2943         MagickBooleanType
2944           sync;
2945
2946         register ssize_t
2947           x;
2948
2949         register Quantum
2950           *restrict q;
2951
2952         if (status == MagickFalse)
2953           continue;
2954         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2955           exception);
2956         if (q == (Quantum *) NULL)
2957           {
2958             status=MagickFalse;
2959             continue;
2960           }
2961         for (x=(ssize_t) image->columns; x != 0; x--)
2962         {
2963           double
2964             blue,
2965             green,
2966             red;
2967
2968           red=EncodesRGBGamma((MagickRealType) logmap[ScaleQuantumToMap(
2969             GetPixelRed(image,q))]);
2970           green=EncodesRGBGamma((MagickRealType) logmap[ScaleQuantumToMap(
2971             GetPixelGreen(image,q))]);
2972           blue=EncodesRGBGamma((MagickRealType) logmap[ScaleQuantumToMap(
2973             GetPixelBlue(image,q))]);
2974           SetPixelRed(image,ClampToQuantum(red),q);
2975           SetPixelGreen(image,ClampToQuantum(green),q);
2976           SetPixelBlue(image,ClampToQuantum(blue),q);
2977           q+=GetPixelChannels(image);
2978         }
2979         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2980         if (sync == MagickFalse)
2981           status=MagickFalse;
2982       }
2983       image_view=DestroyCacheView(image_view);
2984       logmap=(Quantum *) RelinquishMagickMemory(logmap);
2985       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2986         return(MagickFalse);
2987       return(status);
2988     }
2989     case LuvColorspace:
2990     {
2991       /*
2992         Transform image from Luv to sRGB.
2993       */
2994       if (image->storage_class == PseudoClass)
2995         {
2996           if (SyncImage(image,exception) == MagickFalse)
2997             return(MagickFalse);
2998           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2999             return(MagickFalse);
3000         }
3001       image_view=AcquireAuthenticCacheView(image,exception);
3002 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3003       #pragma omp parallel for schedule(static,4) shared(status) \
3004         dynamic_number_threads(image,image->columns,image->rows,1)
3005 #endif
3006       for (y=0; y < (ssize_t) image->rows; y++)
3007       {
3008         MagickBooleanType
3009           sync;
3010
3011         register ssize_t
3012           x;
3013
3014         register Quantum
3015           *restrict q;
3016
3017         if (status == MagickFalse)
3018           continue;
3019         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3020           exception);
3021         if (q == (Quantum *) NULL)
3022           {
3023             status=MagickFalse;
3024             continue;
3025           }
3026         for (x=0; x < (ssize_t) image->columns; x++)
3027         {
3028           double
3029             blue,
3030             green,
3031             L,
3032             red,
3033             u,
3034             v,
3035             X,
3036             Y,
3037             Z;
3038
3039           L=QuantumScale*GetPixelRed(image,q);
3040           u=QuantumScale*GetPixelGreen(image,q);
3041           v=QuantumScale*GetPixelBlue(image,q);
3042           ConvertLuvToXYZ(L,u,v,&X,&Y,&Z);
3043           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
3044           SetPixelRed(image,ClampToQuantum(EncodesRGBGamma(red)),q);
3045           SetPixelGreen(image,ClampToQuantum(EncodesRGBGamma(green)),q);
3046           SetPixelBlue(image,ClampToQuantum(EncodesRGBGamma(blue)),q);
3047           q+=GetPixelChannels(image);
3048         }
3049         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3050         if (sync == MagickFalse)
3051           status=MagickFalse;
3052       }
3053       image_view=DestroyCacheView(image_view);
3054       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3055         return(MagickFalse);
3056       return(status);
3057     }
3058     case RGBColorspace:
3059     {
3060       /*
3061         Transform linear RGB to sRGB colorspace.
3062       */
3063       if (image->storage_class == PseudoClass)
3064         {
3065           if (SyncImage(image,exception) == MagickFalse)
3066             return(MagickFalse);
3067           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3068             return(MagickFalse);
3069         }
3070       image_view=AcquireAuthenticCacheView(image,exception);
3071 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3072       #pragma omp parallel for schedule(static,4) shared(status) \
3073         dynamic_number_threads(image,image->columns,image->rows,1)
3074 #endif
3075       for (y=0; y < (ssize_t) image->rows; y++)
3076       {
3077         MagickBooleanType
3078           sync;
3079
3080         register ssize_t
3081           x;
3082
3083         register Quantum
3084           *restrict q;
3085
3086         if (status == MagickFalse)
3087           continue;
3088         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3089           exception);
3090         if (q == (Quantum *) NULL)
3091           {
3092             status=MagickFalse;
3093             continue;
3094           }
3095         for (x=(ssize_t) image->columns; x != 0; x--)
3096         {
3097           double
3098             blue,
3099             green,
3100             red;
3101
3102           red=EncodesRGBGamma((MagickRealType) GetPixelRed(image,q));
3103           green=EncodesRGBGamma((MagickRealType) GetPixelGreen(image,q));
3104           blue=EncodesRGBGamma((MagickRealType) GetPixelBlue(image,q));
3105           SetPixelRed(image,ClampToQuantum(red),q);
3106           SetPixelGreen(image,ClampToQuantum(green),q);
3107           SetPixelBlue(image,ClampToQuantum(blue),q);
3108           q+=GetPixelChannels(image);
3109         }
3110         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3111         if (sync == MagickFalse)
3112           status=MagickFalse;
3113       }
3114       image_view=DestroyCacheView(image_view);
3115       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3116         return(MagickFalse);
3117       return(status);
3118     }
3119     case XYZColorspace:
3120     {
3121       /*
3122         Transform image from XYZ to sRGB.
3123       */
3124       if (image->storage_class == PseudoClass)
3125         {
3126           if (SyncImage(image,exception) == MagickFalse)
3127             return(MagickFalse);
3128           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3129             return(MagickFalse);
3130         }
3131       image_view=AcquireAuthenticCacheView(image,exception);
3132 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3133       #pragma omp parallel for schedule(static,4) shared(status) \
3134         dynamic_number_threads(image,image->columns,image->rows,1)
3135 #endif
3136       for (y=0; y < (ssize_t) image->rows; y++)
3137       {
3138         MagickBooleanType
3139           sync;
3140
3141         register ssize_t
3142           x;
3143
3144         register Quantum
3145           *restrict q;
3146
3147         if (status == MagickFalse)
3148           continue;
3149         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3150           exception);
3151         if (q == (Quantum *) NULL)
3152           {
3153             status=MagickFalse;
3154             continue;
3155           }
3156         for (x=0; x < (ssize_t) image->columns; x++)
3157         {
3158           double
3159             blue,
3160             green,
3161             red,
3162             X,
3163             Y,
3164             Z;
3165
3166           X=QuantumScale*GetPixelRed(image,q);
3167           Y=QuantumScale*GetPixelGreen(image,q);
3168           Z=QuantumScale*GetPixelBlue(image,q);
3169           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
3170           SetPixelRed(image,ClampToQuantum(EncodesRGBGamma(red)),q);
3171           SetPixelGreen(image,ClampToQuantum(EncodesRGBGamma(green)),q);
3172           SetPixelBlue(image,ClampToQuantum(EncodesRGBGamma(blue)),q);
3173           q+=GetPixelChannels(image);
3174         }
3175         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3176         if (sync == MagickFalse)
3177           status=MagickFalse;
3178       }
3179       image_view=DestroyCacheView(image_view);
3180       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3181         return(MagickFalse);
3182       return(status);
3183     }
3184     default:
3185       break;
3186   }
3187   /*
3188     Allocate the tables.
3189   */
3190   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
3191     sizeof(*x_map));
3192   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
3193     sizeof(*y_map));
3194   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
3195     sizeof(*z_map));
3196   if ((x_map == (TransformPacket *) NULL) ||
3197       (y_map == (TransformPacket *) NULL) ||
3198       (z_map == (TransformPacket *) NULL))
3199     {
3200       if (z_map != (TransformPacket *) NULL)
3201         z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
3202       if (y_map != (TransformPacket *) NULL)
3203         y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
3204       if (x_map != (TransformPacket *) NULL)
3205         x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
3206       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3207         image->filename);
3208     }
3209   switch (image->colorspace)
3210   {
3211     case OHTAColorspace:
3212     {
3213       /*
3214         Initialize OHTA tables:
3215
3216           R = I1+1.00000*I2-0.66668*I3
3217           G = I1+0.00000*I2+1.33333*I3
3218           B = I1-1.00000*I2-0.66668*I3
3219
3220         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
3221         through QuantumRange.
3222       */
3223 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
3224       #pragma omp parallel for schedule(static,4) \
3225         dynamic_number_threads(image,image->columns,1,1)
3226 #endif
3227       for (i=0; i <= (ssize_t) MaxMap; i++)
3228       {
3229         x_map[i].x=(MagickRealType) (1.0f*(float) i);
3230         y_map[i].x=(MagickRealType) (0.5f*(2.0f*(float) i-MaxMap));
3231         z_map[i].x=(MagickRealType) ((-0.333340f)*(2.0f*(float) i-MaxMap));
3232         x_map[i].y=(MagickRealType) (1.0f*(float) i);
3233         y_map[i].y=(MagickRealType) 0.000000f;
3234         z_map[i].y=(MagickRealType) (0.666665f*(2.0f*(float) i-MaxMap));
3235         x_map[i].z=(MagickRealType) (1.0f*(float) i);
3236         y_map[i].z=(MagickRealType) (-0.500000f*(2.0f*(float) i-MaxMap));
3237         z_map[i].z=(MagickRealType) (-0.333340f*(2.0f*(float) i-MaxMap));
3238       }
3239       break;
3240     }
3241     case Rec601YCbCrColorspace:
3242     case YCbCrColorspace:
3243     {
3244       /*
3245         Initialize YCbCr tables:
3246
3247           R = Y            +1.402000*Cr
3248           G = Y-0.344136*Cb-0.714136*Cr
3249           B = Y+1.772000*Cb
3250
3251         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
3252         through QuantumRange.
3253       */
3254 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
3255       #pragma omp parallel for schedule(static,4) \
3256         dynamic_number_threads(image,image->columns,1,1)
3257 #endif
3258       for (i=0; i <= (ssize_t) MaxMap; i++)
3259       {
3260         x_map[i].x=0.99999999999914679361*i;
3261         y_map[i].x=(1.2188941887145875e-06)*i;
3262         z_map[i].x=0.5f*1.4019995886561440468*(2.00f*i-MaxMap);
3263         x_map[i].y=0.99999975910502514331*i;
3264         y_map[i].y=0.5f*(-0.34413567816504303521)*(2.00f*i-MaxMap);
3265         z_map[i].y=0.5f*(-0.71413649331646789076)*(2.00f*i-MaxMap);
3266         x_map[i].z=1.00000124040004623180*i;
3267         y_map[i].z=0.5f*1.77200006607230409200*(2.00f*i-MaxMap);
3268         z_map[i].z=2.1453384174593273e-06*i;
3269       }
3270       break;
3271     }
3272     case Rec709YCbCrColorspace:
3273     {
3274       /*
3275         Initialize YCbCr tables:
3276
3277           R = Y            +1.574800*Cr
3278           G = Y-0.187324*Cb-0.468124*Cr
3279           B = Y+1.855600*Cb
3280
3281         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
3282         through QuantumRange.
3283       */
3284 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
3285       #pragma omp parallel for schedule(static,4) \
3286         dynamic_number_threads(image,image->columns,1,1)
3287 #endif
3288       for (i=0; i <= (ssize_t) MaxMap; i++)
3289       {
3290         x_map[i].x=(MagickRealType) (1.0f*i);
3291         y_map[i].x=(MagickRealType) (0.000000f*(2.0f*i-MaxMap));
3292         z_map[i].x=(MagickRealType) (0.5f*1.574800f*(2.0f*i-MaxMap));
3293         x_map[i].y=(MagickRealType) (1.0f*i);
3294         y_map[i].y=(MagickRealType) (0.5f*(-0.187324f)*(2.0f*i-MaxMap));
3295         z_map[i].y=(MagickRealType) (0.5f*(-0.468124f)*(2.0f*i-MaxMap));
3296         x_map[i].z=(MagickRealType) (1.0f*i);
3297         y_map[i].z=(MagickRealType) (0.5f*1.855600f*(2.0f*i-MaxMap));
3298         z_map[i].z=(MagickRealType) (0.000000f*(2.0f*i-MaxMap));
3299       }
3300       break;
3301     }
3302     case YCCColorspace:
3303     {
3304       /*
3305         Initialize YCC tables:
3306
3307           R = Y            +1.340762*C2
3308           G = Y-0.317038*C1-0.682243*C2
3309           B = Y+1.632639*C1
3310
3311         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
3312       */
3313 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
3314       #pragma omp parallel for schedule(static,4) \
3315         dynamic_number_threads(image,image->columns,1,1)
3316 #endif
3317       for (i=0; i <= (ssize_t) MaxMap; i++)
3318       {
3319         x_map[i].x=(MagickRealType) (1.3584000f*(float) i);
3320         y_map[i].x=(MagickRealType) 0.0000000f;
3321         z_map[i].x=(MagickRealType) (1.8215000f*(1.0f*(float) i-(double)
3322           ScaleQuantumToMap(ScaleCharToQuantum(137))));
3323         x_map[i].y=(MagickRealType) (1.3584000f*(float) i);
3324         y_map[i].y=(MagickRealType) (-0.4302726f*(1.0f*(float) i-(double)
3325           ScaleQuantumToMap(ScaleCharToQuantum(156))));
3326         z_map[i].y=(MagickRealType) (-0.9271435f*(1.0f*(float) i-(double)
3327           ScaleQuantumToMap(ScaleCharToQuantum(137))));
3328         x_map[i].z=(MagickRealType) (1.3584000f*(float) i);
3329         y_map[i].z=(MagickRealType) (2.2179000f*(1.0f*(float) i-(double)
3330           ScaleQuantumToMap(ScaleCharToQuantum(156))));
3331         z_map[i].z=(MagickRealType) 0.0000000f;
3332       }
3333       break;
3334     }
3335     case YIQColorspace:
3336     {
3337       /*
3338         Initialize YIQ tables:
3339
3340           R = Y+0.95620*I+0.62140*Q
3341           G = Y-0.27270*I-0.64680*Q
3342           B = Y-1.10370*I+1.70060*Q
3343
3344         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
3345         through QuantumRange.
3346       */
3347 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
3348       #pragma omp parallel for schedule(static,4) \
3349         dynamic_number_threads(image,image->columns,1,1)
3350 #endif
3351       for (i=0; i <= (ssize_t) MaxMap; i++)
3352       {
3353         x_map[i].x=1.0f*i;
3354         y_map[i].x=0.5f*0.9562957197589482261*(2.00000f*i-MaxMap);
3355         z_map[i].x=0.5f*0.6210244164652610754*(2.00000f*i-MaxMap);
3356         x_map[i].y=1.0f*i;
3357         y_map[i].y=0.5f*(-0.2721220993185104464)*(2.00000f*i-MaxMap);
3358         z_map[i].y=0.5f*(-0.6473805968256950427)*(2.00000f*i-MaxMap);
3359         x_map[i].z=1.0f*i;
3360         y_map[i].z=0.5f*(-1.1069890167364901945)*(2.00000f*i-MaxMap);
3361         z_map[i].z=0.5f*1.7046149983646481374*(2.00000f*i-MaxMap);
3362       }
3363       break;
3364     }
3365     case YPbPrColorspace:
3366     {
3367       /*
3368         Initialize YPbPr tables:
3369
3370           R = Y            +1.402000*C2
3371           G = Y-0.344136*C1+0.714136*C2
3372           B = Y+1.772000*C1
3373
3374         Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
3375         through QuantumRange.
3376       */
3377 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
3378       #pragma omp parallel for schedule(static,4) \
3379         dynamic_number_threads(image,image->columns,1,1)
3380 #endif
3381       for (i=0; i <= (ssize_t) MaxMap; i++)
3382       {
3383         x_map[i].x=0.99999999999914679361*i;
3384         y_map[i].x=(-1.2188941887145875e-06)*(2.0f*i-MaxMap);
3385         z_map[i].x=0.5f*1.4019995886561440468*(2.0f*i-MaxMap);
3386         x_map[i].y=0.99999975910502514331*i;
3387         y_map[i].y=0.5f*(-0.34413567816504303521)*(2.0f*i-MaxMap);
3388         z_map[i].y=0.5f*(-0.71413649331646789076)*(2.0f*i-MaxMap);
3389         x_map[i].z=1.00000124040004623180*i;
3390         y_map[i].z=0.5f*1.77200006607230409200*(2.0f*i-MaxMap);
3391         z_map[i].z=2.1453384174593273e-06*(2.0f*i-MaxMap);
3392       }
3393       break;
3394     }
3395     case YUVColorspace:
3396     {
3397       /*
3398         Initialize YUV tables:
3399
3400           R = Y         +1.13983*V
3401           G = Y-0.39464*U-0.58060*V
3402           B = Y+2.03211*U
3403
3404         U and V, normally -0.5 through 0.5, must be normalized to the range 0
3405         through QuantumRange.
3406       */
3407 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
3408       #pragma omp parallel for schedule(static,4) \
3409         dynamic_number_threads(image,image->columns,1,1)
3410 #endif
3411       for (i=0; i <= (ssize_t) MaxMap; i++)
3412       {
3413         x_map[i].x=1.0f*i;
3414         y_map[i].x=(-3.945707070708279e-05)*(2.0f*i-MaxMap);
3415         z_map[i].x=0.5f*1.1398279671717170825*(2.0f*i-MaxMap);
3416         x_map[i].y=1.0f*i;
3417         y_map[i].y=0.5f*(-0.3946101641414141437)*(2.0f*i-MaxMap);
3418         z_map[i].y=0.5f*(-0.5805003156565656797)*(2.0f*i-MaxMap);
3419         x_map[i].z=1.0f*i;
3420         y_map[i].z=0.5f*2.0319996843434342537*(2.0f*i-MaxMap);
3421         z_map[i].z=(-4.813762626262513e-04)*(2.0f*i-MaxMap);
3422       }
3423       break;
3424     }
3425     default:
3426     {
3427       /*
3428         Linear conversion tables.
3429       */
3430 #if defined(MAGICKCORE_OPENMP_SUPPORT) && defined(NoBenefitFromParallelism)
3431       #pragma omp parallel for schedule(static,4) \
3432         dynamic_number_threads(image,image->columns,1,1)
3433 #endif
3434       for (i=0; i <= (ssize_t) MaxMap; i++)
3435       {
3436         x_map[i].x=(MagickRealType) (1.0*(float) i);
3437         y_map[i].x=(MagickRealType) 0.0;
3438         z_map[i].x=(MagickRealType) 0.0;
3439         x_map[i].y=(MagickRealType) 0.0;
3440         y_map[i].y=(MagickRealType) (1.0*(float) i);
3441         z_map[i].y=(MagickRealType) 0.0;
3442         x_map[i].z=(MagickRealType) 0.0;
3443         y_map[i].z=(MagickRealType) 0.0;
3444         z_map[i].z=(MagickRealType) (1.0*(float) i);
3445       }
3446       break;
3447     }
3448   }
3449   /*
3450     Convert to sRGB.
3451   */
3452   switch (image->storage_class)
3453   {
3454     case DirectClass:
3455     default:
3456     {
3457       /*
3458         Convert DirectClass image.
3459       */
3460       image_view=AcquireAuthenticCacheView(image,exception);
3461 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3462       #pragma omp parallel for schedule(static,4) shared(status) \
3463         dynamic_number_threads(image,image->columns,image->rows,1)
3464 #endif
3465       for (y=0; y < (ssize_t) image->rows; y++)
3466       {
3467         MagickBooleanType
3468           sync;
3469
3470         PixelInfo
3471           pixel;
3472
3473         register ssize_t
3474           x;
3475
3476         register Quantum
3477           *restrict q;
3478
3479         if (status == MagickFalse)
3480           continue;
3481         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3482           exception);
3483         if (q == (Quantum *) NULL)
3484           {
3485             status=MagickFalse;
3486             continue;
3487           }
3488         for (x=0; x < (ssize_t) image->columns; x++)
3489         {
3490           register size_t
3491             blue,
3492             green,
3493             red;
3494
3495           red=ScaleQuantumToMap(GetPixelRed(image,q));
3496           green=ScaleQuantumToMap(GetPixelGreen(image,q));
3497           blue=ScaleQuantumToMap(GetPixelBlue(image,q));
3498           pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
3499           pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
3500           pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
3501           if (image->colorspace == YCCColorspace)
3502             {
3503               pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.red/
3504                 (double) MaxMap)];
3505               pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.green/
3506                 (double) MaxMap)];
3507               pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.blue/
3508                 (double) MaxMap)];
3509             }
3510           else
3511             {
3512               pixel.red=EncodesRGBGamma((MagickRealType)
3513                 ScaleMapToQuantum(pixel.red));
3514               pixel.green=EncodesRGBGamma((MagickRealType)
3515                 ScaleMapToQuantum(pixel.green));
3516               pixel.blue=EncodesRGBGamma((MagickRealType)
3517                 ScaleMapToQuantum(pixel.blue));
3518             }
3519           SetPixelRed(image,ClampToQuantum(pixel.red),q);
3520           SetPixelGreen(image,ClampToQuantum(pixel.green),q);
3521           SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
3522           q+=GetPixelChannels(image);
3523         }
3524         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3525         if (sync == MagickFalse)
3526           status=MagickFalse;
3527         if (image->progress_monitor != (MagickProgressMonitor) NULL)
3528           {
3529             MagickBooleanType
3530               proceed;
3531
3532 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3533             #pragma omp critical (MagickCore_TransformsRGBImage)
3534 #endif
3535             proceed=SetImageProgress(image,TransformsRGBImageTag,progress++,
3536               image->rows);
3537             if (proceed == MagickFalse)
3538               status=MagickFalse;
3539           }
3540       }
3541       image_view=DestroyCacheView(image_view);
3542       break;
3543     }
3544     case PseudoClass:
3545     {
3546       /*
3547         Convert PseudoClass image.
3548       */
3549 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3550       #pragma omp parallel for schedule(static,4) shared(status) \
3551         dynamic_number_threads(image,image->columns,1,1)
3552 #endif
3553       for (i=0; i < (ssize_t) image->colors; i++)
3554       {
3555         PixelInfo
3556           pixel;
3557
3558         register size_t
3559           blue,
3560           green,
3561           red;
3562
3563         red=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red));
3564         green=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green));
3565         blue=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue));
3566         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
3567         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
3568         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
3569         if (image->colorspace == YCCColorspace)
3570           {
3571             pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.red/
3572               (double) MaxMap)];
3573             pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.green/
3574               (double) MaxMap)];
3575             pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0f*pixel.blue/
3576               (double) MaxMap)];
3577           }
3578         else
3579           {
3580             pixel.red=EncodesRGBGamma((MagickRealType)
3581               ScaleMapToQuantum(pixel.red));
3582             pixel.green=EncodesRGBGamma((MagickRealType)
3583               ScaleMapToQuantum(pixel.green));
3584             pixel.blue=EncodesRGBGamma((MagickRealType)
3585               ScaleMapToQuantum(pixel.blue));
3586           }
3587         image->colormap[i].red=(double) ClampToQuantum(pixel.red);
3588         image->colormap[i].green=(double) ClampToQuantum(pixel.green);
3589         image->colormap[i].blue=(double) ClampToQuantum(pixel.blue);
3590       }
3591       (void) SyncImage(image,exception);
3592       break;
3593     }
3594   }
3595   /*
3596     Relinquish resources.
3597   */
3598   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
3599   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
3600   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
3601   if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3602     return(MagickFalse);
3603   return(MagickTrue);
3604 }